Changeset: dae3337378c2 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=dae3337378c2
Modified Files:
        gdk/gdk_atoms.mx
        sql/server/sql_parser.y
        sql/test/BugTracker-2011/Tests/double_erange.Bug-2774.stable.err
        sql/test/BugTracker-2011/Tests/double_erange.Bug-2774.stable.out
        sql/test/copy/Tests/overflow_error.stable.err
        sql/test/copy/Tests/overflow_error.stable.out
Branch: Aug2011
Log Message:

Floating point overflow is not allowed, but underflow *is* allowed.
According to the SQL spec, floating point ("approximate numeric
literal") overflow results in a syntax error, but underflow is treated
the same as overspecification (more digits than the implementation can
represent) and results in the value 0 or a value very close to 0.
On underflow, the strtof and strtod functions return either 0 or an
unnormalized number which is closer to zero than the smallest
normalized number.  In addition, the function may or may not set errno
to ERANGE.  On overflow, the functions return HUGE_VAL (or HUGE_VALF)
and set errno to ERANGE.  We now check for overflow by checking
whether errno is set to ERANGE *and* the value is not "close to zero".

This fixes bug 2774, the output of which is also now approved.


diffs (truncated from 500 to 300 lines):

diff --git a/gdk/gdk_atoms.mx b/gdk/gdk_atoms.mx
--- a/gdk/gdk_atoms.mx
+++ b/gdk/gdk_atoms.mx
@@ -1571,13 +1571,15 @@ dblFromStr(char *src, int *len, dbl **ds
                **dst = dbl_nil;
                p += 3;
        } else {
-               /* on overflow, strtod returns HUGE_VAL and sets errno to
-                  ERANGE; on underflow, it returns 0 and also sets errno to
-                  ERANGE.  We accept 0, but not HUGE_VAL. */
+               /* on overflow, strtod returns HUGE_VAL and sets
+                * errno to ERANGE; on underflow, it returns a value
+                * whose magnitude is no greater than the smallest
+                * normalized double, and may or may not set errno to
+                * ERANGE.  We accept underflow, but not overflow. */
                errno = 0;
                d = strtod(src, &p);
-               if (p == src || (errno == ERANGE && d != 0)) {
-                       **dst = dbl_nil;        /* default return value is nil 
*/
+               if (p == src || (errno == ERANGE && (d < -1 || d > 1))) {
+                       **dst = dbl_nil; /* default return value is nil */
                        p = src;
                } else
                        **dst = (dbl) d;
@@ -1605,13 +1607,15 @@ fltFromStr(char *src, int *len, flt **ds
                p += 3;
        } else {
 #ifdef HAVE_STRTOF
-               /* on overflow, strtof returns HUGE_VALF and sets errno to
-                  ERANGE; on underflow, it returns 0 and also sets errno to
-                  ERANGE.  We accept 0, but not HUGE_VALF. */
+               /* on overflow, strtof returns HUGE_VALF and sets
+                * errno to ERANGE; on underflow, it returns a value
+                * whose magnitude is no greater than the smallest
+                * normalized float, and may or may not set errno to
+                * ERANGE.  We accept underflow, but not overflow. */
                errno = 0;
                f = strtof(src, &p);
                n = (int) (p - src);
-               if (n == 0 || (errno == ERANGE && f != 0)
+               if (n == 0 || (errno == ERANGE && (f < -1 || f > 1))
 #ifdef INFINITY
                    || f == INFINITY
 #endif
@@ -1634,7 +1638,7 @@ fltFromStr(char *src, int *len, flt **ds
                    )
 #endif
                {
-                       **dst = flt_nil;        /* default return value is nil 
*/
+                       **dst = flt_nil; /* default return value is nil */
                        n = 0;
                } else
                        **dst = (flt) f;
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -3828,12 +3828,23 @@ literal:
                        if (*s == '+' || *s == '-')
                                digits --;
                        sql_find_subtype(&t, "decimal", digits, scale );
-                       $$ = _newAtomNode( atom_dec(SA, &t, value, val)); 
-                  } else { 
-                       double val = strtod($1,NULL);
-
+                       $$ = _newAtomNode( atom_dec(SA, &t, value, val));
+                  } else {
+                       char *p = $1;
+                       double val;
+
+                       errno = 0;
+                       val = strtod($1,&p);
+                       if (p == $1 || (errno == ERANGE && (val < -1 || val > 
1))) {
+                               char *msg = sql_message("Double value too large 
or not a number (%s)", $1);
+
+                               yyerror(msg);
+                               _DELETE(msg);
+                               $$ = NULL;
+                               YYABORT;
+                       }
                        sql_find_subtype(&t, "double", 51, 0 );
-                       $$ = _newAtomNode(atom_float(SA, &t, val)); 
+                       $$ = _newAtomNode(atom_float(SA, &t, val));
                   }
                }
  |  APPROXNUM
@@ -3843,7 +3854,7 @@ literal:
 
                  errno = 0;
                  val = strtod($1,&p);
-                 if (p == $1 || (errno == ERANGE && val != 0)) {
+                 if (p == $1 || (errno == ERANGE && (val < -1 || val > 1))) {
                        char *msg = sql_message("Double value too large or not 
a number (%s)", $1);
 
                        yyerror(msg);
diff --git a/sql/test/BugTracker-2011/Tests/double_erange.Bug-2774.stable.err 
b/sql/test/BugTracker-2011/Tests/double_erange.Bug-2774.stable.err
--- a/sql/test/BugTracker-2011/Tests/double_erange.Bug-2774.stable.err
+++ b/sql/test/BugTracker-2011/Tests/double_erange.Bug-2774.stable.err
@@ -32,110 +32,8 @@ stderr of test 'double_erange.Bug-2774` 
 # 19:28:55 >  mclient -lsql -ftest -i -e --host=rig --port=32288 
 # 19:28:55 >  
 
-MAPI  = monetdb@rig:30301
-QUERY = insert into f2774 values (308,1e-308);
-ERROR = !Double value too large or not a number (1e-308) in: "insert into 
f2774 values (308,1e-308"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into d2774 values (308,1e-308);
-ERROR = !Double value too large or not a number (1e-308) in: "insert into 
d2774 values (308,1e-308"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into f2774 values (310,1e-310);
-ERROR = !Double value too large or not a number (1e-310) in: "insert into 
f2774 values (310,1e-310"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into d2774 values (310,1e-310);
-ERROR = !Double value too large or not a number (1e-310) in: "insert into 
d2774 values (310,1e-310"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into f2774 values (312,1e-312);
-ERROR = !Double value too large or not a number (1e-312) in: "insert into 
f2774 values (312,1e-312"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into d2774 values (312,1e-312);
-ERROR = !Double value too large or not a number (1e-312) in: "insert into 
d2774 values (312,1e-312"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into f2774 values (314,1e-314);
-ERROR = !Double value too large or not a number (1e-314) in: "insert into 
f2774 values (314,1e-314"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into d2774 values (314,1e-314);
-ERROR = !Double value too large or not a number (1e-314) in: "insert into 
d2774 values (314,1e-314"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into f2774 values (316,1e-316);
-ERROR = !Double value too large or not a number (1e-316) in: "insert into 
f2774 values (316,1e-316"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into d2774 values (316,1e-316);
-ERROR = !Double value too large or not a number (1e-316) in: "insert into 
d2774 values (316,1e-316"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into f2774 values (318,1e-318);
-ERROR = !Double value too large or not a number (1e-318) in: "insert into 
f2774 values (318,1e-318"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into d2774 values (318,1e-318);
-ERROR = !Double value too large or not a number (1e-318) in: "insert into 
d2774 values (318,1e-318"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into f2774 values (320,1e-320);
-ERROR = !Double value too large or not a number (1e-320) in: "insert into 
f2774 values (320,1e-320"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into d2774 values (320,1e-320);
-ERROR = !Double value too large or not a number (1e-320) in: "insert into 
d2774 values (320,1e-320"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into f2774 values (322,1e-322);
-ERROR = !Double value too large or not a number (1e-322) in: "insert into 
f2774 values (322,1e-322"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into d2774 values (322,1e-322);
-ERROR = !Double value too large or not a number (1e-322) in: "insert into 
d2774 values (322,1e-322"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into f2774 values (323,1e-323);
-ERROR = !Double value too large or not a number (1e-323) in: "insert into 
f2774 values (323,1e-323"
-        !syntax error, unexpected ')' in: ")"
-MAPI  = monetdb@rig:30301
-QUERY = insert into d2774 values (323,1e-323);
-ERROR = !Double value too large or not a number (1e-323) in: "insert into 
d2774 values (323,1e-323"
-        !syntax error, unexpected ')' in: ")"
 
-! to be checked & approved !
+# 13:53:27 >  
+# 13:53:27 >  "Done."
+# 13:53:27 >  
 
-MAPI  = monetdb@rig:30301
-QUERY = copy 18 records into f2774 from stdin using delimiters ',','\n';
-        300,1e-300
-        302,1e-302
-        304,1e-304
-        306,1e-306
-        307,1e-307
-        308,1e-308
-        310,1e-310
-        312,1e-312
-ERROR = !SQLException:importTable:value '1e-308' from line 6 field 2 not 
inserted, expecting type double
-        !failed to import table
-MAPI  = monetdb@rig:30301
-QUERY = copy 18 records into d2774 from stdin using delimiters ',','\n';
-        300,1e-300
-        302,1e-302
-        304,1e-304
-        306,1e-306
-        307,1e-307
-        308,1e-308
-        310,1e-310
-        312,1e-312
-ERROR = !SQLException:importTable:value '1e-308' from line 6 field 2 not 
inserted, expecting type double
-        !failed to import table
-
-! to be checked & approved !
-
-
-# 19:32:20 >
-# 19:32:20 >  Done.
-# 19:32:20 >  
-
diff --git a/sql/test/BugTracker-2011/Tests/double_erange.Bug-2774.stable.out 
b/sql/test/BugTracker-2011/Tests/double_erange.Bug-2774.stable.out
--- a/sql/test/BugTracker-2011/Tests/double_erange.Bug-2774.stable.out
+++ b/sql/test/BugTracker-2011/Tests/double_erange.Bug-2774.stable.out
@@ -57,6 +57,42 @@ Ready.
 [ 1    ]
 #insert into d2774 values (307,1e-307);
 [ 1    ]
+#insert into f2774 values (308,1e-308);
+[ 1    ]
+#insert into d2774 values (308,1e-308);
+[ 1    ]
+#insert into f2774 values (310,1e-310);
+[ 1    ]
+#insert into d2774 values (310,1e-310);
+[ 1    ]
+#insert into f2774 values (312,1e-312);
+[ 1    ]
+#insert into d2774 values (312,1e-312);
+[ 1    ]
+#insert into f2774 values (314,1e-314);
+[ 1    ]
+#insert into d2774 values (314,1e-314);
+[ 1    ]
+#insert into f2774 values (316,1e-316);
+[ 1    ]
+#insert into d2774 values (316,1e-316);
+[ 1    ]
+#insert into f2774 values (318,1e-318);
+[ 1    ]
+#insert into d2774 values (318,1e-318);
+[ 1    ]
+#insert into f2774 values (320,1e-320);
+[ 1    ]
+#insert into d2774 values (320,1e-320);
+[ 1    ]
+#insert into f2774 values (322,1e-322);
+[ 1    ]
+#insert into d2774 values (322,1e-322);
+[ 1    ]
+#insert into f2774 values (323,1e-323);
+[ 1    ]
+#insert into d2774 values (323,1e-323);
+[ 1    ]
 #insert into f2774 values (324,1e-324);
 [ 1    ]
 #insert into d2774 values (324,1e-324);
@@ -83,9 +119,19 @@ Ready.
 [ 304, 1e-304  ]
 [ 306, 1e-306  ]
 [ 307, 1e-307  ]
-
-! to be checked & approved !
-
+[ 308, 1e-308  ]
+[ 310, 1e-310  ]
+[ 312, 1e-312  ]
+[ 314, 1e-314  ]
+[ 316, 9.999999837e-317        ]
+[ 318, 9.999987485e-319        ]
+[ 320, 9.999888672e-321        ]
+[ 322, 9.881312917e-323        ]
+[ 323, 9.881312917e-324        ]
+[ 324, 0       ]
+[ 326, 0       ]
+[ 328, 0       ]
+[ 330, 0       ]
 #select * from d2774;
 % sys.d2774,   sys.d2774 # table_name
 % i,   d # name
@@ -96,13 +142,23 @@ Ready.
 [ 304, 1e-304  ]
 [ 306, 1e-306  ]
 [ 307, 1e-307  ]
-
-! to be checked & approved !
-
+[ 308, 1e-308  ]
+[ 310, 1e-310  ]
+[ 312, 1e-312  ]
+[ 314, 1e-314  ]
+[ 316, 9.999999837e-317        ]
+[ 318, 9.999987485e-319        ]
+[ 320, 9.999888672e-321        ]
+[ 322, 9.881312917e-323        ]
+[ 323, 9.881312917e-324        ]
+[ 324, 0       ]
+[ 326, 0       ]
+[ 328, 0       ]
+[ 330, 0       ]
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to