1: # 2008 April 28
2: #
3: # The author disclaims copyright to this source code. In place of
4: # a legal notice, here is a blessing:
5: #
6: # May you do good and not evil.
7: # May you find forgiveness for yourself and forgive others.
8: # May you share freely, never taking more than you give.
9: #
10: #***********************************************************************
11: #
12: # Ticket #3060
13: #
14: # Make sure IEEE floating point NaN values are handled properly.
15: # SQLite should always convert NaN into NULL.
16: #
17: # Also verify that the decimal to IEEE754 binary conversion routines
18: # correctly generate 0.0, +Inf, and -Inf as appropriate for numbers
19: # out of range.
20: #
21: # $Id: nan.test,v 1.1.1.1 2012/02/21 17:04:16 misho Exp $
22: #
23:
24: set testdir [file dirname $argv0]
25: source $testdir/tester.tcl
26:
27: # Do not use a codec for tests in this file, as the database file is
28: # manipulated directly using tcl scripts (using the [hexio_write] command).
29: #
30: do_not_use_codec
31:
32: do_test nan-1.1.1 {
33: db eval {
34: PRAGMA auto_vacuum=OFF;
35: PRAGMA page_size=1024;
36: CREATE TABLE t1(x FLOAT);
37: }
38: set ::STMT [sqlite3_prepare db "INSERT INTO t1 VALUES(?)" -1 TAIL]
39: sqlite3_bind_double $::STMT 1 NaN
40: sqlite3_step $::STMT
41: sqlite3_reset $::STMT
42: db eval {SELECT x, typeof(x) FROM t1}
43: } {{} null}
44: if {$tcl_platform(platform) != "symbian"} {
45: do_realnum_test nan-1.1.2 {
46: sqlite3_bind_double $::STMT 1 +Inf
47: sqlite3_step $::STMT
48: sqlite3_reset $::STMT
49: db eval {SELECT x, typeof(x) FROM t1}
50: } {{} null inf real}
51: do_realnum_test nan-1.1.3 {
52: sqlite3_bind_double $::STMT 1 -Inf
53: sqlite3_step $::STMT
54: sqlite3_reset $::STMT
55: db eval {SELECT x, typeof(x) FROM t1}
56: } {{} null inf real -inf real}
57: do_realnum_test nan-1.1.4 {
58: sqlite3_bind_double $::STMT 1 -NaN
59: sqlite3_step $::STMT
60: sqlite3_reset $::STMT
61: db eval {SELECT x, typeof(x) FROM t1}
62: } {{} null inf real -inf real {} null}
63: do_realnum_test nan-1.1.5 {
64: sqlite3_bind_double $::STMT 1 NaN0
65: sqlite3_step $::STMT
66: sqlite3_reset $::STMT
67: db eval {SELECT x, typeof(x) FROM t1}
68: } {{} null inf real -inf real {} null {} null}
69: do_realnum_test nan-1.1.6 {
70: sqlite3_bind_double $::STMT 1 -NaN0
71: sqlite3_step $::STMT
72: sqlite3_reset $::STMT
73: db eval {SELECT x, typeof(x) FROM t1}
74: } {{} null inf real -inf real {} null {} null {} null}
75: do_test nan-1.1.7 {
76: db eval {
77: UPDATE t1 SET x=x-x;
78: SELECT x, typeof(x) FROM t1;
79: }
80: } {{} null {} null {} null {} null {} null {} null}
81: }
82:
83: # The following block of tests, nan-1.2.*, are the same as the nan-1.1.*
84: # tests above, except that the SELECT queries used to validate data
85: # convert floating point values to text internally before returning them
86: # to Tcl. This allows the tests to be run on platforms where Tcl has
87: # problems converting "inf" and "-inf" from floating point to text format.
88: # It also tests the internal float->text conversion routines a bit.
89: #
90: do_test nan-1.2.1 {
91: db eval {
92: DELETE FROM T1;
93: }
94: sqlite3_bind_double $::STMT 1 NaN
95: sqlite3_step $::STMT
96: sqlite3_reset $::STMT
97: db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
98: } {{} null}
99: do_test nan-1.2.2 {
100: sqlite3_bind_double $::STMT 1 +Inf
101: sqlite3_step $::STMT
102: sqlite3_reset $::STMT
103: db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
104: } {{} null Inf real}
105: do_test nan-1.2.3 {
106: sqlite3_bind_double $::STMT 1 -Inf
107: sqlite3_step $::STMT
108: sqlite3_reset $::STMT
109: db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
110: } {{} null Inf real -Inf real}
111: do_test nan-1.2.4 {
112: sqlite3_bind_double $::STMT 1 -NaN
113: sqlite3_step $::STMT
114: sqlite3_reset $::STMT
115: db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
116: } {{} null Inf real -Inf real {} null}
117: do_test nan-1.2.5 {
118: sqlite3_bind_double $::STMT 1 NaN0
119: sqlite3_step $::STMT
120: sqlite3_reset $::STMT
121: db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
122: } {{} null Inf real -Inf real {} null {} null}
123: do_test nan-1.2.6 {
124: sqlite3_bind_double $::STMT 1 -NaN0
125: sqlite3_step $::STMT
126: sqlite3_reset $::STMT
127: db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
128: } {{} null Inf real -Inf real {} null {} null {} null}
129: do_test nan-1.2.7 {
130: db eval {
131: UPDATE t1 SET x=x-x;
132: SELECT CAST(x AS text), typeof(x) FROM t1;
133: }
134: } {{} null {} null {} null {} null {} null {} null}
135:
136: do_test nan-2.1 {
137: db eval {
138: DELETE FROM T1;
139: }
140: sqlite3_bind_double $::STMT 1 NaN
141: sqlite3_step $::STMT
142: sqlite3_reset $::STMT
143: db eval {SELECT x, typeof(x) FROM t1}
144: } {{} null}
145: sqlite3_finalize $::STMT
146:
147: # SQLite always converts NaN into NULL so it is not possible to write
148: # a NaN value into the database file using SQLite. The following series
149: # of tests writes a normal floating point value (0.5) into the database,
150: # then writes directly into the database file to change the 0.5 into NaN.
151: # Then it reads the value of the database to verify it is converted into
152: # NULL.
153: #
154: do_test nan-3.1 {
155: db eval {
156: DELETE FROM t1;
157: INSERT INTO t1 VALUES(0.5);
158: PRAGMA auto_vacuum=OFF;
159: PRAGMA page_size=1024;
160: VACUUM;
161: }
162: hexio_read test.db 2040 8
163: } {3FE0000000000000}
164: do_test nan-3.2 {
165: db eval {
166: SELECT x, typeof(x) FROM t1
167: }
168: } {0.5 real}
169: do_test nan-3.3 {
170: db close
171: hexio_write test.db 2040 FFF8000000000000
172: sqlite3 db test.db
173: db eval {SELECT x, typeof(x) FROM t1}
174: } {{} null}
175: do_test nan-3.4 {
176: db close
177: hexio_write test.db 2040 7FF8000000000000
178: sqlite3 db test.db
179: db eval {SELECT x, typeof(x) FROM t1}
180: } {{} null}
181: do_test nan-3.5 {
182: db close
183: hexio_write test.db 2040 FFFFFFFFFFFFFFFF
184: sqlite3 db test.db
185: db eval {SELECT x, typeof(x) FROM t1}
186: } {{} null}
187: do_test nan-3.6 {
188: db close
189: hexio_write test.db 2040 7FFFFFFFFFFFFFFF
190: sqlite3 db test.db
191: db eval {SELECT x, typeof(x) FROM t1}
192: } {{} null}
193:
194: # Verify that the sqlite3AtoF routine is able to handle extreme
195: # numbers.
196: #
197: do_test nan-4.1 {
198: db eval {DELETE FROM t1}
199: db eval "INSERT INTO t1 VALUES([string repeat 9 307].0)"
200: db eval {SELECT x, typeof(x) FROM t1}
201: } {1e+307 real}
202: do_test nan-4.2 {
203: db eval {DELETE FROM t1}
204: db eval "INSERT INTO t1 VALUES([string repeat 9 308].0)"
205: db eval {SELECT x, typeof(x) FROM t1}
206: } {1e+308 real}
207: do_test nan-4.3 {
208: db eval {DELETE FROM t1}
209: db eval "INSERT INTO t1 VALUES(-[string repeat 9 307].0)"
210: db eval {SELECT x, typeof(x) FROM t1}
211: } {-1e+307 real}
212: do_test nan-4.4 {
213: db eval {DELETE FROM t1}
214: db eval "INSERT INTO t1 VALUES(-[string repeat 9 308].0)"
215: db eval {SELECT x, typeof(x) FROM t1}
216: } {-1e+308 real}
217: do_test nan-4.5 {
218: db eval {DELETE FROM t1}
219: set big -[string repeat 0 10000][string repeat 9 308].[string repeat 0 10000]
220: db eval "INSERT INTO t1 VALUES($big)"
221: db eval {SELECT x, typeof(x) FROM t1}
222: } {-1e+308 real}
223: do_test nan-4.6 {
224: db eval {DELETE FROM t1}
225: set big [string repeat 0 10000][string repeat 9 308].[string repeat 0 10000]
226: db eval "INSERT INTO t1 VALUES($big)"
227: db eval {SELECT x, typeof(x) FROM t1}
228: } {1e+308 real}
229:
230: if {$tcl_platform(platform) != "symbian"} {
231: # Do not run these tests on Symbian, as the Tcl port doesn't like to
232: # convert from floating point value "-inf" to a string.
233: #
234: do_realnum_test nan-4.7 {
235: db eval {DELETE FROM t1}
236: db eval "INSERT INTO t1 VALUES([string repeat 9 309].0)"
237: db eval {SELECT x, typeof(x) FROM t1}
238: } {inf real}
239: do_realnum_test nan-4.8 {
240: db eval {DELETE FROM t1}
241: db eval "INSERT INTO t1 VALUES(-[string repeat 9 309].0)"
242: db eval {SELECT x, typeof(x) FROM t1}
243: } {-inf real}
244: }
245: do_test nan-4.9 {
246: db eval {DELETE FROM t1}
247: db eval "INSERT INTO t1 VALUES([string repeat 9 309].0)"
248: db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
249: } {Inf real}
250: do_test nan-4.10 {
251: db eval {DELETE FROM t1}
252: db eval "INSERT INTO t1 VALUES(-[string repeat 9 309].0)"
253: db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
254: } {-Inf real}
255:
256: do_test nan-4.11 {
257: db eval {DELETE FROM t1}
258: db eval "INSERT INTO t1 VALUES(1234.5[string repeat 0 10000]12345)"
259: db eval {SELECT x, typeof(x) FROM t1}
260: } {1234.5 real}
261: do_test nan-4.12 {
262: db eval {DELETE FROM t1}
263: db eval "INSERT INTO t1 VALUES(-1234.5[string repeat 0 10000]12345)"
264: db eval {SELECT x, typeof(x) FROM t1}
265: } {-1234.5 real}
266: do_test nan-4.13 {
267: db eval {DELETE FROM t1}
268: set small [string repeat 0 10000].[string repeat 0 324][string repeat 9 10000]
269: db eval "INSERT INTO t1 VALUES($small)"
270: db eval {SELECT x, typeof(x) FROM t1}
271: } {0.0 real}
272: do_test nan-4.14 {
273: db eval {DELETE FROM t1}
274: set small \
275: -[string repeat 0 10000].[string repeat 0 324][string repeat 9 10000]
276: db eval "INSERT INTO t1 VALUES($small)"
277: db eval {SELECT x, typeof(x) FROM t1}
278: } {0.0 real}
279:
280: # These tests test some really, really small floating point numbers.
281: #
282: if {$tcl_platform(platform) != "symbian"} {
283: # These two are not run on symbian because tcl has trouble converting
284: # the very small numbers back to text form (probably due to a difference
285: # in the sprintf() implementation).
286: #
287: do_test nan-4.15 {
288: db eval {DELETE FROM t1}
289: set small \
290: [string repeat 0 10000].[string repeat 0 323][string repeat 9 10000]
291: db eval "INSERT INTO t1 VALUES($small)"
292: db eval {SELECT x, typeof(x) FROM t1}
293: } {9.88131291682493e-324 real}
294: do_test nan-4.16 {
295: db eval {DELETE FROM t1}
296: set small \
297: -[string repeat 0 10000].[string repeat 0 323][string repeat 9 10000]
298: db eval "INSERT INTO t1 VALUES($small)"
299: db eval {SELECT x, typeof(x) FROM t1}
300: } {-9.88131291682493e-324 real}
301: }
302: do_test nan-4.17 {
303: db eval {DELETE FROM t1}
304: set small [string repeat 0 10000].[string repeat 0 323][string repeat 9 10000]
305: db eval "INSERT INTO t1 VALUES($small)"
306: db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
307: } {9.88131291682493e-324 real}
308: do_test nan-4.18 {
309: db eval {DELETE FROM t1}
310: set small \
311: -[string repeat 0 10000].[string repeat 0 323][string repeat 9 10000]
312: db eval "INSERT INTO t1 VALUES($small)"
313: db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
314: } {-9.88131291682493e-324 real}
315:
316: do_realnum_test nan-4.20 {
317: db eval {DELETE FROM t1}
318: set big [string repeat 9 10000].0e-9000
319: db eval "INSERT INTO t1 VALUES($big)"
320: db eval {SELECT x, typeof(x) FROM t1}
321: } {inf real}
322:
323: do_realnum_test nan-4.30 {
324: db eval {
325: DELETE FROM t1;
326: INSERT INTO t1 VALUES('2.5e+9999');
327: SELECT x, typeof(x) FROM t1;
328: }
329: } {inf real}
330: do_realnum_test nan-4.31 {
331: db eval {
332: DELETE FROM t1;
333: INSERT INTO t1 VALUES('2.5e+10000');
334: SELECT x, typeof(x) FROM t1;
335: }
336: } {inf real}
337:
338: do_realnum_test nan-4.32 {
339: db eval {
340: DELETE FROM t1;
341: INSERT INTO t1 VALUES('2.5e-9999');
342: SELECT x, typeof(x) FROM t1;
343: }
344: } {0.0 real}
345: do_realnum_test nan-4.33 {
346: db eval {
347: DELETE FROM t1;
348: INSERT INTO t1 VALUES('2.5e-10000');
349: SELECT x, typeof(x) FROM t1;
350: }
351: } {0.0 real}
352: do_realnum_test nan-4.34 {
353: db eval {
354: DELETE FROM t1;
355: INSERT INTO t1 VALUES('2.5e2147483650');
356: SELECT x, typeof(x) FROM t1;
357: }
358: } {inf real}
359: do_realnum_test nan-4.35 {
360: db eval {
361: DELETE FROM t1;
362: INSERT INTO t1 VALUES('2.5e-2147483650');
363: SELECT x, typeof(x) FROM t1;
364: }
365: } {0.0 real}
366:
367:
368:
369:
370:
371: finish_test
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>