diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-02-21 18:47:12 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-02-21 18:47:12 +0000 |
commit | 393f313227fba2b7905cfbd69b3e4c18d762bf4f (patch) | |
tree | 0eab81bd6705a19b625880d9b5cefb1d50c78d78 /src/backend/parser | |
parent | ee97d103ccf68ae45343caea4188ca3dd5ce7365 (diff) |
Change parse-time representation of float literals (which include oversize
integers) to be strings instead of 'double'. We convert from string form
to internal representation only after type resolution has determined the
correct type for the constant. This eliminates loss-of-precision worries
and gets rid of the change in behavior seen at 17 digits with the
previous kluge.
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 45 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 12 | ||||
-rw-r--r-- | src/backend/parser/scan.l | 39 |
3 files changed, 41 insertions, 55 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index f43393eeff8..b81b6d387ab 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.147 2000/02/20 02:14:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.148 2000/02/21 18:47:02 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -78,6 +78,7 @@ static Node *makeRowExpr(char *opr, List *largs, List *rargs); static void mapTargetColumns(List *source, List *target); static void param_type_init(Oid *typev, int nargs); static Node *doNegate(Node *n); +static void doNegateFloat(Value *v); /* old versions of flex define this as a macro */ #if defined(yywrap) @@ -88,7 +89,6 @@ static Node *doNegate(Node *n); %union { - double dval; int ival; char chr; char *str; @@ -352,9 +352,8 @@ static Node *doNegate(Node *n); UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION /* Special keywords, not in the query language - see the "lex" file */ -%token <str> IDENT, SCONST, Op +%token <str> IDENT, FCONST, SCONST, Op %token <ival> ICONST, PARAM -%token <dval> FCONST /* these are not real. they are here so that they get generated as #define's*/ %token OP @@ -1567,7 +1566,7 @@ FloatOnly: FCONST | '-' FCONST { $$ = makeFloat($2); - $$->val.dval = - $$->val.dval; + doNegateFloat($$); } ; @@ -1722,16 +1721,11 @@ TriggerFuncArgs: TriggerFuncArg TriggerFuncArg: ICONST { - char *s = (char *) palloc (256); + char *s = (char *) palloc(64); sprintf (s, "%d", $1); $$ = s; } - | FCONST - { - char *s = (char *) palloc (256); - sprintf (s, "%g", $1); - $$ = s; - } + | FCONST { $$ = $1; } | Sconst { $$ = $1; } | IDENT { $$ = $1; } ; @@ -5183,7 +5177,7 @@ AexprConst: Iconst { A_Const *n = makeNode(A_Const); n->val.type = T_Float; - n->val.val.dval = $1; + n->val.val.str = $1; $$ = (Node *)n; } | Sconst @@ -5621,7 +5615,8 @@ Oid param_type(int t) * a few cycles throughout the parse and rewrite stages if we collapse * the minus into the constant sooner rather than later... */ -static Node *doNegate(Node *n) +static Node * +doNegate(Node *n) { if (IsA(n, A_Const)) { @@ -5634,10 +5629,30 @@ static Node *doNegate(Node *n) } if (con->val.type == T_Float) { - con->val.val.dval = -con->val.val.dval; + doNegateFloat(&con->val); return n; } } return makeA_Expr(OP, "-", NULL, n); } + +static void +doNegateFloat(Value *v) +{ + char *oldval = v->val.str; + + Assert(IsA(v, Float)); + if (*oldval == '+') + oldval++; + if (*oldval == '-') + v->val.str = oldval; /* just strip the '-' */ + else + { + char *newval = (char *) palloc(strlen(oldval) + 2); + + *newval = '-'; + strcpy(newval+1, oldval); + v->val.str = newval; + } +} diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 3fd3370672f..2efdd136005 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.69 2000/02/20 21:32:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.70 2000/02/21 18:47:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -726,23 +726,19 @@ parser_typecast_constant(Value *expr, TypeName *typename) switch (nodeTag(expr)) { - case T_String: - const_string = DatumGetPointer(expr->val.str); - break; case T_Integer: string_palloced = true; const_string = int4out(expr->val.ival); break; case T_Float: - string_palloced = true; - const_string = float8out(&expr->val.dval); + case T_String: + const_string = expr->val.str; break; case T_Null: isNull = true; break; default: - elog(ERROR, - "Cannot cast this expression to type '%s'", + elog(ERROR, "Cannot cast this expression to type '%s'", typename->name); } diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index fa3408c1f1d..5b8dd16d81f 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.64 2000/02/19 04:17:25 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.65 2000/02/21 18:47:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -324,7 +324,7 @@ other . } {param} { - yylval.ival = atoi((char*)&yytext[1]); + yylval.ival = atol((char*)&yytext[1]); return PARAM; } @@ -332,46 +332,21 @@ other . char* endptr; errno = 0; - yylval.ival = strtol((char *)yytext,&endptr,10); + yylval.ival = strtol((char *)yytext, &endptr, 10); if (*endptr != '\0' || errno == ERANGE) { - errno = 0; -#if 0 - yylval.dval = strtod(((char *)yytext),&endptr); - if (*endptr != '\0' || errno == ERANGE) - elog(ERROR,"Bad integer input '%s'",yytext); - CheckFloat8Val(yylval.dval); - elog(NOTICE,"Integer input '%s' is out of range; promoted to float", yytext); - return FCONST; -#endif + /* integer too large, treat it as a float */ yylval.str = pstrdup((char*)yytext); - return SCONST; + return FCONST; } return ICONST; } {decimal} { - char* endptr; - - if (strlen((char *)yytext) <= 17) - { - errno = 0; - yylval.dval = strtod((char *)yytext,&endptr); - if (*endptr != '\0' || errno == ERANGE) - elog(ERROR,"Bad float input '%s'",yytext); - CheckFloat8Val(yylval.dval); - return FCONST; - } yylval.str = pstrdup((char*)yytext); - return SCONST; + return FCONST; } {real} { - char* endptr; - - errno = 0; - yylval.dval = strtod((char *)yytext,&endptr); - if (*endptr != '\0' || errno == ERANGE) - elog(ERROR,"Bad float input '%s'",yytext); - CheckFloat8Val(yylval.dval); + yylval.str = pstrdup((char*)yytext); return FCONST; } |