1010 *
1111 *
1212 * IDENTIFICATION
13- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.49 1997/09/2408:31:04 vadim Exp $
13+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.50 1997/09/2417:53:53 thomas Exp $
1414 *
1515 * HISTORY
1616 * AUTHORDATEMAJOR EVENT
@@ -232,7 +232,9 @@ static char *FlattenStringList(List *list);
232232%tokenBOTH, LEADING, TRAILING,
233233%tokenEXTRACT, POSITION, SUBSTRING, TRIM
234234%tokenDOUBLE, PRECISION, FLOAT
235+ %tokenDECIMAL, NUMERIC
235236%tokenCHARACTER, VARYING
237+ %tokenCURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP
236238
237239/* Special keywords, not in the query language - see the "lex" file */
238240%token <str>IDENT, SCONST, Op
@@ -2339,6 +2341,10 @@ typname: txname
23392341
23402342if (!strcasecmp($1, "float"))
23412343tname = xlateSqlType("float8");
2344+ else if (!strcasecmp($1, "decimal"))
2345+ tname = xlateSqlType("integer");
2346+ else if (!strcasecmp($1, "numeric"))
2347+ tname = xlateSqlType("integer");
23422348else
23432349tname = xlateSqlType($1);
23442350$$->name = tname;
@@ -2375,6 +2381,8 @@ txname: Id{ $$ = $1; }
23752381| CHARACTER char_type{ $$ = $2; }
23762382| DOUBLE PRECISION{ $$ = xlateSqlType("float8"); }
23772383| FLOAT{ $$ = xlateSqlType("float"); }
2384+ | DECIMAL{ $$ = "decimal"; }
2385+ | NUMERIC{ $$ = "numeric"; }
23782386;
23792387
23802388char_type: VARYING{ $$ = xlateSqlType("varchar"); }
@@ -2400,8 +2408,10 @@ Typename: typname opt_array_bounds
24002408{
24012409$$ = $1;
24022410$$->arrayBounds = $2;
2411+ #if FALSE
24032412if (!strcasecmp($1->name, "varchar"))
24042413$$->typlen = 4 + 1;
2414+ #endif
24052415}
24062416| txname '(' Iconst ')'
24072417{
@@ -2410,19 +2420,32 @@ Typename: typname opt_array_bounds
24102420 * We do it here instead of the 'typname:' production
24112421 * because we don't want to allow arrays of VARCHAR().
24122422 * I haven't thought about whether that will work or not.
2413- * - ay 6/95
2414- * Also implements FLOAT() - thomas 1997-09-18
2423+ *- ay 6/95
2424+ * Also implements FLOAT().
2425+ * Check precision limits assuming IEEE floating types.
2426+ *- thomas 1997-09-18
24152427 */
24162428$$ = makeNode(TypeName);
24172429if (!strcasecmp($1, "float")) {
24182430if ($3 < 1)
2419- elog(WARN,"precision for'%s' type must be at least 1",$1 );
2420- else if ($3 <= 7)
2431+ elog(WARN,"precision forFLOAT must be at least 1",NULL );
2432+ else if ($3 < 7)
24212433$$->name = xlateSqlType("float4");
2422- else if ($3 <14 )
2434+ else if ($3 <16 )
24232435$$->name = xlateSqlType("float8");
24242436else
2425- elog(WARN,"precision for '%s' type must be less than 14",$1);
2437+ elog(WARN,"precision for FLOAT must be less than 16",NULL);
2438+ } else if (!strcasecmp($1, "decimal")) {
2439+ /* DECIMAL is allowed to have more precision than specified */
2440+ if ($3 > 9)
2441+ elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3);
2442+ $$->name = xlateSqlType("integer");
2443+
2444+ } else if (!strcasecmp($1, "numeric")) {
2445+ /* integer holds 9.33 decimal places, so assume an even 9 for now */
2446+ if ($3 != 9)
2447+ elog(WARN,"NUMERIC precision %d must be 9",$3);
2448+ $$->name = xlateSqlType("integer");
24262449
24272450} else {
24282451if (!strcasecmp($1, "char"))
@@ -2449,6 +2472,28 @@ Typename: typname opt_array_bounds
24492472$$->typlen = 4 + $3;
24502473}
24512474}
2475+ | txname '(' Iconst ',' Iconst ')'
2476+ {
2477+ $$ = makeNode(TypeName);
2478+ if (!strcasecmp($1, "decimal")) {
2479+ if ($3 > 9)
2480+ elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3);
2481+ if ($5 != 0)
2482+ elog(WARN,"DECIMAL scale %d must be zero",$5);
2483+ $$->name = xlateSqlType("integer");
2484+
2485+ } else if (!strcasecmp($1, "numeric")) {
2486+ if ($3 != 9)
2487+ elog(WARN,"NUMERIC precision %d must be 9",$3);
2488+ if ($5 != 0)
2489+ elog(WARN,"NUMERIC scale %d must be zero",$5);
2490+ $$->name = xlateSqlType("integer");
2491+
2492+ } else {
2493+ elog(WARN,"%s(%d,%d) not implemented",$1,$3,$5);
2494+ }
2495+ $$->name = xlateSqlType("integer");
2496+ }
24522497;
24532498
24542499
@@ -2550,6 +2595,88 @@ a_expr: attr opt_indirection
25502595FuncCall *n = makeNode(FuncCall);
25512596n->funcname = $1;
25522597n->args = NIL;
2598+ $$ = (Node *)n;
2599+ }
2600+ | CURRENT_DATE
2601+ {
2602+ A_Const *n = makeNode(A_Const);
2603+ TypeName *t = makeNode(TypeName);
2604+
2605+ n->val.type = T_String;
2606+ n->val.val.str = "now";
2607+ n->typename = t;
2608+
2609+ t->name = xlateSqlType("date");
2610+ t->setof = FALSE;
2611+
2612+ $$ = (Node *)n;
2613+ }
2614+ | CURRENT_TIME
2615+ {
2616+ A_Const *n = makeNode(A_Const);
2617+ TypeName *t = makeNode(TypeName);
2618+
2619+ n->val.type = T_String;
2620+ n->val.val.str = "now";
2621+ n->typename = t;
2622+
2623+ t->name = xlateSqlType("time");
2624+ t->setof = FALSE;
2625+
2626+ $$ = (Node *)n;
2627+ }
2628+ | CURRENT_TIME '(' AexprConst ')'
2629+ {
2630+ FuncCall *n = makeNode(FuncCall);
2631+ A_Const *s = makeNode(A_Const);
2632+ TypeName *t = makeNode(TypeName);
2633+
2634+ n->funcname = xlateSqlType("time");
2635+ n->args = lcons(s, NIL);
2636+
2637+ s->val.type = T_String;
2638+ s->val.val.str = "now";
2639+ s->typename = t;
2640+
2641+ t->name = xlateSqlType("time");
2642+ t->setof = FALSE;
2643+
2644+ elog(NOTICE,"CURRENT_TIME(p) precision not implemented",NULL);
2645+
2646+ $$ = (Node *)n;
2647+ }
2648+ | CURRENT_TIMESTAMP
2649+ {
2650+ A_Const *n = makeNode(A_Const);
2651+ TypeName *t = makeNode(TypeName);
2652+
2653+ n->val.type = T_String;
2654+ n->val.val.str = "now";
2655+ n->typename = t;
2656+
2657+ t->name = xlateSqlType("timestamp");
2658+ t->setof = FALSE;
2659+
2660+ $$ = (Node *)n;
2661+ }
2662+ | CURRENT_TIMESTAMP '(' AexprConst ')'
2663+ {
2664+ FuncCall *n = makeNode(FuncCall);
2665+ A_Const *s = makeNode(A_Const);
2666+ TypeName *t = makeNode(TypeName);
2667+
2668+ n->funcname = xlateSqlType("timestamp");
2669+ n->args = lcons(s, NIL);
2670+
2671+ s->val.type = T_String;
2672+ s->val.val.str = "now";
2673+ s->typename = t;
2674+
2675+ t->name = xlateSqlType("timestamp");
2676+ t->setof = FALSE;
2677+
2678+ elog(NOTICE,"CURRENT_TIMESTAMP(p) precision not implemented",NULL);
2679+
25532680$$ = (Node *)n;
25542681}
25552682/* We probably need to define an "exists" node,
@@ -3022,7 +3149,10 @@ access_method:Id{ $$ = $1; };
30223149attr_name:ColId{ $$ = $1; };
30233150class:Id{ $$ = $1; };
30243151index_name:Id{ $$ = $1; };
3025- name:Id{ $$ = $1; };
3152+
3153+ name: Id{ $$ = $1; }
3154+ | TIME{ $$ = xlateSqlType("time"); }
3155+ ;
30263156
30273157date:Sconst{ $$ = $1; };
30283158file_name:Sconst{ $$ = $1; };
@@ -3138,14 +3268,16 @@ void parser_init(Oid *typev, int nargs)
31383268/* FlattenStringList()
31393269 * Traverse list of string nodes and convert to a single string.
31403270 * Used for reconstructing string form of complex expressions.
3271+ *
3272+ * Allocate at least one byte for terminator.
31413273 */
31423274static char *
31433275FlattenStringList(List *list)
31443276{
31453277List *l, *lp;
31463278char *s;
31473279char *sp;
3148- int nlist, len =1 ;
3280+ int nlist, len =0 ;
31493281
31503282nlist = length(list);
31513283#ifdef PARSEDEBUG
@@ -3157,12 +3289,13 @@ printf( "list has %d elements\n", nlist);
31573289sp = (char *)(lp->elem.ptr_value);
31583290l = lnext(l);
31593291#ifdef PARSEDEBUG
3160- printf( "length of %s is %d\n", sp, strlen(sp));
3292+ printf( "sp is x%8p; length of %s is %d\n", sp , sp, strlen(sp));
31613293#endif
3162- len += strlen(sp)+1 ;
3294+ len += strlen(sp);
31633295};
3296+ len += nlist;
31643297
3165- s = (char*) palloc(len);
3298+ s = (char*) palloc(len+1 );
31663299*s = '\0';
31673300
31683301l = list;
@@ -3174,9 +3307,9 @@ printf( "length of %s is %d\n", sp, strlen(sp));
31743307printf( "length of %s is %d\n", sp, strlen(sp));
31753308#endif
31763309strcat(s,sp);
3177- strcat(s," ");
3310+ if (l != NIL) strcat(s," ");
31783311};
3179- *(s+len-2 ) = '\0';
3312+ *(s+len) = '\0';
31803313
31813314#ifdef PARSEDEBUG
31823315printf( "flattened string is \"%s\"\n", s);