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"
3235#include "utils/syscache.h"
3336
3437static void disallow_setop (char * op ,Type optype ,Node * operand );
38+ static bool fitsInFloat (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 */
402421Const *
403422make_const (Value * value )
@@ -419,18 +438,25 @@ make_const(Value *value)
419438break ;
420439
421440case T_Float :
441+ if (fitsInFloat (value ))
422442{
423- float64 dummy ;
443+ float64 fltval = ( 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
430448typeid = FLOAT8OID ;
431449typelen = sizeof (float64data );
432450typebyval = 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+ }
434460break ;
435461
436462case T_String :
@@ -441,11 +467,11 @@ make_const(Value *value)
441467typebyval = false;
442468break ;
443469
444- case T_Null :
445470default :
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+ case T_Null :
449475/* return a null const */
450476con = makeConst (UNKNOWNOID ,
451477-1 ,
@@ -467,3 +493,45 @@ make_const(Value *value)
467493
468494return con ;
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+ static bool
505+ fitsInFloat (Value * value )
506+ {
507+ const char * ptr ;
508+ int ndigits ;
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+ else if (* 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+ }