From 7476e3718b038f563d39ea7f108fbff156275c94 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 20 Jan 2000 02:24:50 +0000 Subject: [PATCH] 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. --- src/backend/parser/analyze.c | 39 ++++++++++++++++++++++-- src/backend/parser/gram.y | 57 ++++++++++++++++-------------------- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 0dd1e9907a..a4c2dd7eff 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -5,7 +5,7 @@ * * 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 @@ #include "parser/parse_clause.h" #include "parser/parse_relation.h" #include "parser/parse_target.h" +#include "parser/parse_type.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 *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt); @@ -38,7 +42,7 @@ static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt); static void transformForUpdate(Query *qry, List *forUpdate); static void transformFkeyGetPrimaryKey(FkConstraint *fkconstraint); -void CheckSelectForUpdate(Query *qry); +static void transformColumnType(ParseState *pstate, ColumnDef *column); /* kluge to return extra info from transformCreateStmt() */ static List *extras_before; @@ -601,6 +605,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) column = (ColumnDef *) element; columns = lappend(columns, column); + transformColumnType(pstate, column); + /* Special case SERIAL type? */ if (column->is_sequence) { @@ -1701,4 +1707,31 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint) 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; + } + } +} diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index d62f3ef61c..ca22fc095f 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -10,7 +10,7 @@ * * * 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 * AUTHOR DATE MAJOR EVENT @@ -1032,6 +1032,7 @@ columnDef: ColId Typename ColConstraintList n->colname = $1; n->typename = makeNode(TypeName); n->typename->name = xlateSqlType("integer"); + n->typename->typmod = -1; n->raw_default = NULL; n->cooked_default = NULL; n->is_not_null = TRUE; @@ -2280,6 +2281,7 @@ func_return: set_opt TypeId n->name = $2; n->setof = $1; n->arrayBounds = NULL; + n->typmod = -1; $$ = (Node *)n; } ; @@ -3643,12 +3645,13 @@ Numeric: FLOAT opt_float | DOUBLE PRECISION { $$ = makeNode(TypeName); - $$->name = xlateSqlType("float"); + $$->name = xlateSqlType("float8"); + $$->typmod = -1; } | DECIMAL opt_decimal { $$ = makeNode(TypeName); - $$->name = xlateSqlType("numeric"); + $$->name = xlateSqlType("decimal"); $$->typmod = $2; } | NUMERIC opt_numeric @@ -3664,7 +3667,7 @@ numeric: FLOAT | DOUBLE PRECISION { $$ = xlateSqlType("float8"); } | DECIMAL - { $$ = xlateSqlType("numeric"); } + { $$ = xlateSqlType("decimal"); } | NUMERIC { $$ = xlateSqlType("numeric"); } ; @@ -3707,7 +3710,8 @@ opt_numeric: '(' Iconst ',' Iconst ')' } | /*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 ')' } | /*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(). */ Character: character '(' Iconst ')' { $$ = makeNode(TypeName); - if (strcasecmp($1, "char") == 0) - $$->name = xlateSqlType("bpchar"); - else if (strcasecmp($1, "varchar") == 0) - $$->name = xlateSqlType("varchar"); - else - yyerror("internal parsing error; unrecognized character type"); - + $$->name = xlateSqlType($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) elog(ERROR,"length for type '%s' cannot exceed %ld",$1, 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 - * between this and "text" is that we blank-pad and - * truncate where necessary + * between these and "text" is that we blank-pad and + * truncate where necessary) */ $$->typmod = VARHDRSZ + $3; } | character { $$ = makeNode(TypeName); - /* Let's try to make all single-character types into bpchar(1) - * - thomas 1998-05-07 - */ - if (strcasecmp($1, "char") == 0) - { - $$->name = xlateSqlType("bpchar"); - $$->typmod = VARHDRSZ + 1; - } - else - { - $$->name = xlateSqlType($1); - $$->typmod = -1; - } + $$->name = xlateSqlType($1); + /* default length, if needed, will be inserted later */ + $$->typmod = -1; } ; @@ -5131,6 +5121,7 @@ ColLabel: ColId { $$ = $1; } | EXPLAIN { $$ = "explain"; } | EXTEND { $$ = "extend"; } | FALSE_P { $$ = "false"; } + | FLOAT { $$ = "float"; } | FOREIGN { $$ = "foreign"; } | GLOBAL { $$ = "global"; } | GROUP { $$ = "group"; } @@ -5314,6 +5305,10 @@ xlateSqlType(char *name) else if (!strcasecmp(name, "real") || !strcasecmp(name, "float")) return "float8"; + else if (!strcasecmp(name, "decimal")) + return "numeric"; + else if (!strcasecmp(name, "char")) + return "bpchar"; else if (!strcasecmp(name, "interval")) return "timespan"; else if (!strcasecmp(name, "boolean"))