From: drh Date: Tue, 29 Apr 2008 00:15:20 +0000 (+0000) Subject: Always convert IEEE NaN into NULL. Ticket #3060. Add test cases to verify X-Git-Tag: version-3.6.10~1111 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2eaf93d34fb46993458504ee32ee984e39b56f8a;p=thirdparty%2Fsqlite.git Always convert IEEE NaN into NULL. Ticket #3060. Add test cases to verify that this is happening. (CVS 5066) FossilOrigin-Name: 9b07e59e510e2de39c2081653662fbc654ca6fbb --- diff --git a/manifest b/manifest index 058de80da6..264571c06e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allow\sSQLITE_MAX_COLUMN\sto\sbe\sset\sto\szero\sat\scompile-time\sin\sorder\sto\ndisable\sthe\schecks.\s\sAlso\sSQLITE_MAX_EXPR_DEPTH.\s\sTicket\s#3069.\s(CVS\s5065) -D 2008-04-28T20:35:49 +C Always\sconvert\sIEEE\sNaN\sinto\sNULL.\s\sTicket\s#3060.\s\sAdd\stest\scases\sto\sverify\nthat\sthis\sis\shappening.\s(CVS\s5066) +D 2008-04-29T00:15:21 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 25b3282a4ac39388632c2fb0e044ff494d490952 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -94,7 +94,7 @@ F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d F src/delete.c d3fc5987f2eb88f7b9549d58a5dfea079a83fe8b -F src/expr.c 6a6f37005921314b1ae7c3ed4fab03c58fd5e647 +F src/expr.c a896d1be67b2abe9759369cb7f3a3b7a1c21fc3f F src/fault.c 83057e86815d473e526f7df0b0108dfdd022ff23 F src/func.c 77a910a1ca7613d291fd0b5cba3be14c02f0dce0 F src/hash.c 522a8f5a23cf18fe5845afee7263c5be76c25ca2 @@ -169,11 +169,11 @@ F src/update.c 2d7143b9014e955509cc4f323f9a9584fb898f34 F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b F src/util.c a3907b05dcc3720a6d71bb39e61d67b0d994b51f F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30 -F src/vdbe.c 1e0ee231e5b035195c6d0043f059fe7f3df563da +F src/vdbe.c 26964ba7ed76d2a1c52747d601aaf2dc5b09b651 F src/vdbe.h bfd84bda447f39cb599302c7ec85067dae20453c F src/vdbeInt.h 05316345da487b0cf540482576f9ae3337d133cd F src/vdbeapi.c 0e1b5a808bb0e556f2a975eb7d11fd3153e922bf -F src/vdbeaux.c 7a0d0f021ebc54ae581a4f1ba833a2bee576228e +F src/vdbeaux.c aae523de91fb72a32a256253880739fe103ea76e F src/vdbeblob.c 554736781ee273a8089c776e96bdb53e66f57ce6 F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736 F src/vdbemem.c 8cdc5d4c9558338a2c5ae81135d0826136833b5e @@ -398,6 +398,7 @@ F test/misc5.test c1bc7b8cbc6694dccfc4c0b03c00c8f2dc55c46b F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test 26e0d948a413bca61ed031159907a03d64647409 F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33 +F test/nan.test bda46bce39d14bbe23b97feb390a0b54961a0de9 F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82 F test/null.test a8b09b8ed87852742343b33441a9240022108993 F test/onefile.test 5af2867a8097cea08f15de5382b8d57d1219d8e3 @@ -632,7 +633,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 76175199ac2fda57e616eb386ba0bad6aa9f74b4 -R dc8adbd3002ee68e412cd270901158fa +P e6f71abb22fb74e5910d817caec98fa44070fc5f +R e524df0bf8a8555789b9eeb5782f38f2 U drh -Z 1669d55a9b3e668684a817ba98300199 +Z e4a613f256396e3f19a950003ad91fee diff --git a/manifest.uuid b/manifest.uuid index 8ca0edb939..301fe26ff7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e6f71abb22fb74e5910d817caec98fa44070fc5f \ No newline at end of file +9b07e59e510e2de39c2081653662fbc654ca6fbb \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 9dfd6fc784..e0c5ecfbcb 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.369 2008/04/25 00:08:38 drh Exp $ +** $Id: expr.c,v 1.370 2008/04/29 00:15:21 drh Exp $ */ #include "sqliteInt.h" #include @@ -1938,9 +1938,13 @@ static void codeReal(Vdbe *v, const char *z, int n, int negateFlag, int iMem){ char *zV; assert( !isdigit(z[n]) ); sqlite3AtoF(z, &value); - if( negateFlag ) value = -value; - zV = dup8bytes(v, (char*)&value); - sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); + if( sqlite3IsNaN(value) ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, iMem); + }else{ + if( negateFlag ) value = -value; + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); + } } } diff --git a/src/vdbe.c b/src/vdbe.c index 2f027e95cc..35527f65dc 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.736 2008/04/28 16:55:26 drh Exp $ +** $Id: vdbe.c,v 1.737 2008/04/29 00:15:21 drh Exp $ */ #include "sqliteInt.h" #include @@ -842,6 +842,7 @@ case OP_Int64: { /* out2-prerelease */ */ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ pOut->flags = MEM_Real; + assert( !sqlite3IsNaN(*pOp->p4.pReal) ); pOut->r = *pOp->p4.pReal; break; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 38dd344d64..60b42f61fb 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -14,7 +14,7 @@ ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. ** -** $Id: vdbeaux.c,v 1.380 2008/04/27 18:40:12 drh Exp $ +** $Id: vdbeaux.c,v 1.381 2008/04/29 00:15:21 drh Exp $ */ #include "sqliteInt.h" #include @@ -2133,7 +2133,7 @@ int sqlite3VdbeSerialGet( assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); swapMixedEndianFloat(x); memcpy(&pMem->r, &x, sizeof(x)); - pMem->flags = MEM_Real; + pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; } return 8; } diff --git a/test/nan.test b/test/nan.test new file mode 100644 index 0000000000..ff60d58f17 --- /dev/null +++ b/test/nan.test @@ -0,0 +1,94 @@ +# 2008 April 28 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Ticket #3060 +# +# Make sure IEEE floating point NaN values are handled properly. +# SQLite should always convert NaN into NULL. +# +# $Id: nan.test,v 1.1 2008/04/29 00:15:21 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 { + CREATE TABLE t1(x FLOAT); + } + db eval "INSERT INTO t1 VALUES($nan)" + db eval {SELECT x, typeof(x) FROM t1} +} {{} null} +do_test nan-1.2 { + db eval "INSERT INTO t1 VALUES($inf)" + db eval {SELECT x, typeof(x) FROM t1} +} {{} null inf real} +do_test nan-1.3 { + db eval "INSERT INTO t1 VALUES(-$inf)" + db eval {SELECT x, typeof(x) FROM t1} +} {{} null inf real -inf real} +do_test nan-1.4 { + db eval { + UPDATE t1 SET x=x-x; + SELECT x, typeof(x) FROM t1; + } +} {{} null {} null {} null} + +do_test nan-2.1 { + db eval { + DELETE FROM T1; + } + db eval "INSERT INTO t1 VALUES('$nan')" + db eval {SELECT x, typeof(x) FROM t1} +} {{} null} + +# 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 +# of tests writes a normal floating point value (0.5) into the database, +# then writes directly into the database file to change the 0.5 into NaN. +# Then it reads the value of the database to verify it is converted into +# NULL. +# +do_test nan-3.1 { + db eval { + DELETE FROM t1; + INSERT INTO t1 VALUES(0.5); + PRAGMA auto_vacuum=OFF; + PRAGMA page_size=1024; + VACUUM; + } + hexio_read test.db 2040 8 +} {3FE0000000000000} +do_test nan-3.2 { + db eval { + SELECT x, typeof(x) FROM t1 + } +} {0.5 real} +do_test nan-3.3 { + db close + hexio_write test.db 2040 FFF8000000000000 + sqlite3 db test.db + db eval {SELECT x, typeof(x) FROM t1} +} {{} null} + +finish_test