Re: [HACKERS] numeric data type on 6.5 - Mailing list pgsql-hackers

From Thomas Lockhart
Subject Re: [HACKERS] numeric data type on 6.5
Date
Msg-id 372F0201.2C9584E3@alumni.caltech.edu
Whole thread Raw
In response to Re: [HACKERS] numeric data type on 6.5  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: [HACKERS] numeric data type on 6.5
Re: [HACKERS] numeric data type on 6.5
List pgsql-hackers
> > I'm looking at this right now. I had coded in a fallback to FLOAT8 for
> > the integer types because at the time that was the only other useful
> > numeric type. However, I'm going to try changing the code to leave a
> > failed INTx token as a string of unspecified type, which would be
> > typed and converted later using the automatic coersion mechanism.
> That would be good as far as it goes, but what about cases with a
> decimal point in 'em?  Converting to float and then to numeric will
> lose precision.
> I'm inclined to think you should prevent the parser from converting
> *any* numeric constant out of string form until it knows the target data
> type.
> (IIRC, INT8 has problems similar to NUMERIC's...)

Right. Here is a patch which tries to do something right for most
cases. For the "integer" token (numbers w/o a decimal point) it keeps
the token as a string if the conversion to int4 fails. I split the
"real" token into "decimal" (w/o exponent) and "real"; at the moment
"decimal" is forced to become a float8 if there are fewer than 18
characters in the string, but there may be a more robust strategy to
be had.

When a numeric token is kept as a string, the parser requires some
typing context to handle the string later, otherwise it will complain.
But that is probably better than silently swallowing numeric data and
possibly mishandling it.

Seems to do OK with numeric tokens of unspecified type which will
become int8 and numeric in the parser. There may be some edge-effect
cases (e.g. decimal data with 17 characters) which aren't quite right.

Comments?

                         - Tom

--
Thomas Lockhart                lockhart@alumni.caltech.edu
South Pasadena, California*** ../src/backend/parser/scan.l.orig    Tue Mar 30 15:08:02 1999
--- ../src/backend/parser/scan.l    Tue Apr 27 16:29:21 1999
***************
*** 152,161 ****
  xmstop            -

  integer            [\-]?{digit}+
  /*
- real            [\-]?{digit}+\.{digit}+([Ee][-+]?{digit}+)?
- */
  real            [\-]?(((({digit}*\.{digit}+)|({digit}+\.{digit}*))([Ee][-+]?{digit}+)?)|({digit}+[Ee][-+]?{digit}+))

  param            \${integer}

--- 152,162 ----
  xmstop            -

  integer            [\-]?{digit}+
+ decimal            [\-]?(({digit}*\.{digit}+)|({digit}+\.{digit}*))
+ real            [\-]?((({digit}*\.{digit}+)|({digit}+\.{digit}*)|({digit}+))([Ee][-+]?{digit}+))
  /*
  real            [\-]?(((({digit}*\.{digit}+)|({digit}+\.{digit}*))([Ee][-+]?{digit}+)?)|({digit}+[Ee][-+]?{digit}+))
+ */

  param            \${integer}

***************
*** 334,348 ****
--- 335,369 ----
                      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
+                         yylval.str = pstrdup((char*)yytext);
+                         return SCONST;
                      }
                      return ICONST;
                  }
+ {decimal}/{space}*-{number} {
+                     char* endptr;
+
+                     BEGIN(xm);
+                     if (strlen((char *)yytext) <= 17)
+                     {
+                         errno = 0;
+                         yylval.dval = strtod(((char *)yytext),&endptr);
+                         if (*endptr != '\0' || errno == ERANGE)
+                             elog(ERROR,"Bad float8 input '%s'",yytext);
+                         CheckFloat8Val(yylval.dval);
+                         return FCONST;
+                     }
+                     yylval.str = pstrdup((char*)yytext);
+                     return SCONST;
+                 }
  {real}/{space}*-{number} {
                      char* endptr;

***************
*** 362,375 ****
--- 383,415 ----
                      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
+                         yylval.str = pstrdup((char*)yytext);
+                         return SCONST;
                      }
                      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;
                  }
  {real}            {
                      char* endptr;

pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: [HACKERS] an older problem? hash table out of memory
Next
From: Tom Lane
Date:
Subject: Re: [HACKERS] adate::Date is equiv. to adate if adate is type of Date ?