]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
New test cases to verify that SQLite handles bound NaN, +Inf, and -Inf
authordrh <drh@noemail.net>
Sun, 11 May 2008 11:07:06 +0000 (11:07 +0000)
committerdrh <drh@noemail.net>
Sun, 11 May 2008 11:07:06 +0000 (11:07 +0000)
floating point values correctly.  Improvements to the text->real conversion
routine so that it generates +Inf and -Inf at appropriate times.
Tickets #3101 and #3060. (CVS 5116)

FossilOrigin-Name: 3ff2f1cdc9c57bca56de6cdc0ad5edc95b0606a0

manifest
manifest.uuid
src/sqlite.h.in
src/test1.c
src/util.c
test/nan.test

index 17ec26567056809fa88b00170833fc1f9b53c6ed..6bdf0b67df6aff169ebd7c9a2e76a128a216e479 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sleaked\sfilename\sin\scase\sDosOpen()\sfails.\s(CVS\s5115)
-D 2008-05-09T19:38:24
+C New\stest\scases\sto\sverify\sthat\sSQLite\shandles\sbound\sNaN,\s+Inf,\sand\s-Inf\nfloating\spoint\svalues\scorrectly.\s\sImprovements\sto\sthe\stext->real\sconversion\nroutine\sso\sthat\sit\sgenerates\s+Inf\sand\s-Inf\sat\sappropriate\stimes.\nTickets\s#3101\sand\s#3060.\s(CVS\s5116)
+D 2008-05-11T11:07:07
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in 8b9b8263852f0217157f9042b8e3dae7427ec739
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -130,13 +130,13 @@ F src/printf.c 77c192ccc81117d68b21b449cd33396357aa266d
 F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a
 F src/select.c da43ce3080112aa77863e9c570c1df19a892acb8
 F src/shell.c 668ad976716982eb658019eda489b6f55131dbe7
-F src/sqlite.h.in abb785d2afcf45bb9344fe6edc1c7b428e1b719f
+F src/sqlite.h.in bf986db272eebf11be5c2d49b187a0f9562e2ee4
 F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
 F src/sqliteInt.h c38fad42820bd3a68cdb185edbea9aff8bf5c18b
 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
 F src/table.c 46ccf9b7892a86f57420ae7bac69ecd5e72d26b5
 F src/tclsqlite.c c57e740e30bd6dda678796eed62c7f0e64689834
-F src/test1.c 09062b31b89e3a74dd0a33d2af729b47678976f2
+F src/test1.c 86b31ca06489ed08687e460bf155c6b17958f83a
 F src/test2.c f0808cc643528b9620e4059ca9bda8346f526121
 F src/test3.c f5328839e29631ed9eef8674994ad7341b2de59b
 F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
@@ -165,7 +165,7 @@ F src/tokenize.c 8d77af8584cf027dc21375f0efa5818cb303c995
 F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
 F src/update.c 2d7143b9014e955509cc4f323f9a9584fb898f34
 F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b
-F src/util.c 99e0f11500f5a11f4ec7c60b52f34bd0ff622cea
+F src/util.c 4f0125fa1ba77be12e30e1b234352fc1b5abfe00
 F src/vacuum.c c3b2b70677f874102b8753bf494c232e777f3998
 F src/vdbe.c 56c11eb1493296ef6da5bbc049e77b795824bdc7
 F src/vdbe.h f4bb70962d9c13e0f65b215c90e8acea1ae6e8ee
@@ -398,7 +398,7 @@ F test/misc5.test 0b68dcb630d44af2dbcdca94dd2b17c8d580f6fa
 F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
 F test/misc7.test 26e0d948a413bca61ed031159907a03d64647409
 F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
-F test/nan.test c2a4562a3cbd5c78eb0592e08495bfdef077a76e
+F test/nan.test 14c41572ff52dbc740b1c3303dd313a90dc6084c
 F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82
 F test/null.test a8b09b8ed87852742343b33441a9240022108993
 F test/onefile.test 5af2867a8097cea08f15de5382b8d57d1219d8e3
