12eaf93d3Sdrh# 2008 April 28 22eaf93d3Sdrh# 32eaf93d3Sdrh# The author disclaims copyright to this source code. In place of 42eaf93d3Sdrh# a legal notice, here is a blessing: 52eaf93d3Sdrh# 62eaf93d3Sdrh# May you do good and not evil. 72eaf93d3Sdrh# May you find forgiveness for yourself and forgive others. 82eaf93d3Sdrh# May you share freely, never taking more than you give. 92eaf93d3Sdrh# 102eaf93d3Sdrh#*********************************************************************** 112eaf93d3Sdrh# 122eaf93d3Sdrh# Ticket #3060 132eaf93d3Sdrh# 142eaf93d3Sdrh# Make sure IEEE floating point NaN values are handled properly. 152eaf93d3Sdrh# SQLite should always convert NaN into NULL. 162eaf93d3Sdrh# 17a06f17feSdrh# Also verify that the decimal to IEEE754 binary conversion routines 18a06f17feSdrh# correctly generate 0.0, +Inf, and -Inf as appropriate for numbers 19a06f17feSdrh# out of range. 20a06f17feSdrh# 21b11bcfdeSdanielk1977# $Id: nan.test,v 1.5 2008/09/18 11:30:13 danielk1977 Exp $ 222eaf93d3Sdrh# 232eaf93d3Sdrh 242eaf93d3Sdrhset testdir [file dirname $argv0] 252eaf93d3Sdrhsource $testdir/tester.tcl 262eaf93d3Sdrh 2768928b6cSdan# Do not use a codec for tests in this file, as the database file is 2868928b6cSdan# manipulated directly using tcl scripts (using the [hexio_write] command). 2968928b6cSdan# 3068928b6cSdando_not_use_codec 3168928b6cSdan 3289bae3edSdanielk1977do_test nan-1.1.1 { 332eaf93d3Sdrh db eval { 34b7d63620Sdrh PRAGMA auto_vacuum=OFF; 35b7d63620Sdrh PRAGMA page_size=1024; 362eaf93d3Sdrh CREATE TABLE t1(x FLOAT); 372eaf93d3Sdrh } 38a06f17feSdrh set ::STMT [sqlite3_prepare db "INSERT INTO t1 VALUES(?)" -1 TAIL] 39a06f17feSdrh sqlite3_bind_double $::STMT 1 NaN 40a06f17feSdrh sqlite3_step $::STMT 41a06f17feSdrh sqlite3_reset $::STMT 422eaf93d3Sdrh db eval {SELECT x, typeof(x) FROM t1} 432eaf93d3Sdrh} {{} null} 4489bae3edSdanielk1977if {$tcl_platform(platform) != "symbian"} { 4533f5379cSdan do_realnum_test nan-1.1.2 { 46a06f17feSdrh sqlite3_bind_double $::STMT 1 +Inf 47a06f17feSdrh sqlite3_step $::STMT 48a06f17feSdrh sqlite3_reset $::STMT 492eaf93d3Sdrh db eval {SELECT x, typeof(x) FROM t1} 502eaf93d3Sdrh } {{} null inf real} 5133f5379cSdan do_realnum_test nan-1.1.3 { 52a06f17feSdrh sqlite3_bind_double $::STMT 1 -Inf 53a06f17feSdrh sqlite3_step $::STMT 54a06f17feSdrh sqlite3_reset $::STMT 552eaf93d3Sdrh db eval {SELECT x, typeof(x) FROM t1} 562eaf93d3Sdrh } {{} null inf real -inf real} 5733f5379cSdan do_realnum_test nan-1.1.4 { 58a06f17feSdrh sqlite3_bind_double $::STMT 1 -NaN 59a06f17feSdrh sqlite3_step $::STMT 60a06f17feSdrh sqlite3_reset $::STMT 61a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 62a06f17feSdrh } {{} null inf real -inf real {} null} 6333f5379cSdan do_realnum_test nan-1.1.5 { 64a06f17feSdrh sqlite3_bind_double $::STMT 1 NaN0 65a06f17feSdrh sqlite3_step $::STMT 66a06f17feSdrh sqlite3_reset $::STMT 67a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 68a06f17feSdrh } {{} null inf real -inf real {} null {} null} 6933f5379cSdan do_realnum_test nan-1.1.6 { 70a06f17feSdrh sqlite3_bind_double $::STMT 1 -NaN0 71a06f17feSdrh sqlite3_step $::STMT 72a06f17feSdrh sqlite3_reset $::STMT 73a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 74a06f17feSdrh } {{} null inf real -inf real {} null {} null {} null} 75100efa3fSshaneh do_test nan-1.1.7 { 762eaf93d3Sdrh db eval { 772eaf93d3Sdrh UPDATE t1 SET x=x-x; 782eaf93d3Sdrh SELECT x, typeof(x) FROM t1; 792eaf93d3Sdrh } 80a06f17feSdrh } {{} null {} null {} null {} null {} null {} null} 8189bae3edSdanielk1977} 8289bae3edSdanielk1977 8389bae3edSdanielk1977# The following block of tests, nan-1.2.*, are the same as the nan-1.1.* 8489bae3edSdanielk1977# tests above, except that the SELECT queries used to validate data 8589bae3edSdanielk1977# convert floating point values to text internally before returning them 8689bae3edSdanielk1977# to Tcl. This allows the tests to be run on platforms where Tcl has 8789bae3edSdanielk1977# problems converting "inf" and "-inf" from floating point to text format. 8889bae3edSdanielk1977# It also tests the internal float->text conversion routines a bit. 8989bae3edSdanielk1977# 9089bae3edSdanielk1977do_test nan-1.2.1 { 9189bae3edSdanielk1977 db eval { 9289bae3edSdanielk1977 DELETE FROM T1; 9389bae3edSdanielk1977 } 9489bae3edSdanielk1977 sqlite3_bind_double $::STMT 1 NaN 9589bae3edSdanielk1977 sqlite3_step $::STMT 9689bae3edSdanielk1977 sqlite3_reset $::STMT 9789bae3edSdanielk1977 db eval {SELECT CAST(x AS text), typeof(x) FROM t1} 9889bae3edSdanielk1977} {{} null} 9989bae3edSdanielk1977do_test nan-1.2.2 { 10089bae3edSdanielk1977 sqlite3_bind_double $::STMT 1 +Inf 10189bae3edSdanielk1977 sqlite3_step $::STMT 10289bae3edSdanielk1977 sqlite3_reset $::STMT 10389bae3edSdanielk1977 db eval {SELECT CAST(x AS text), typeof(x) FROM t1} 10489bae3edSdanielk1977} {{} null Inf real} 10589bae3edSdanielk1977do_test nan-1.2.3 { 10689bae3edSdanielk1977 sqlite3_bind_double $::STMT 1 -Inf 10789bae3edSdanielk1977 sqlite3_step $::STMT 10889bae3edSdanielk1977 sqlite3_reset $::STMT 10989bae3edSdanielk1977 db eval {SELECT CAST(x AS text), typeof(x) FROM t1} 11089bae3edSdanielk1977} {{} null Inf real -Inf real} 11189bae3edSdanielk1977do_test nan-1.2.4 { 11289bae3edSdanielk1977 sqlite3_bind_double $::STMT 1 -NaN 11389bae3edSdanielk1977 sqlite3_step $::STMT 11489bae3edSdanielk1977 sqlite3_reset $::STMT 11589bae3edSdanielk1977 db eval {SELECT CAST(x AS text), typeof(x) FROM t1} 11689bae3edSdanielk1977} {{} null Inf real -Inf real {} null} 11789bae3edSdanielk1977do_test nan-1.2.5 { 11889bae3edSdanielk1977 sqlite3_bind_double $::STMT 1 NaN0 11989bae3edSdanielk1977 sqlite3_step $::STMT 12089bae3edSdanielk1977 sqlite3_reset $::STMT 12189bae3edSdanielk1977 db eval {SELECT CAST(x AS text), typeof(x) FROM t1} 12289bae3edSdanielk1977} {{} null Inf real -Inf real {} null {} null} 123100efa3fSshanehdo_test nan-1.2.6 { 12489bae3edSdanielk1977 sqlite3_bind_double $::STMT 1 -NaN0 12589bae3edSdanielk1977 sqlite3_step $::STMT 12689bae3edSdanielk1977 sqlite3_reset $::STMT 12789bae3edSdanielk1977 db eval {SELECT CAST(x AS text), typeof(x) FROM t1} 12889bae3edSdanielk1977} {{} null Inf real -Inf real {} null {} null {} null} 129100efa3fSshanehdo_test nan-1.2.7 { 13089bae3edSdanielk1977 db eval { 13189bae3edSdanielk1977 UPDATE t1 SET x=x-x; 13289bae3edSdanielk1977 SELECT CAST(x AS text), typeof(x) FROM t1; 13389bae3edSdanielk1977 } 13489bae3edSdanielk1977} {{} null {} null {} null {} null {} null {} null} 1352eaf93d3Sdrh 1362eaf93d3Sdrhdo_test nan-2.1 { 1372eaf93d3Sdrh db eval { 1382eaf93d3Sdrh DELETE FROM T1; 1392eaf93d3Sdrh } 140a06f17feSdrh sqlite3_bind_double $::STMT 1 NaN 141a06f17feSdrh sqlite3_step $::STMT 142a06f17feSdrh sqlite3_reset $::STMT 1432eaf93d3Sdrh db eval {SELECT x, typeof(x) FROM t1} 1442eaf93d3Sdrh} {{} null} 145a06f17feSdrhsqlite3_finalize $::STMT 1462eaf93d3Sdrh 1472eaf93d3Sdrh# SQLite always converts NaN into NULL so it is not possible to write 1482eaf93d3Sdrh# a NaN value into the database file using SQLite. The following series 1492eaf93d3Sdrh# of tests writes a normal floating point value (0.5) into the database, 1502eaf93d3Sdrh# then writes directly into the database file to change the 0.5 into NaN. 1512eaf93d3Sdrh# Then it reads the value of the database to verify it is converted into 1522eaf93d3Sdrh# NULL. 1532eaf93d3Sdrh# 1547da56b4fSdrhif {![nonzero_reserved_bytes]} { 1552eaf93d3Sdrh do_test nan-3.1 { 1562eaf93d3Sdrh db eval { 1572eaf93d3Sdrh DELETE FROM t1; 1582eaf93d3Sdrh INSERT INTO t1 VALUES(0.5); 1592eaf93d3Sdrh PRAGMA auto_vacuum=OFF; 1602eaf93d3Sdrh PRAGMA page_size=1024; 1612eaf93d3Sdrh VACUUM; 1622eaf93d3Sdrh } 1632eaf93d3Sdrh hexio_read test.db 2040 8 1642eaf93d3Sdrh } {3FE0000000000000} 1652eaf93d3Sdrh do_test nan-3.2 { 1662eaf93d3Sdrh db eval { 1672eaf93d3Sdrh SELECT x, typeof(x) FROM t1 1682eaf93d3Sdrh } 1692eaf93d3Sdrh } {0.5 real} 1702eaf93d3Sdrh do_test nan-3.3 { 1712eaf93d3Sdrh db close 1722eaf93d3Sdrh hexio_write test.db 2040 FFF8000000000000 1732eaf93d3Sdrh sqlite3 db test.db 1742eaf93d3Sdrh db eval {SELECT x, typeof(x) FROM t1} 1752eaf93d3Sdrh } {{} null} 176a06f17feSdrh do_test nan-3.4 { 177a06f17feSdrh db close 178a06f17feSdrh hexio_write test.db 2040 7FF8000000000000 179a06f17feSdrh sqlite3 db test.db 180a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 181a06f17feSdrh } {{} null} 182a06f17feSdrh do_test nan-3.5 { 183a06f17feSdrh db close 184a06f17feSdrh hexio_write test.db 2040 FFFFFFFFFFFFFFFF 185a06f17feSdrh sqlite3 db test.db 186a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 187a06f17feSdrh } {{} null} 188a06f17feSdrh do_test nan-3.6 { 189a06f17feSdrh db close 190a06f17feSdrh hexio_write test.db 2040 7FFFFFFFFFFFFFFF 191a06f17feSdrh sqlite3 db test.db 192a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 193a06f17feSdrh } {{} null} 1947da56b4fSdrh} 195a06f17feSdrh 196a06f17feSdrh# Verify that the sqlite3AtoF routine is able to handle extreme 197a06f17feSdrh# numbers. 198a06f17feSdrh# 199a06f17feSdrhdo_test nan-4.1 { 200a06f17feSdrh db eval {DELETE FROM t1} 201a06f17feSdrh db eval "INSERT INTO t1 VALUES([string repeat 9 307].0)" 202a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 203a06f17feSdrh} {1e+307 real} 204a06f17feSdrhdo_test nan-4.2 { 205a06f17feSdrh db eval {DELETE FROM t1} 206a06f17feSdrh db eval "INSERT INTO t1 VALUES([string repeat 9 308].0)" 207a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 208a06f17feSdrh} {1e+308 real} 209a06f17feSdrhdo_test nan-4.3 { 210a06f17feSdrh db eval {DELETE FROM t1} 211a06f17feSdrh db eval "INSERT INTO t1 VALUES(-[string repeat 9 307].0)" 212a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 213a06f17feSdrh} {-1e+307 real} 21489bae3edSdanielk1977do_test nan-4.4 { 215a06f17feSdrh db eval {DELETE FROM t1} 216a06f17feSdrh db eval "INSERT INTO t1 VALUES(-[string repeat 9 308].0)" 217a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 218a06f17feSdrh} {-1e+308 real} 21989bae3edSdanielk1977do_test nan-4.5 { 220a06f17feSdrh db eval {DELETE FROM t1} 221a06f17feSdrh set big -[string repeat 0 10000][string repeat 9 308].[string repeat 0 10000] 222a06f17feSdrh db eval "INSERT INTO t1 VALUES($big)" 223a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 224a06f17feSdrh} {-1e+308 real} 22589bae3edSdanielk1977do_test nan-4.6 { 226a06f17feSdrh db eval {DELETE FROM t1} 227a06f17feSdrh set big [string repeat 0 10000][string repeat 9 308].[string repeat 0 10000] 228a06f17feSdrh db eval "INSERT INTO t1 VALUES($big)" 229a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 230a06f17feSdrh} {1e+308 real} 231a06f17feSdrh 23289bae3edSdanielk1977if {$tcl_platform(platform) != "symbian"} { 23389bae3edSdanielk1977 # Do not run these tests on Symbian, as the Tcl port doesn't like to 23489bae3edSdanielk1977 # convert from floating point value "-inf" to a string. 23589bae3edSdanielk1977 # 23633f5379cSdan do_realnum_test nan-4.7 { 23789bae3edSdanielk1977 db eval {DELETE FROM t1} 23889bae3edSdanielk1977 db eval "INSERT INTO t1 VALUES([string repeat 9 309].0)" 23989bae3edSdanielk1977 db eval {SELECT x, typeof(x) FROM t1} 24089bae3edSdanielk1977 } {inf real} 24133f5379cSdan do_realnum_test nan-4.8 { 24289bae3edSdanielk1977 db eval {DELETE FROM t1} 24389bae3edSdanielk1977 db eval "INSERT INTO t1 VALUES(-[string repeat 9 309].0)" 24489bae3edSdanielk1977 db eval {SELECT x, typeof(x) FROM t1} 24589bae3edSdanielk1977 } {-inf real} 24689bae3edSdanielk1977} 24789bae3edSdanielk1977do_test nan-4.9 { 24889bae3edSdanielk1977 db eval {DELETE FROM t1} 24989bae3edSdanielk1977 db eval "INSERT INTO t1 VALUES([string repeat 9 309].0)" 25089bae3edSdanielk1977 db eval {SELECT CAST(x AS text), typeof(x) FROM t1} 25189bae3edSdanielk1977} {Inf real} 25289bae3edSdanielk1977do_test nan-4.10 { 25389bae3edSdanielk1977 db eval {DELETE FROM t1} 25489bae3edSdanielk1977 db eval "INSERT INTO t1 VALUES(-[string repeat 9 309].0)" 25589bae3edSdanielk1977 db eval {SELECT CAST(x AS text), typeof(x) FROM t1} 25689bae3edSdanielk1977} {-Inf real} 257a06f17feSdrh 258100efa3fSshanehdo_test nan-4.11 { 259a06f17feSdrh db eval {DELETE FROM t1} 260a06f17feSdrh db eval "INSERT INTO t1 VALUES(1234.5[string repeat 0 10000]12345)" 261a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 262a06f17feSdrh} {1234.5 real} 263100efa3fSshanehdo_test nan-4.12 { 264a06f17feSdrh db eval {DELETE FROM t1} 265a06f17feSdrh db eval "INSERT INTO t1 VALUES(-1234.5[string repeat 0 10000]12345)" 266a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 267a06f17feSdrh} {-1234.5 real} 268100efa3fSshanehdo_test nan-4.13 { 269a06f17feSdrh db eval {DELETE FROM t1} 270a06f17feSdrh set small [string repeat 0 10000].[string repeat 0 324][string repeat 9 10000] 271a06f17feSdrh db eval "INSERT INTO t1 VALUES($small)" 272a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 273a06f17feSdrh} {0.0 real} 274100efa3fSshanehdo_test nan-4.14 { 275a06f17feSdrh db eval {DELETE FROM t1} 276a06f17feSdrh set small \ 277a06f17feSdrh -[string repeat 0 10000].[string repeat 0 324][string repeat 9 10000] 278a06f17feSdrh db eval "INSERT INTO t1 VALUES($small)" 279a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 280a06f17feSdrh} {0.0 real} 281a06f17feSdrh 282b11bcfdeSdanielk1977# These tests test some really, really small floating point numbers. 283b11bcfdeSdanielk1977# 284b11bcfdeSdanielk1977if {$tcl_platform(platform) != "symbian"} { 285b11bcfdeSdanielk1977 # These two are not run on symbian because tcl has trouble converting 286b11bcfdeSdanielk1977 # the very small numbers back to text form (probably due to a difference 287b11bcfdeSdanielk1977 # in the sprintf() implementation). 288b11bcfdeSdanielk1977 # 289100efa3fSshaneh do_test nan-4.15 { 290b11bcfdeSdanielk1977 db eval {DELETE FROM t1} 291b11bcfdeSdanielk1977 set small \ 292b11bcfdeSdanielk1977 [string repeat 0 10000].[string repeat 0 323][string repeat 9 10000] 293b11bcfdeSdanielk1977 db eval "INSERT INTO t1 VALUES($small)" 294b11bcfdeSdanielk1977 db eval {SELECT x, typeof(x) FROM t1} 295b11bcfdeSdanielk1977 } {9.88131291682493e-324 real} 296100efa3fSshaneh do_test nan-4.16 { 297b11bcfdeSdanielk1977 db eval {DELETE FROM t1} 298b11bcfdeSdanielk1977 set small \ 299b11bcfdeSdanielk1977 -[string repeat 0 10000].[string repeat 0 323][string repeat 9 10000] 300b11bcfdeSdanielk1977 db eval "INSERT INTO t1 VALUES($small)" 301b11bcfdeSdanielk1977 db eval {SELECT x, typeof(x) FROM t1} 302b11bcfdeSdanielk1977 } {-9.88131291682493e-324 real} 303b11bcfdeSdanielk1977} 304100efa3fSshanehdo_test nan-4.17 { 305b11bcfdeSdanielk1977 db eval {DELETE FROM t1} 306b11bcfdeSdanielk1977 set small [string repeat 0 10000].[string repeat 0 323][string repeat 9 10000] 307b11bcfdeSdanielk1977 db eval "INSERT INTO t1 VALUES($small)" 308b11bcfdeSdanielk1977 db eval {SELECT CAST(x AS text), typeof(x) FROM t1} 309b11bcfdeSdanielk1977} {9.88131291682493e-324 real} 310100efa3fSshanehdo_test nan-4.18 { 311b11bcfdeSdanielk1977 db eval {DELETE FROM t1} 312b11bcfdeSdanielk1977 set small \ 313b11bcfdeSdanielk1977 -[string repeat 0 10000].[string repeat 0 323][string repeat 9 10000] 314b11bcfdeSdanielk1977 db eval "INSERT INTO t1 VALUES($small)" 315b11bcfdeSdanielk1977 db eval {SELECT CAST(x AS text), typeof(x) FROM t1} 316b11bcfdeSdanielk1977} {-9.88131291682493e-324 real} 317b11bcfdeSdanielk1977 31833f5379cSdando_realnum_test nan-4.20 { 319a06f17feSdrh db eval {DELETE FROM t1} 320a06f17feSdrh set big [string repeat 9 10000].0e-9000 321a06f17feSdrh db eval "INSERT INTO t1 VALUES($big)" 322a06f17feSdrh db eval {SELECT x, typeof(x) FROM t1} 3236085f5e0Sshane} {inf real} 324a06f17feSdrh 32557db4a75Sdrhdo_realnum_test nan-4.30 { 32657db4a75Sdrh db eval { 32757db4a75Sdrh DELETE FROM t1; 32857db4a75Sdrh INSERT INTO t1 VALUES('2.5e+9999'); 32957db4a75Sdrh SELECT x, typeof(x) FROM t1; 33057db4a75Sdrh } 33157db4a75Sdrh} {inf real} 33257db4a75Sdrhdo_realnum_test nan-4.31 { 33357db4a75Sdrh db eval { 33457db4a75Sdrh DELETE FROM t1; 33557db4a75Sdrh INSERT INTO t1 VALUES('2.5e+10000'); 33657db4a75Sdrh SELECT x, typeof(x) FROM t1; 33757db4a75Sdrh } 33857db4a75Sdrh} {inf real} 33957db4a75Sdrh 34057db4a75Sdrhdo_realnum_test nan-4.32 { 34157db4a75Sdrh db eval { 34257db4a75Sdrh DELETE FROM t1; 34357db4a75Sdrh INSERT INTO t1 VALUES('2.5e-9999'); 34457db4a75Sdrh SELECT x, typeof(x) FROM t1; 34557db4a75Sdrh } 34657db4a75Sdrh} {0.0 real} 34757db4a75Sdrhdo_realnum_test nan-4.33 { 34857db4a75Sdrh db eval { 34957db4a75Sdrh DELETE FROM t1; 35057db4a75Sdrh INSERT INTO t1 VALUES('2.5e-10000'); 35157db4a75Sdrh SELECT x, typeof(x) FROM t1; 35257db4a75Sdrh } 35357db4a75Sdrh} {0.0 real} 35457db4a75Sdrhdo_realnum_test nan-4.34 { 35557db4a75Sdrh db eval { 35657db4a75Sdrh DELETE FROM t1; 35757db4a75Sdrh INSERT INTO t1 VALUES('2.5e2147483650'); 35857db4a75Sdrh SELECT x, typeof(x) FROM t1; 35957db4a75Sdrh } 36057db4a75Sdrh} {inf real} 36157db4a75Sdrhdo_realnum_test nan-4.35 { 36257db4a75Sdrh db eval { 36357db4a75Sdrh DELETE FROM t1; 36457db4a75Sdrh INSERT INTO t1 VALUES('2.5e-2147483650'); 36557db4a75Sdrh SELECT x, typeof(x) FROM t1; 36657db4a75Sdrh } 36757db4a75Sdrh} {0.0 real} 36857db4a75Sdrh 369*3ba18addSdrhdo_realnum_test nan-4.40 { 370*3ba18addSdrh db eval { 371*3ba18addSdrh SELECT cast('-1e999' AS real); 372*3ba18addSdrh } 373*3ba18addSdrh} {-inf} 3742eaf93d3Sdrh 3752eaf93d3Sdrhfinish_test 376