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