Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit512669d

Browse files
committed
Make make_const() check the size and precision of a T_Float Value,
and produce either FLOAT8 or NUMERIC output depending on whether thevalue fits in a float8 or not. This is almost back to the way thecode was before I changed T_Float, but there is a critical difference:now, when a numeric constant doesn't fit in float8, it will be treatedas type NUMERIC instead of type UNKNOWN.
1 parent399a570 commit512669d

File tree

2 files changed

+94
-23
lines changed

2 files changed

+94
-23
lines changed

‎src/backend/parser/gram.y

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.149 2000/02/22 00:05:04 tgl Exp $
14+
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.150 2000/02/24 01:59:17 tgl Exp $
1515
*
1616
* HISTORY
1717
* AUTHORDATEMAJOR EVENT
@@ -5606,14 +5606,17 @@ Oid param_type(int t)
56065606
}
56075607

56085608
/*
5609-
*The optimizer doesn't like '-' 4 for index use. It only checks for
5610-
*Var '=' Const. It wants an integer of -4, so we try to merge the
5611-
*minus into the constant.
5612-
*
5613-
*This code is no longer essential as of 10/1999, since the optimizer
5614-
*now has a constant-subexpression simplifier. However, we can save
5615-
*a few cycles throughout the parse and rewrite stages if we collapse
5616-
*the minus into the constant sooner rather than later...
5609+
* doNegate --- handle negation of a numeric constant.
5610+
*
5611+
* Formerly, we did this here because the optimizer couldn't cope with
5612+
* indexquals that looked like "var = -4" --- it wants "var = const"
5613+
* and a unary minus operator applied to a constant didn't qualify.
5614+
* As of Postgres 7.0, that problem doesn't exist anymore because there
5615+
* is a constant-subexpression simplifier in the optimizer. However,
5616+
* there's still a good reason for doing this here, which is that we can
5617+
* postpone committing to a particular internal representation for simple
5618+
* negative constants. It's better to leave "-123.456" in string form
5619+
* until we know what the desired type is.
56175620
*/
56185621
static Node *
56195622
doNegate(Node *n)

‎src/backend/parser/parse_node.c

Lines changed: 82 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.37 2000/01/26 05:56:42 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.38 2000/02/24 01:59:17 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515
#include<ctype.h>
16+
#include<errno.h>
17+
#include<float.h>
1618

1719
#include"postgres.h"
20+
1821
#include"access/heapam.h"
1922
#include"catalog/pg_operator.h"
2023
#include"catalog/pg_type.h"
@@ -32,6 +35,8 @@
3235
#include"utils/syscache.h"
3336

3437
staticvoiddisallow_setop(char*op,Typeoptype,Node*operand);
38+
staticboolfitsInFloat(Value*value);
39+
3540

3641
/* make_parsestate()
3742
* Allocate and initialize a new ParseState.
@@ -393,11 +398,25 @@ transformArraySubscripts(ParseState *pstate,
393398
* make_const
394399
*
395400
*Convert a Value node (as returned by the grammar) to a Const node
396-
*of the "natural" type for the constant. For strings we produce
397-
*a constant of type UNKNOWN ---- representation is the same as text,
398-
*but this indicates to later type resolution that we're not sure that
399-
*it should be considered text. Explicit "NULL" constants are also
400-
*typed as UNKNOWN.
401+
*of the "natural" type for the constant. Note that this routine is
402+
*only used when there is no explicit cast for the constant, so we
403+
*have to guess what type is wanted.
404+
*
405+
*For string literals we produce a constant of type UNKNOWN ---- whose
406+
*representation is the same as text, but it indicates to later type
407+
*resolution that we're not sure that it should be considered text.
408+
*Explicit "NULL" constants are also typed as UNKNOWN.
409+
*
410+
* For integers and floats we produce int4, float8, or numeric depending
411+
*on the value of the number. XXX In some cases it would be nice to take
412+
*context into account when determining the type to convert to, but in
413+
*other cases we can't delay the type choice. One possibility is to invent
414+
*a dummy type "UNKNOWNNUMERIC" that's treated similarly to UNKNOWN;
415+
*that would allow us to do the right thing in examples like a simple
416+
*INSERT INTO table (numericcolumn) VALUES (1.234), since we wouldn't
417+
*have to resolve the unknown type until we knew the destination column
418+
*type. On the other hand UNKNOWN has considerable problems of its own.
419+
*We would not like "SELECT 1.2 + 3.4" to claim it can't choose a type.
401420
*/
402421
Const*
403422
make_const(Value*value)
@@ -419,18 +438,25 @@ make_const(Value *value)
419438
break;
420439

421440
caseT_Float:
441+
if (fitsInFloat(value))
422442
{
423-
float64dummy;
443+
float64fltval= (float64)palloc(sizeof(float64data));
424444

425-
dummy= (float64)palloc(sizeof(float64data));
426-
*dummy=floatVal(value);
427-
428-
val=Float64GetDatum(dummy);
445+
*fltval=floatVal(value);
446+
val=Float64GetDatum(fltval);
429447

430448
typeid=FLOAT8OID;
431449
typelen=sizeof(float64data);
432450
typebyval= false;
433451
}
452+
else
453+
{
454+
val=PointerGetDatum(numeric_in(strVal(value),0,-1));
455+
456+
typeid=NUMERICOID;
457+
typelen=-1;/* variable len */
458+
typebyval= false;
459+
}
434460
break;
435461

436462
caseT_String:
@@ -441,11 +467,11 @@ make_const(Value *value)
441467
typebyval= false;
442468
break;
443469

444-
caseT_Null:
445470
default:
446-
if (nodeTag(value)!=T_Null)
447-
elog(NOTICE,"make_const: unknown type %d\n",nodeTag(value));
471+
elog(NOTICE,"make_const: unknown type %d",nodeTag(value));
472+
/* FALLTHROUGH */
448473

474+
caseT_Null:
449475
/* return a null const */
450476
con=makeConst(UNKNOWNOID,
451477
-1,
@@ -467,3 +493,45 @@ make_const(Value *value)
467493

468494
returncon;
469495
}
496+
497+
/*
498+
* Decide whether a T_Float value fits in float8, or must be treated as
499+
* type "numeric". We check the number of digits and check for overflow/
500+
* underflow. (With standard compilation options, Postgres' NUMERIC type
501+
* can handle decimal exponents up to 1000, considerably more than most
502+
* implementations of float8, so this is a sensible test.)
503+
*/
504+
staticbool
505+
fitsInFloat(Value*value)
506+
{
507+
constchar*ptr;
508+
intndigits;
509+
char*endptr;
510+
511+
/*
512+
* Count digits, ignoring leading zeroes (but not trailing zeroes).
513+
* DBL_DIG is the maximum safe number of digits for "double".
514+
*/
515+
ptr=strVal(value);
516+
while (*ptr=='+'||*ptr=='-'||*ptr=='0'||*ptr=='.')
517+
ptr++;
518+
ndigits=0;
519+
for (;*ptr;ptr++)
520+
{
521+
if (isdigit(*ptr))
522+
ndigits++;
523+
elseif (*ptr=='e'||*ptr=='E')
524+
break;/* don't count digits in exponent */
525+
}
526+
if (ndigits>DBL_DIG)
527+
return false;
528+
/*
529+
* Use strtod() to check for overflow/underflow.
530+
*/
531+
errno=0;
532+
(void)strtod(strVal(value),&endptr);
533+
if (*endptr!='\0'||errno!=0)
534+
return false;
535+
536+
return true;
537+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp