*
*
* 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
%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
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;
| CHARACTER char_type { $$ = $2; }
| DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
| FLOAT { $$ = xlateSqlType("float"); }
+ | DECIMAL { $$ = "decimal"; }
+ | NUMERIC { $$ = "numeric"; }
;
char_type: VARYING { $$ = xlateSqlType("varchar"); }
{
$$ = $1;
$$->arrayBounds = $2;
+#if FALSE
if (!strcasecmp($1->name, "varchar"))
$$->typlen = 4 + 1;
+#endif
}
| txname '(' Iconst ')'
{
* 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"))
$$->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");
+ }
;
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,
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; };
/* 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)
List *l, *lp;
char *s;
char *sp;
- int nlist, len = 1;
+ int nlist, len = 0;
nlist = length(list);
#ifdef PARSEDEBUG
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;
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);