diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 650f490566d7a74bc780a7b740914520a8fc3fba..8e1dc4a4efeb7b88edb8fb1bb591b0e4a8ac4ab4 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 1.49 1997/09/24 08:31:04 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.50 1997/09/24 17:53:53 thomas Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -232,7 +232,9 @@ static char *FlattenStringList(List *list); %token BOTH, LEADING, TRAILING, %token EXTRACT, POSITION, SUBSTRING, TRIM %token DOUBLE, PRECISION, FLOAT +%token DECIMAL, NUMERIC %token CHARACTER, VARYING +%token CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP /* Special keywords, not in the query language - see the "lex" file */ %token <str> IDENT, SCONST, Op @@ -2339,6 +2341,10 @@ typname: txname if (!strcasecmp($1, "float")) tname = xlateSqlType("float8"); + else if (!strcasecmp($1, "decimal")) + tname = xlateSqlType("integer"); + else if (!strcasecmp($1, "numeric")) + tname = xlateSqlType("integer"); else tname = xlateSqlType($1); $$->name = tname; @@ -2375,6 +2381,8 @@ txname: Id { $$ = $1; } | CHARACTER char_type { $$ = $2; } | DOUBLE PRECISION { $$ = xlateSqlType("float8"); } | FLOAT { $$ = xlateSqlType("float"); } + | DECIMAL { $$ = "decimal"; } + | NUMERIC { $$ = "numeric"; } ; char_type: VARYING { $$ = xlateSqlType("varchar"); } @@ -2400,8 +2408,10 @@ Typename: typname opt_array_bounds { $$ = $1; $$->arrayBounds = $2; +#if FALSE if (!strcasecmp($1->name, "varchar")) $$->typlen = 4 + 1; +#endif } | txname '(' Iconst ')' { @@ -2410,19 +2420,32 @@ Typename: typname opt_array_bounds * We do it here instead of the 'typname:' production * because we don't want to allow arrays of VARCHAR(). * I haven't thought about whether that will work or not. - * - ay 6/95 - * Also implements FLOAT() - thomas 1997-09-18 + * - ay 6/95 + * Also implements FLOAT(). + * Check precision limits assuming IEEE floating types. + * - thomas 1997-09-18 */ $$ = makeNode(TypeName); if (!strcasecmp($1, "float")) { if ($3 < 1) - elog(WARN,"precision for '%s' type must be at least 1",$1); - else if ($3 <= 7) + elog(WARN,"precision for FLOAT must be at least 1",NULL); + else if ($3 < 7) $$->name = xlateSqlType("float4"); - else if ($3 < 14) + else if ($3 < 16) $$->name = xlateSqlType("float8"); else - elog(WARN,"precision for '%s' type must be less than 14",$1); + elog(WARN,"precision for FLOAT must be less than 16",NULL); + } else if (!strcasecmp($1, "decimal")) { + /* DECIMAL is allowed to have more precision than specified */ + if ($3 > 9) + elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3); + $$->name = xlateSqlType("integer"); + + } else if (!strcasecmp($1, "numeric")) { + /* integer holds 9.33 decimal places, so assume an even 9 for now */ + if ($3 != 9) + elog(WARN,"NUMERIC precision %d must be 9",$3); + $$->name = xlateSqlType("integer"); } else { if (!strcasecmp($1, "char")) @@ -2449,6 +2472,28 @@ Typename: typname opt_array_bounds $$->typlen = 4 + $3; } } + | txname '(' Iconst ',' Iconst ')' + { + $$ = makeNode(TypeName); + if (!strcasecmp($1, "decimal")) { + if ($3 > 9) + elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3); + if ($5 != 0) + elog(WARN,"DECIMAL scale %d must be zero",$5); + $$->name = xlateSqlType("integer"); + + } else if (!strcasecmp($1, "numeric")) { + if ($3 != 9) + elog(WARN,"NUMERIC precision %d must be 9",$3); + if ($5 != 0) + elog(WARN,"NUMERIC scale %d must be zero",$5); + $$->name = xlateSqlType("integer"); + + } else { + elog(WARN,"%s(%d,%d) not implemented",$1,$3,$5); + } + $$->name = xlateSqlType("integer"); + } ; @@ -2550,6 +2595,88 @@ a_expr: attr opt_indirection FuncCall *n = makeNode(FuncCall); n->funcname = $1; n->args = NIL; + $$ = (Node *)n; + } + | CURRENT_DATE + { + A_Const *n = makeNode(A_Const); + TypeName *t = makeNode(TypeName); + + n->val.type = T_String; + n->val.val.str = "now"; + n->typename = t; + + t->name = xlateSqlType("date"); + t->setof = FALSE; + + $$ = (Node *)n; + } + | CURRENT_TIME + { + A_Const *n = makeNode(A_Const); + TypeName *t = makeNode(TypeName); + + n->val.type = T_String; + n->val.val.str = "now"; + n->typename = t; + + t->name = xlateSqlType("time"); + t->setof = FALSE; + + $$ = (Node *)n; + } + | CURRENT_TIME '(' AexprConst ')' + { + FuncCall *n = makeNode(FuncCall); + A_Const *s = makeNode(A_Const); + TypeName *t = makeNode(TypeName); + + n->funcname = xlateSqlType("time"); + n->args = lcons(s, NIL); + + s->val.type = T_String; + s->val.val.str = "now"; + s->typename = t; + + t->name = xlateSqlType("time"); + t->setof = FALSE; + + elog(NOTICE,"CURRENT_TIME(p) precision not implemented",NULL); + + $$ = (Node *)n; + } + | CURRENT_TIMESTAMP + { + A_Const *n = makeNode(A_Const); + TypeName *t = makeNode(TypeName); + + n->val.type = T_String; + n->val.val.str = "now"; + n->typename = t; + + t->name = xlateSqlType("timestamp"); + t->setof = FALSE; + + $$ = (Node *)n; + } + | CURRENT_TIMESTAMP '(' AexprConst ')' + { + FuncCall *n = makeNode(FuncCall); + A_Const *s = makeNode(A_Const); + TypeName *t = makeNode(TypeName); + + n->funcname = xlateSqlType("timestamp"); + n->args = lcons(s, NIL); + + s->val.type = T_String; + s->val.val.str = "now"; + s->typename = t; + + t->name = xlateSqlType("timestamp"); + t->setof = FALSE; + + elog(NOTICE,"CURRENT_TIMESTAMP(p) precision not implemented",NULL); + $$ = (Node *)n; } /* We probably need to define an "exists" node, @@ -3022,7 +3149,10 @@ access_method: Id { $$ = $1; }; attr_name: ColId { $$ = $1; }; class: Id { $$ = $1; }; index_name: Id { $$ = $1; }; -name: Id { $$ = $1; }; + +name: Id { $$ = $1; } + | TIME { $$ = xlateSqlType("time"); } + ; date: Sconst { $$ = $1; }; file_name: Sconst { $$ = $1; }; @@ -3138,6 +3268,8 @@ void parser_init(Oid *typev, int nargs) /* FlattenStringList() * Traverse list of string nodes and convert to a single string. * Used for reconstructing string form of complex expressions. + * + * Allocate at least one byte for terminator. */ static char * FlattenStringList(List *list) @@ -3145,7 +3277,7 @@ FlattenStringList(List *list) List *l, *lp; char *s; char *sp; - int nlist, len = 1; + int nlist, len = 0; nlist = length(list); #ifdef PARSEDEBUG @@ -3157,12 +3289,13 @@ printf( "list has %d elements\n", nlist); sp = (char *)(lp->elem.ptr_value); l = lnext(l); #ifdef PARSEDEBUG -printf( "length of %s is %d\n", sp, strlen(sp)); +printf( "sp is x%8p; length of %s is %d\n", sp, sp, strlen(sp)); #endif - len += strlen(sp)+1; + len += strlen(sp); }; + len += nlist; - s = (char*) palloc(len); + s = (char*) palloc(len+1); *s = '\0'; l = list; @@ -3174,9 +3307,9 @@ printf( "length of %s is %d\n", sp, strlen(sp)); printf( "length of %s is %d\n", sp, strlen(sp)); #endif strcat(s,sp); - strcat(s," "); + if (l != NIL) strcat(s," "); }; - *(s+len-2) = '\0'; + *(s+len) = '\0'; #ifdef PARSEDEBUG printf( "flattened string is \"%s\"\n", s);