@@ -634,7 +634,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P bf45a3ab7a295dcc399bdcf27965f1684b0a33b8
-R 57da237ef91fecaf24c595d9efd8c265
-U pweilbacher
-Z 0e3f04d9bb50f18e2eb4ea17dbbe751e
+P ecc6c739064922937ce66339f74403a0346aeedd
+R b636f115ca9e3f31cdc91f25e88091d1
+U drh
+Z 25e0008b9bf09460cd85318ac588b5de
index 2c59ffa2c809708a8d47253394b218da09356817..b230cd4401a6dd0a4e0718d8bc564512bddb8acd 100644 (file)
@@ -1 +1 @@
-ecc6c739064922937ce66339f74403a0346aeedd
\ No newline at end of file
+3ff2f1cdc9c57bca56de6cdc0ad5edc95b0606a0
\ No newline at end of file
index 6866c4f9604a0bde844fd0b3c5ca9c1f8365b0c2..d5742eac4bababe591b64ed91c0c16d1b8cd4454 100644 (file)
@@ -30,7 +30,7 @@
 ** the version number) and changes its name to "sqlite3.h" as
 ** part of the build process.
 **
-** @(#) $Id: sqlite.h.in,v 1.310 2008/04/27 22:48:05 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.311 2008/05/11 11:07:07 drh Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -155,7 +155,7 @@ int sqlite3_threadsafe(void);
 
 /*
 ** CAPI3REF: Database Connection Handle {F12000}
-** KEYWORDS: {database connection}
+** KEYWORDS: {database connection} {database connections}
 **
 ** Each open SQLite database is represented by pointer to an instance of the
 ** opaque structure named "sqlite3".  It is useful to think of an sqlite3
index cf420f0215bb039e47719410556ffa29799abcac..5eaef8a8d2548fedeb36529ee34b853a167c1f9b 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.301 2008/05/05 11:33:48 danielk1977 Exp $
+** $Id: test1.c,v 1.302 2008/05/11 11:07:07 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -2614,6 +2614,24 @@ static int test_bind_double(
   int idx;
   double value;
   int rc;
+  const char *zVal;
+  int i;
+  static const struct {
+    const char *zName;     /* Name of the special floating point value */
+    unsigned int iUpper;   /* Upper 32 bits */
+    unsigned int iLower;   /* Lower 32 bits */
+  } aSpecialFp[] = {
+    {  "NaN",      0x7fffffff, 0xffffffff },
+    {  "SNaN",     0x7ff7ffff, 0xffffffff },
+    {  "-NaN",     0xffffffff, 0xffffffff },
+    {  "-SNaN",    0xfff7ffff, 0xffffffff },
+    {  "+Inf",     0x7ff00000, 0x00000000 },
+    {  "-Inf",     0xfff00000, 0x00000000 },
+    {  "Epsilon",  0x00000000, 0x00000001 },
+    {  "-Epsilon", 0x80000000, 0x00000001 },
+    {  "NaN0",     0x7ff80000, 0x00000000 },
+    {  "-NaN0",    0xfff80000, 0x00000000 },
+  };
 
   if( objc!=4 ){
     Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -2629,12 +2647,19 @@ static int test_bind_double(
   ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions
   ** contain a bug.
   */
-  if( strcmp(Tcl_GetString(objv[3]), "NaN")==0 ){
-    sqlite3_int64 i;
-    i = 0xfff80000;
-    i <<= 32;
-    value = *(double*)(char*)&i;
-  }else if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ){
+  zVal = Tcl_GetString(objv[3]);
+  for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){
+    if( strcmp(aSpecialFp[i].zName, zVal)==0 ){
+      sqlite3_uint64 x;
+      x = aSpecialFp[i].iUpper;
+      x <<= 32;
+      x |= aSpecialFp[i].iLower;
+      value = *(double*)(char*)&x;
+      break;
+    }
+  }
+  if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) &&
+         Tcl_GetDoubleFromObj(interp, objv[3], &value) ){
     return TCL_ERROR;
   }
   rc = sqlite3_bind_double(pStmt, idx, value);
index 08be3066200cd05100f9a8bacf83326b814b31b0..0cd214aea2d79567589e26650e24d4fe342e4c44 100644 (file)
@@ -14,7 +14,7 @@
 ** This file contains functions for allocating memory, comparing
 ** strings, and stuff like that.
 **
