Commit 7476e371 authored by Tom Lane's avatar Tom Lane

Assign a typmod of -1 to unadorned CHAR and NUMERIC type specs. This

allows casts without specific length requirements to continue to work
as they did before; that is, x::char will not truncate the value of x,
whereas x::char(1) will.  Likewise for NUMERIC precision/scale.
The column length defaults of char(1) and numeric(30,6) are now inserted
in analyze.c's processing of CREATE TABLE.
parent 08195a43
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: analyze.c,v 1.130 2000/01/16 08:21:59 tgl Exp $ * $Id: analyze.c,v 1.131 2000/01/20 02:24:50 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -23,7 +23,11 @@ ...@@ -23,7 +23,11 @@
#include "parser/parse_clause.h" #include "parser/parse_clause.h"
#include "parser/parse_relation.h" #include "parser/parse_relation.h"
#include "parser/parse_target.h" #include "parser/parse_target.h"
#include "parser/parse_type.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/numeric.h"
void CheckSelectForUpdate(Query *qry); /* no points for style... */
static Query *transformStmt(ParseState *pstate, Node *stmt); static Query *transformStmt(ParseState *pstate, Node *stmt);
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt); static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
...@@ -38,7 +42,7 @@ static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt); ...@@ -38,7 +42,7 @@ static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
static void transformForUpdate(Query *qry, List *forUpdate); static void transformForUpdate(Query *qry, List *forUpdate);
static void transformFkeyGetPrimaryKey(FkConstraint *fkconstraint); static void transformFkeyGetPrimaryKey(FkConstraint *fkconstraint);
void CheckSelectForUpdate(Query *qry); static void transformColumnType(ParseState *pstate, ColumnDef *column);
/* kluge to return extra info from transformCreateStmt() */ /* kluge to return extra info from transformCreateStmt() */
static List *extras_before; static List *extras_before;
...@@ -601,6 +605,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) ...@@ -601,6 +605,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
column = (ColumnDef *) element; column = (ColumnDef *) element;
columns = lappend(columns, column); columns = lappend(columns, column);
transformColumnType(pstate, column);
/* Special case SERIAL type? */ /* Special case SERIAL type? */
if (column->is_sequence) if (column->is_sequence)
{ {
...@@ -1701,4 +1707,31 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint) ...@@ -1701,4 +1707,31 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint)
heap_close(pkrel, AccessShareLock); heap_close(pkrel, AccessShareLock);
} }
/*
* Special handling of type definition for a column
*/
static void
transformColumnType(ParseState *pstate, ColumnDef *column)
{
/*
* If the column doesn't have an explicitly specified typmod,
* check to see if we want to insert a default length.
*
* Note that we deliberately do NOT look at array or set information
* here; "numeric[]" needs the same default typmod as "numeric".
*/
if (column->typename->typmod == -1)
{
switch (typeTypeId(typenameType(column->typename->name)))
{
case BPCHAROID:
/* "char" -> "char(1)" */
column->typename->typmod = VARHDRSZ + 1;
break;
case NUMERICOID:
column->typename->typmod = VARHDRSZ +
((NUMERIC_DEFAULT_PRECISION<<16) | NUMERIC_DEFAULT_SCALE);
break;
}
}
}
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.131 2000/01/18 23:30:20 petere Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.132 2000/01/20 02:24:50 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -1032,6 +1032,7 @@ columnDef: ColId Typename ColConstraintList ...@@ -1032,6 +1032,7 @@ columnDef: ColId Typename ColConstraintList
n->colname = $1; n->colname = $1;
n->typename = makeNode(TypeName); n->typename = makeNode(TypeName);
n->typename->name = xlateSqlType("integer"); n->typename->name = xlateSqlType("integer");
n->typename->typmod = -1;
n->raw_default = NULL; n->raw_default = NULL;
n->cooked_default = NULL; n->cooked_default = NULL;
n->is_not_null = TRUE; n->is_not_null = TRUE;
...@@ -2280,6 +2281,7 @@ func_return: set_opt TypeId ...@@ -2280,6 +2281,7 @@ func_return: set_opt TypeId
n->name = $2; n->name = $2;
n->setof = $1; n->setof = $1;
n->arrayBounds = NULL; n->arrayBounds = NULL;
n->typmod = -1;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
...@@ -3643,12 +3645,13 @@ Numeric: FLOAT opt_float ...@@ -3643,12 +3645,13 @@ Numeric: FLOAT opt_float
| DOUBLE PRECISION | DOUBLE PRECISION
{ {
$$ = makeNode(TypeName); $$ = makeNode(TypeName);
$$->name = xlateSqlType("float"); $$->name = xlateSqlType("float8");
$$->typmod = -1;
} }
| DECIMAL opt_decimal | DECIMAL opt_decimal
{ {
$$ = makeNode(TypeName); $$ = makeNode(TypeName);
$$->name = xlateSqlType("numeric"); $$->name = xlateSqlType("decimal");
$$->typmod = $2; $$->typmod = $2;
} }
| NUMERIC opt_numeric | NUMERIC opt_numeric
...@@ -3664,7 +3667,7 @@ numeric: FLOAT ...@@ -3664,7 +3667,7 @@ numeric: FLOAT
| DOUBLE PRECISION | DOUBLE PRECISION
{ $$ = xlateSqlType("float8"); } { $$ = xlateSqlType("float8"); }
| DECIMAL | DECIMAL
{ $$ = xlateSqlType("numeric"); } { $$ = xlateSqlType("decimal"); }
| NUMERIC | NUMERIC
{ $$ = xlateSqlType("numeric"); } { $$ = xlateSqlType("numeric"); }
; ;
...@@ -3707,7 +3710,8 @@ opt_numeric: '(' Iconst ',' Iconst ')' ...@@ -3707,7 +3710,8 @@ opt_numeric: '(' Iconst ',' Iconst ')'
} }
| /*EMPTY*/ | /*EMPTY*/
{ {
$$ = ((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE) + VARHDRSZ; /* Insert "-1" meaning "default"; may be replaced later */
$$ = -1;
} }
; ;
...@@ -3732,53 +3736,39 @@ opt_decimal: '(' Iconst ',' Iconst ')' ...@@ -3732,53 +3736,39 @@ opt_decimal: '(' Iconst ',' Iconst ')'
} }
| /*EMPTY*/ | /*EMPTY*/
{ {
$$ = ((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE) + VARHDRSZ; /* Insert "-1" meaning "default"; may be replaced later */
$$ = -1;
} }
; ;
/* SQL92 character data types /*
* SQL92 character data types
* The following implements CHAR() and VARCHAR(). * The following implements CHAR() and VARCHAR().
*/ */
Character: character '(' Iconst ')' Character: character '(' Iconst ')'
{ {
$$ = makeNode(TypeName); $$ = makeNode(TypeName);
if (strcasecmp($1, "char") == 0) $$->name = xlateSqlType($1);
$$->name = xlateSqlType("bpchar");
else if (strcasecmp($1, "varchar") == 0)
$$->name = xlateSqlType("varchar");
else
yyerror("internal parsing error; unrecognized character type");
if ($3 < 1) if ($3 < 1)
elog(ERROR,"length for '%s' type must be at least 1",$1); elog(ERROR,"length for type '%s' must be at least 1",$1);
else if ($3 > MaxAttrSize) else if ($3 > MaxAttrSize)
elog(ERROR,"length for type '%s' cannot exceed %ld",$1, elog(ERROR,"length for type '%s' cannot exceed %ld",$1,
MaxAttrSize); MaxAttrSize);
/* we actually implement this sort of like a varlen, so /* we actually implement these like a varlen, so
* the first 4 bytes is the length. (the difference * the first 4 bytes is the length. (the difference
* between this and "text" is that we blank-pad and * between these and "text" is that we blank-pad and
* truncate where necessary * truncate where necessary)
*/ */
$$->typmod = VARHDRSZ + $3; $$->typmod = VARHDRSZ + $3;
} }
| character | character
{ {
$$ = makeNode(TypeName); $$ = makeNode(TypeName);
/* Let's try to make all single-character types into bpchar(1) $$->name = xlateSqlType($1);
* - thomas 1998-05-07 /* default length, if needed, will be inserted later */
*/ $$->typmod = -1;
if (strcasecmp($1, "char") == 0)
{
$$->name = xlateSqlType("bpchar");
$$->typmod = VARHDRSZ + 1;
}
else
{
$$->name = xlateSqlType($1);
$$->typmod = -1;
}
} }
; ;
...@@ -5131,6 +5121,7 @@ ColLabel: ColId { $$ = $1; } ...@@ -5131,6 +5121,7 @@ ColLabel: ColId { $$ = $1; }
| EXPLAIN { $$ = "explain"; } | EXPLAIN { $$ = "explain"; }
| EXTEND { $$ = "extend"; } | EXTEND { $$ = "extend"; }
| FALSE_P { $$ = "false"; } | FALSE_P { $$ = "false"; }
| FLOAT { $$ = "float"; }
| FOREIGN { $$ = "foreign"; } | FOREIGN { $$ = "foreign"; }
| GLOBAL { $$ = "global"; } | GLOBAL { $$ = "global"; }
| GROUP { $$ = "group"; } | GROUP { $$ = "group"; }
...@@ -5314,6 +5305,10 @@ xlateSqlType(char *name) ...@@ -5314,6 +5305,10 @@ xlateSqlType(char *name)
else if (!strcasecmp(name, "real") else if (!strcasecmp(name, "real")
|| !strcasecmp(name, "float")) || !strcasecmp(name, "float"))
return "float8"; return "float8";
else if (!strcasecmp(name, "decimal"))
return "numeric";
else if (!strcasecmp(name, "char"))
return "bpchar";
else if (!strcasecmp(name, "interval")) else if (!strcasecmp(name, "interval"))
return "timespan"; return "timespan";
else if (!strcasecmp(name, "boolean")) else if (!strcasecmp(name, "boolean"))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment