mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-09 14:21:03 +03:00
New test cases to verify that SQLite handles bound NaN, +Inf, and -Inf
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
This commit is contained in:
20
manifest
20
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
|
||||
|
||||
@@ -1 +1 @@
|
||||
ecc6c739064922937ce66339f74403a0346aeedd
|
||||
3ff2f1cdc9c57bca56de6cdc0ad5edc95b0606a0
|
||||
@@ -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
|
||||
|
||||
39
src/test1.c
39
src/test1.c
@@ -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);
|
||||
|
||||
16
src/util.c
16
src/util.c
@@ -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) ){
|
||||
if( nSignificant<18 ){
|
||||
v1 = v1*10.0 + (*z - '0');
|
||||
divisor *= 10.0;
|
||||
nSignificant++;
|
||||
}
|
||||
z++;
|
||||
}
|
||||
v1 /= divisor;
|
||||
|
||||
166
test/nan.test
166
test/nan.test
@@ -14,23 +14,16 @@
|
||||
# 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
|
||||
|
||||
Reference in New Issue
Block a user