-** $Id: util.c,v 1.227 2008/05/09 13:47:59 drh Exp $
+** $Id: util.c,v 1.228 2008/05/11 11:07:07 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdarg.h>
@@ -262,6 +262,7 @@ int sqlite3AtoF(const char *z, double *pResult){
   int sign = 1;
   const char *zBegin = z;
   LONGDOUBLE_TYPE v1 = 0.0;
+  int nSignificant = 0;
   while( isspace(*(u8*)z) ) z++;
   if( *z=='-' ){
     sign = -1;
@@ -269,16 +270,29 @@ int sqlite3AtoF(const char *z, double *pResult){
   }else if( *z=='+' ){
     z++;
   }
+  while( z[0]=='0' ){
+    z++;
+  }
   while( isdigit(*(u8*)z) ){
     v1 = v1*10.0 + (*z - '0');
     z++;
+    nSignificant++;
   }
   if( *z=='.' ){
     LONGDOUBLE_TYPE divisor = 1.0;
     z++;
+    if( nSignificant==0 ){
+      while( z[0]=='0' ){
+        divisor *= 10.0;
+        z++;
+      }
+    }
     while( isdigit(*(u8*)z) ){
-      v1 = v1*10.0 + (*z - '0');
-      divisor *= 10.0;
+      if( nSignificant<18 ){
+        v1 = v1*10.0 + (*z - '0');
+        divisor *= 10.0;
+        nSignificant++;
+      }
       z++;
     }
     v1 /= divisor;
index 0344811bdaae006f826a7840b8adb11b3dc276ab..d5645acbcc593cf43c49891d1ed83618cf64ae6e 100644 (file)
 # Make sure IEEE floating point NaN values are handled properly.
 # SQLite should always convert NaN into NULL.
 #
-# $Id: nan.test,v 1.2 2008/05/01 18:01:47 drh Exp $
+# Also verify that the decimal to IEEE754 binary conversion routines
+# correctly generate 0.0, +Inf, and -Inf as appropriate for numbers
+# out of range.
+#
+# $Id: nan.test,v 1.3 2008/05/11 11:07:07 drh Exp $
 #
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
 
-# The ascii->float conversion routine in SQLite converts all digits
-# of a number to a long long double.  Then it divids by 10**N where
-# N is the number of digits to the right of the decimal point.  If
-# both the full number and 10**N are +Inf we will get +Inf/+Inf which
-# is NaN.
-#
-unset -nocomplain nan
-set nan 9.[string repeat 9 5000]
-
-unset -nocomplain inf
-set inf [string repeat 9 5000].0
 
 do_test nan-1.1 {
   db eval {
@@ -38,31 +31,59 @@ do_test nan-1.1 {
     PRAGMA page_size=1024;
     CREATE TABLE t1(x FLOAT);
   }
-  db eval "INSERT INTO t1 VALUES($nan)"
+  set ::STMT [sqlite3_prepare db "INSERT INTO t1 VALUES(?)" -1 TAIL]
+  sqlite3_bind_double $::STMT 1 NaN
+  sqlite3_step $::STMT
+  sqlite3_reset $::STMT
   db eval {SELECT x, typeof(x) FROM t1}
 } {{} null}
 do_test nan-1.2 {
-  db eval "INSERT INTO t1 VALUES($inf)"
+  sqlite3_bind_double $::STMT 1 +Inf
+  sqlite3_step $::STMT
+  sqlite3_reset $::STMT
   db eval {SELECT x, typeof(x) FROM t1}
 } {{} null inf real}
 do_test nan-1.3 {
-  db eval "INSERT INTO t1 VALUES(-$inf)"
+  sqlite3_bind_double $::STMT 1 -Inf
+  sqlite3_step $::STMT
+  sqlite3_reset $::STMT
   db eval {SELECT x, typeof(x) FROM t1}
 } {{} null inf real -inf real}
 do_test nan-1.4 {
+  sqlite3_bind_double $::STMT 1 -NaN
+  sqlite3_step $::STMT
+  sqlite3_reset $::STMT
+  db eval {SELECT x, typeof(x) FROM t1}
+} {{} null inf real -inf real {} null}
+do_test nan-1.5 {
+  sqlite3_bind_double $::STMT 1 NaN0
+  sqlite3_step $::STMT
+  sqlite3_reset $::STMT
+  db eval {SELECT x, typeof(x) FROM t1}
+} {{} null inf real -inf real {} null {} null}
+do_test nan-1.5 {
+  sqlite3_bind_double $::STMT 1 -NaN0
+  sqlite3_step $::STMT
+  sqlite3_reset $::STMT
+  db eval {SELECT x, typeof(x) FROM t1}
+} {{} null inf real -inf real {} null {} null {} null}
+do_test nan-1.6 {
   db eval {
     UPDATE t1 SET x=x-x;
     SELECT x, typeof(x) FROM t1;
   }
-} {{} null {} null {} null}
+} {{} null {} null {} null {} null {} null {} null}
 
 do_test nan-2.1 {
   db eval {
     DELETE FROM T1;
   }
-  db eval "INSERT INTO t1 VALUES('$nan')"
+  sqlite3_bind_double $::STMT 1 NaN
+  sqlite3_step $::STMT
+  sqlite3_reset $::STMT
   db eval {SELECT x, typeof(x) FROM t1}
 } {{} null}
+sqlite3_finalize $::STMT
 
 # SQLite always converts NaN into NULL so it is not possible to write
 # a NaN value into the database file using SQLite.  The following series
@@ -92,5 +113,116 @@ do_test nan-3.3 {
   sqlite3 db test.db
   db eval {SELECT x, typeof(x) FROM t1}
 } {{} null}
+do_test nan-3.4 {
+  db close
+  hexio_write test.db 2040 7FF8000000000000
+  sqlite3 db test.db
+  db eval {SELECT x, typeof(x) FROM t1}
+} {{} null}
+do_test nan-3.5 {
+  db close
+  hexio_write test.db 2040 FFFFFFFFFFFFFFFF
+  sqlite3 db test.db
+  db eval {SELECT x, typeof(x) FROM t1}
+} {{} null}
+do_test nan-3.6 {
+  db close
+  hexio_write test.db 2040 7FFFFFFFFFFFFFFF
+  sqlite3 db test.db
+  db eval {SELECT x, typeof(x) FROM t1}
+} {{} null}
+
+# Verify that the sqlite3AtoF routine is able to handle extreme
+# numbers.
+#
+do_test nan-4.1 {
+  db eval {DELETE FROM t1}
+  db eval "INSERT INTO t1 VALUES([string repeat 9 307].0)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {1e+307 real}
+do_test nan-4.2 {
+  db eval {DELETE FROM t1}
+  db eval "INSERT INTO t1 VALUES([string repeat 9 308].0)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {1e+308 real}
+do_test nan-4.3 {
+  db eval {DELETE FROM t1}
+  db eval "INSERT INTO t1 VALUES([string repeat 9 309].0)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {inf real}
+do_test nan-4.4 {
+  db eval {DELETE FROM t1}
+  db eval "INSERT INTO t1 VALUES(-[string repeat 9 307].0)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {-1e+307 real}
+do_test nan-4.5 {
+  db eval {DELETE FROM t1}
+  db eval "INSERT INTO t1 VALUES(-[string repeat 9 308].0)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {-1e+308 real}
+do_test nan-4.6 {
+  db eval {DELETE FROM t1}
+  db eval "INSERT INTO t1 VALUES(-[string repeat 9 309].0)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {-inf real}
+do_test nan-4.7 {
+  db eval {DELETE FROM t1}
+  set big -[string repeat 0 10000][string repeat 9 308].[string repeat 0 10000]
+  db eval "INSERT INTO t1 VALUES($big)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {-1e+308 real}
+do_test nan-4.8 {
+  db eval {DELETE FROM t1}
+  set big [string repeat 0 10000][string repeat 9 308].[string repeat 0 10000]
+  db eval "INSERT INTO t1 VALUES($big)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {1e+308 real}
+
+
+do_test nan-4.10 {
+  db eval {DELETE FROM t1}
+  db eval "INSERT INTO t1 VALUES(1234.5[string repeat 0 10000]12345)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {1234.5 real}
+do_test nan-4.11 {
+  db eval {DELETE FROM t1}
+  db eval "INSERT INTO t1 VALUES(-1234.5[string repeat 0 10000]12345)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {-1234.5 real}
+do_test nan-4.12 {
+  db eval {DELETE FROM t1}
+  set small [string repeat 0 10000].[string repeat 0 323][string repeat 9 10000]
+  db eval "INSERT INTO t1 VALUES($small)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {9.88131291682493e-324 real}
+do_test nan-4.13 {
+  db eval {DELETE FROM t1}
+  set small [string repeat 0 10000].[string repeat 0 324][string repeat 9 10000]
+  db eval "INSERT INTO t1 VALUES($small)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {0.0 real}
+do_test nan-4.14 {
+  db eval {DELETE FROM t1}
+  set small \
+      -[string repeat 0 10000].[string repeat 0 323][string repeat 9 10000]
+  db eval "INSERT INTO t1 VALUES($small)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {-9.88131291682493e-324 real}
+do_test nan-4.15 {
+  db eval {DELETE FROM t1}
+  set small \
+      -[string repeat 0 10000].[string repeat 0 324][string repeat 9 10000]
+  db eval "INSERT INTO t1 VALUES($small)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {0.0 real}
+
+do_test nan-4.20 {
+  db eval {DELETE FROM t1}
+  set big [string repeat 9 10000].0e-9000
+  db eval "INSERT INTO t1 VALUES($big)"
+  db eval {SELECT x, typeof(x) FROM t1}
+} {{} null}
+
+
 
 finish_test