1: # 2001 September 15
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: # This file implements regression tests for SQLite library. The
12: # focus of this file is testing built-in functions.
13: #
14:
15: set testdir [file dirname $argv0]
16: source $testdir/tester.tcl
17:
18: # Create a table to work with.
19: #
20: do_test func-0.0 {
21: execsql {CREATE TABLE tbl1(t1 text)}
22: foreach word {this program is free software} {
23: execsql "INSERT INTO tbl1 VALUES('$word')"
24: }
25: execsql {SELECT t1 FROM tbl1 ORDER BY t1}
26: } {free is program software this}
27: do_test func-0.1 {
28: execsql {
29: CREATE TABLE t2(a);
30: INSERT INTO t2 VALUES(1);
31: INSERT INTO t2 VALUES(NULL);
32: INSERT INTO t2 VALUES(345);
33: INSERT INTO t2 VALUES(NULL);
34: INSERT INTO t2 VALUES(67890);
35: SELECT * FROM t2;
36: }
37: } {1 {} 345 {} 67890}
38:
39: # Check out the length() function
40: #
41: do_test func-1.0 {
42: execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
43: } {4 2 7 8 4}
44: do_test func-1.1 {
45: set r [catch {execsql {SELECT length(*) FROM tbl1 ORDER BY t1}} msg]
46: lappend r $msg
47: } {1 {wrong number of arguments to function length()}}
48: do_test func-1.2 {
49: set r [catch {execsql {SELECT length(t1,5) FROM tbl1 ORDER BY t1}} msg]
50: lappend r $msg
51: } {1 {wrong number of arguments to function length()}}
52: do_test func-1.3 {
53: execsql {SELECT length(t1), count(*) FROM tbl1 GROUP BY length(t1)
54: ORDER BY length(t1)}
55: } {2 1 4 2 7 1 8 1}
56: do_test func-1.4 {
57: execsql {SELECT coalesce(length(a),-1) FROM t2}
58: } {1 -1 3 -1 5}
59:
60: # Check out the substr() function
61: #
62: do_test func-2.0 {
63: execsql {SELECT substr(t1,1,2) FROM tbl1 ORDER BY t1}
64: } {fr is pr so th}
65: do_test func-2.1 {
66: execsql {SELECT substr(t1,2,1) FROM tbl1 ORDER BY t1}
67: } {r s r o h}
68: do_test func-2.2 {
69: execsql {SELECT substr(t1,3,3) FROM tbl1 ORDER BY t1}
70: } {ee {} ogr ftw is}
71: do_test func-2.3 {
72: execsql {SELECT substr(t1,-1,1) FROM tbl1 ORDER BY t1}
73: } {e s m e s}
74: do_test func-2.4 {
75: execsql {SELECT substr(t1,-1,2) FROM tbl1 ORDER BY t1}
76: } {e s m e s}
77: do_test func-2.5 {
78: execsql {SELECT substr(t1,-2,1) FROM tbl1 ORDER BY t1}
79: } {e i a r i}
80: do_test func-2.6 {
81: execsql {SELECT substr(t1,-2,2) FROM tbl1 ORDER BY t1}
82: } {ee is am re is}
83: do_test func-2.7 {
84: execsql {SELECT substr(t1,-4,2) FROM tbl1 ORDER BY t1}
85: } {fr {} gr wa th}
86: do_test func-2.8 {
87: execsql {SELECT t1 FROM tbl1 ORDER BY substr(t1,2,20)}
88: } {this software free program is}
89: do_test func-2.9 {
90: execsql {SELECT substr(a,1,1) FROM t2}
91: } {1 {} 3 {} 6}
92: do_test func-2.10 {
93: execsql {SELECT substr(a,2,2) FROM t2}
94: } {{} {} 45 {} 78}
95:
96: # Only do the following tests if TCL has UTF-8 capabilities
97: #
98: if {"\u1234"!="u1234"} {
99:
100: # Put some UTF-8 characters in the database
101: #
102: do_test func-3.0 {
103: execsql {DELETE FROM tbl1}
104: foreach word "contains UTF-8 characters hi\u1234ho" {
105: execsql "INSERT INTO tbl1 VALUES('$word')"
106: }
107: execsql {SELECT t1 FROM tbl1 ORDER BY t1}
108: } "UTF-8 characters contains hi\u1234ho"
109: do_test func-3.1 {
110: execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
111: } {5 10 8 5}
112: do_test func-3.2 {
113: execsql {SELECT substr(t1,1,2) FROM tbl1 ORDER BY t1}
114: } {UT ch co hi}
115: do_test func-3.3 {
116: execsql {SELECT substr(t1,1,3) FROM tbl1 ORDER BY t1}
117: } "UTF cha con hi\u1234"
118: do_test func-3.4 {
119: execsql {SELECT substr(t1,2,2) FROM tbl1 ORDER BY t1}
120: } "TF ha on i\u1234"
121: do_test func-3.5 {
122: execsql {SELECT substr(t1,2,3) FROM tbl1 ORDER BY t1}
123: } "TF- har ont i\u1234h"
124: do_test func-3.6 {
125: execsql {SELECT substr(t1,3,2) FROM tbl1 ORDER BY t1}
126: } "F- ar nt \u1234h"
127: do_test func-3.7 {
128: execsql {SELECT substr(t1,4,2) FROM tbl1 ORDER BY t1}
129: } "-8 ra ta ho"
130: do_test func-3.8 {
131: execsql {SELECT substr(t1,-1,1) FROM tbl1 ORDER BY t1}
132: } "8 s s o"
133: do_test func-3.9 {
134: execsql {SELECT substr(t1,-3,2) FROM tbl1 ORDER BY t1}
135: } "F- er in \u1234h"
136: do_test func-3.10 {
137: execsql {SELECT substr(t1,-4,3) FROM tbl1 ORDER BY t1}
138: } "TF- ter ain i\u1234h"
139: do_test func-3.99 {
140: execsql {DELETE FROM tbl1}
141: foreach word {this program is free software} {
142: execsql "INSERT INTO tbl1 VALUES('$word')"
143: }
144: execsql {SELECT t1 FROM tbl1}
145: } {this program is free software}
146:
147: } ;# End \u1234!=u1234
148:
149: # Test the abs() and round() functions.
150: #
151: ifcapable !floatingpoint {
152: do_test func-4.1 {
153: execsql {
154: CREATE TABLE t1(a,b,c);
155: INSERT INTO t1 VALUES(1,2,3);
156: INSERT INTO t1 VALUES(2,12345678901234,-1234567890);
157: INSERT INTO t1 VALUES(3,-2,-5);
158: }
159: catchsql {SELECT abs(a,b) FROM t1}
160: } {1 {wrong number of arguments to function abs()}}
161: }
162: ifcapable floatingpoint {
163: do_test func-4.1 {
164: execsql {
165: CREATE TABLE t1(a,b,c);
166: INSERT INTO t1 VALUES(1,2,3);
167: INSERT INTO t1 VALUES(2,1.2345678901234,-12345.67890);
168: INSERT INTO t1 VALUES(3,-2,-5);
169: }
170: catchsql {SELECT abs(a,b) FROM t1}
171: } {1 {wrong number of arguments to function abs()}}
172: }
173: do_test func-4.2 {
174: catchsql {SELECT abs() FROM t1}
175: } {1 {wrong number of arguments to function abs()}}
176: ifcapable floatingpoint {
177: do_test func-4.3 {
178: catchsql {SELECT abs(b) FROM t1 ORDER BY a}
179: } {0 {2 1.2345678901234 2}}
180: do_test func-4.4 {
181: catchsql {SELECT abs(c) FROM t1 ORDER BY a}
182: } {0 {3 12345.6789 5}}
183: }
184: ifcapable !floatingpoint {
185: if {[working_64bit_int]} {
186: do_test func-4.3 {
187: catchsql {SELECT abs(b) FROM t1 ORDER BY a}
188: } {0 {2 12345678901234 2}}
189: }
190: do_test func-4.4 {
191: catchsql {SELECT abs(c) FROM t1 ORDER BY a}
192: } {0 {3 1234567890 5}}
193: }
194: do_test func-4.4.1 {
195: execsql {SELECT abs(a) FROM t2}
196: } {1 {} 345 {} 67890}
197: do_test func-4.4.2 {
198: execsql {SELECT abs(t1) FROM tbl1}
199: } {0.0 0.0 0.0 0.0 0.0}
200:
201: ifcapable floatingpoint {
202: do_test func-4.5 {
203: catchsql {SELECT round(a,b,c) FROM t1}
204: } {1 {wrong number of arguments to function round()}}
205: do_test func-4.6 {
206: catchsql {SELECT round(b,2) FROM t1 ORDER BY b}
207: } {0 {-2.0 1.23 2.0}}
208: do_test func-4.7 {
209: catchsql {SELECT round(b,0) FROM t1 ORDER BY a}
210: } {0 {2.0 1.0 -2.0}}
211: do_test func-4.8 {
212: catchsql {SELECT round(c) FROM t1 ORDER BY a}
213: } {0 {3.0 -12346.0 -5.0}}
214: do_test func-4.9 {
215: catchsql {SELECT round(c,a) FROM t1 ORDER BY a}
216: } {0 {3.0 -12345.68 -5.0}}
217: do_test func-4.10 {
218: catchsql {SELECT 'x' || round(c,a) || 'y' FROM t1 ORDER BY a}
219: } {0 {x3.0y x-12345.68y x-5.0y}}
220: do_test func-4.11 {
221: catchsql {SELECT round() FROM t1 ORDER BY a}
222: } {1 {wrong number of arguments to function round()}}
223: do_test func-4.12 {
224: execsql {SELECT coalesce(round(a,2),'nil') FROM t2}
225: } {1.0 nil 345.0 nil 67890.0}
226: do_test func-4.13 {
227: execsql {SELECT round(t1,2) FROM tbl1}
228: } {0.0 0.0 0.0 0.0 0.0}
229: do_test func-4.14 {
230: execsql {SELECT typeof(round(5.1,1));}
231: } {real}
232: do_test func-4.15 {
233: execsql {SELECT typeof(round(5.1));}
234: } {real}
235: do_test func-4.16 {
236: catchsql {SELECT round(b,2.0) FROM t1 ORDER BY b}
237: } {0 {-2.0 1.23 2.0}}
238: # Verify some values reported on the mailing list.
239: # Some of these fail on MSVC builds with 64-bit
240: # long doubles, but not on GCC builds with 80-bit
241: # long doubles.
242: for {set i 1} {$i<999} {incr i} {
243: set x1 [expr 40222.5 + $i]
244: set x2 [expr 40223.0 + $i]
245: do_test func-4.17.$i {
246: execsql {SELECT round($x1);}
247: } $x2
248: }
249: for {set i 1} {$i<999} {incr i} {
250: set x1 [expr 40222.05 + $i]
251: set x2 [expr 40222.10 + $i]
252: do_test func-4.18.$i {
253: execsql {SELECT round($x1,1);}
254: } $x2
255: }
256: do_test func-4.20 {
257: execsql {SELECT round(40223.4999999999);}
258: } {40223.0}
259: do_test func-4.21 {
260: execsql {SELECT round(40224.4999999999);}
261: } {40224.0}
262: do_test func-4.22 {
263: execsql {SELECT round(40225.4999999999);}
264: } {40225.0}
265: for {set i 1} {$i<10} {incr i} {
266: do_test func-4.23.$i {
267: execsql {SELECT round(40223.4999999999,$i);}
268: } {40223.5}
269: do_test func-4.24.$i {
270: execsql {SELECT round(40224.4999999999,$i);}
271: } {40224.5}
272: do_test func-4.25.$i {
273: execsql {SELECT round(40225.4999999999,$i);}
274: } {40225.5}
275: }
276: for {set i 10} {$i<32} {incr i} {
277: do_test func-4.26.$i {
278: execsql {SELECT round(40223.4999999999,$i);}
279: } {40223.4999999999}
280: do_test func-4.27.$i {
281: execsql {SELECT round(40224.4999999999,$i);}
282: } {40224.4999999999}
283: do_test func-4.28.$i {
284: execsql {SELECT round(40225.4999999999,$i);}
285: } {40225.4999999999}
286: }
287: do_test func-4.29 {
288: execsql {SELECT round(1234567890.5);}
289: } {1234567891.0}
290: do_test func-4.30 {
291: execsql {SELECT round(12345678901.5);}
292: } {12345678902.0}
293: do_test func-4.31 {
294: execsql {SELECT round(123456789012.5);}
295: } {123456789013.0}
296: do_test func-4.32 {
297: execsql {SELECT round(1234567890123.5);}
298: } {1234567890124.0}
299: do_test func-4.33 {
300: execsql {SELECT round(12345678901234.5);}
301: } {12345678901235.0}
302: do_test func-4.34 {
303: execsql {SELECT round(1234567890123.35,1);}
304: } {1234567890123.4}
305: do_test func-4.35 {
306: execsql {SELECT round(1234567890123.445,2);}
307: } {1234567890123.45}
308: do_test func-4.36 {
309: execsql {SELECT round(99999999999994.5);}
310: } {99999999999995.0}
311: do_test func-4.37 {
312: execsql {SELECT round(9999999999999.55,1);}
313: } {9999999999999.6}
314: do_test func-4.38 {
315: execsql {SELECT round(9999999999999.555,2);}
316: } {9999999999999.56}
317: }
318:
319: # Test the upper() and lower() functions
320: #
321: do_test func-5.1 {
322: execsql {SELECT upper(t1) FROM tbl1}
323: } {THIS PROGRAM IS FREE SOFTWARE}
324: do_test func-5.2 {
325: execsql {SELECT lower(upper(t1)) FROM tbl1}
326: } {this program is free software}
327: do_test func-5.3 {
328: execsql {SELECT upper(a), lower(a) FROM t2}
329: } {1 1 {} {} 345 345 {} {} 67890 67890}
330: ifcapable !icu {
331: do_test func-5.4 {
332: catchsql {SELECT upper(a,5) FROM t2}
333: } {1 {wrong number of arguments to function upper()}}
334: }
335: do_test func-5.5 {
336: catchsql {SELECT upper(*) FROM t2}
337: } {1 {wrong number of arguments to function upper()}}
338:
339: # Test the coalesce() and nullif() functions
340: #
341: do_test func-6.1 {
342: execsql {SELECT coalesce(a,'xyz') FROM t2}
343: } {1 xyz 345 xyz 67890}
344: do_test func-6.2 {
345: execsql {SELECT coalesce(upper(a),'nil') FROM t2}
346: } {1 nil 345 nil 67890}
347: do_test func-6.3 {
348: execsql {SELECT coalesce(nullif(1,1),'nil')}
349: } {nil}
350: do_test func-6.4 {
351: execsql {SELECT coalesce(nullif(1,2),'nil')}
352: } {1}
353: do_test func-6.5 {
354: execsql {SELECT coalesce(nullif(1,NULL),'nil')}
355: } {1}
356:
357:
358: # Test the last_insert_rowid() function
359: #
360: do_test func-7.1 {
361: execsql {SELECT last_insert_rowid()}
362: } [db last_insert_rowid]
363:
364: # Tests for aggregate functions and how they handle NULLs.
365: #
366: ifcapable floatingpoint {
367: do_test func-8.1 {
368: ifcapable explain {
369: execsql {EXPLAIN SELECT sum(a) FROM t2;}
370: }
371: execsql {
372: SELECT sum(a), count(a), round(avg(a),2), min(a), max(a), count(*) FROM t2;
373: }
374: } {68236 3 22745.33 1 67890 5}
375: }
376: ifcapable !floatingpoint {
377: do_test func-8.1 {
378: ifcapable explain {
379: execsql {EXPLAIN SELECT sum(a) FROM t2;}
380: }
381: execsql {
382: SELECT sum(a), count(a), avg(a), min(a), max(a), count(*) FROM t2;
383: }
384: } {68236 3 22745.0 1 67890 5}
385: }
386: do_test func-8.2 {
387: execsql {
388: SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t2;
389: }
390: } {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
391:
392: ifcapable tempdb {
393: do_test func-8.3 {
394: execsql {
395: CREATE TEMP TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
396: SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
397: }
398: } {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
399: } else {
400: do_test func-8.3 {
401: execsql {
402: CREATE TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
403: SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
404: }
405: } {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
406: }
407: do_test func-8.4 {
408: execsql {
409: SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
410: }
411: } {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
412: ifcapable compound {
413: do_test func-8.5 {
414: execsql {
415: SELECT sum(x) FROM (SELECT '9223372036' || '854775807' AS x
416: UNION ALL SELECT -9223372036854775807)
417: }
418: } {0}
419: do_test func-8.6 {
420: execsql {
421: SELECT typeof(sum(x)) FROM (SELECT '9223372036' || '854775807' AS x
422: UNION ALL SELECT -9223372036854775807)
423: }
424: } {integer}
425: do_test func-8.7 {
426: execsql {
427: SELECT typeof(sum(x)) FROM (SELECT '9223372036' || '854775808' AS x
428: UNION ALL SELECT -9223372036854775807)
429: }
430: } {real}
431: ifcapable floatingpoint {
432: do_test func-8.8 {
433: execsql {
434: SELECT sum(x)>0.0 FROM (SELECT '9223372036' || '854775808' AS x
435: UNION ALL SELECT -9223372036850000000)
436: }
437: } {1}
438: }
439: ifcapable !floatingpoint {
440: do_test func-8.8 {
441: execsql {
442: SELECT sum(x)>0 FROM (SELECT '9223372036' || '854775808' AS x
443: UNION ALL SELECT -9223372036850000000)
444: }
445: } {1}
446: }
447: }
448:
449: # How do you test the random() function in a meaningful, deterministic way?
450: #
451: do_test func-9.1 {
452: execsql {
453: SELECT random() is not null;
454: }
455: } {1}
456: do_test func-9.2 {
457: execsql {
458: SELECT typeof(random());
459: }
460: } {integer}
461: do_test func-9.3 {
462: execsql {
463: SELECT randomblob(32) is not null;
464: }
465: } {1}
466: do_test func-9.4 {
467: execsql {
468: SELECT typeof(randomblob(32));
469: }
470: } {blob}
471: do_test func-9.5 {
472: execsql {
473: SELECT length(randomblob(32)), length(randomblob(-5)),
474: length(randomblob(2000))
475: }
476: } {32 1 2000}
477:
478: # The "hex()" function was added in order to be able to render blobs
479: # generated by randomblob(). So this seems like a good place to test
480: # hex().
481: #
482: ifcapable bloblit {
483: do_test func-9.10 {
484: execsql {SELECT hex(x'00112233445566778899aAbBcCdDeEfF')}
485: } {00112233445566778899AABBCCDDEEFF}
486: }
487: set encoding [db one {PRAGMA encoding}]
488: if {$encoding=="UTF-16le"} {
489: do_test func-9.11-utf16le {
490: execsql {SELECT hex(replace('abcdefg','ef','12'))}
491: } {6100620063006400310032006700}
492: do_test func-9.12-utf16le {
493: execsql {SELECT hex(replace('abcdefg','','12'))}
494: } {6100620063006400650066006700}
495: do_test func-9.13-utf16le {
496: execsql {SELECT hex(replace('aabcdefg','a','aaa'))}
497: } {610061006100610061006100620063006400650066006700}
498: } elseif {$encoding=="UTF-8"} {
499: do_test func-9.11-utf8 {
500: execsql {SELECT hex(replace('abcdefg','ef','12'))}
501: } {61626364313267}
502: do_test func-9.12-utf8 {
503: execsql {SELECT hex(replace('abcdefg','','12'))}
504: } {61626364656667}
505: do_test func-9.13-utf8 {
506: execsql {SELECT hex(replace('aabcdefg','a','aaa'))}
507: } {616161616161626364656667}
508: }
509:
510: # Use the "sqlite_register_test_function" TCL command which is part of
511: # the text fixture in order to verify correct operation of some of
512: # the user-defined SQL function APIs that are not used by the built-in
513: # functions.
514: #
515: set ::DB [sqlite3_connection_pointer db]
516: sqlite_register_test_function $::DB testfunc
517: do_test func-10.1 {
518: catchsql {
519: SELECT testfunc(NULL,NULL);
520: }
521: } {1 {first argument should be one of: int int64 string double null value}}
522: do_test func-10.2 {
523: execsql {
524: SELECT testfunc(
525: 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
526: 'int', 1234
527: );
528: }
529: } {1234}
530: do_test func-10.3 {
531: execsql {
532: SELECT testfunc(
533: 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
534: 'string', NULL
535: );
536: }
537: } {{}}
538:
539: ifcapable floatingpoint {
540: do_test func-10.4 {
541: execsql {
542: SELECT testfunc(
543: 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
544: 'double', 1.234
545: );
546: }
547: } {1.234}
548: do_test func-10.5 {
549: execsql {
550: SELECT testfunc(
551: 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
552: 'int', 1234,
553: 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
554: 'string', NULL,
555: 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
556: 'double', 1.234,
557: 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
558: 'int', 1234,
559: 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
560: 'string', NULL,
561: 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
562: 'double', 1.234
563: );
564: }
565: } {1.234}
566: }
567:
568: # Test the built-in sqlite_version(*) SQL function.
569: #
570: do_test func-11.1 {
571: execsql {
572: SELECT sqlite_version(*);
573: }
574: } [sqlite3 -version]
575:
576: # Test that destructors passed to sqlite3 by calls to sqlite3_result_text()
577: # etc. are called. These tests use two special user-defined functions
578: # (implemented in func.c) only available in test builds.
579: #
580: # Function test_destructor() takes one argument and returns a copy of the
581: # text form of that argument. A destructor is associated with the return
582: # value. Function test_destructor_count() returns the number of outstanding
583: # destructor calls for values returned by test_destructor().
584: #
585: if {[db eval {PRAGMA encoding}]=="UTF-8"} {
586: do_test func-12.1-utf8 {
587: execsql {
588: SELECT test_destructor('hello world'), test_destructor_count();
589: }
590: } {{hello world} 1}
591: } else {
592: ifcapable {utf16} {
593: do_test func-12.1-utf16 {
594: execsql {
595: SELECT test_destructor16('hello world'), test_destructor_count();
596: }
597: } {{hello world} 1}
598: }
599: }
600: do_test func-12.2 {
601: execsql {
602: SELECT test_destructor_count();
603: }
604: } {0}
605: do_test func-12.3 {
606: execsql {
607: SELECT test_destructor('hello')||' world'
608: }
609: } {{hello world}}
610: do_test func-12.4 {
611: execsql {
612: SELECT test_destructor_count();
613: }
614: } {0}
615: do_test func-12.5 {
616: execsql {
617: CREATE TABLE t4(x);
618: INSERT INTO t4 VALUES(test_destructor('hello'));
619: INSERT INTO t4 VALUES(test_destructor('world'));
620: SELECT min(test_destructor(x)), max(test_destructor(x)) FROM t4;
621: }
622: } {hello world}
623: do_test func-12.6 {
624: execsql {
625: SELECT test_destructor_count();
626: }
627: } {0}
628: do_test func-12.7 {
629: execsql {
630: DROP TABLE t4;
631: }
632: } {}
633:
634:
635: # Test that the auxdata API for scalar functions works. This test uses
636: # a special user-defined function only available in test builds,
637: # test_auxdata(). Function test_auxdata() takes any number of arguments.
638: do_test func-13.1 {
639: execsql {
640: SELECT test_auxdata('hello world');
641: }
642: } {0}
643:
644: do_test func-13.2 {
645: execsql {
646: CREATE TABLE t4(a, b);
647: INSERT INTO t4 VALUES('abc', 'def');
648: INSERT INTO t4 VALUES('ghi', 'jkl');
649: }
650: } {}
651: do_test func-13.3 {
652: execsql {
653: SELECT test_auxdata('hello world') FROM t4;
654: }
655: } {0 1}
656: do_test func-13.4 {
657: execsql {
658: SELECT test_auxdata('hello world', 123) FROM t4;
659: }
660: } {{0 0} {1 1}}
661: do_test func-13.5 {
662: execsql {
663: SELECT test_auxdata('hello world', a) FROM t4;
664: }
665: } {{0 0} {1 0}}
666: do_test func-13.6 {
667: execsql {
668: SELECT test_auxdata('hello'||'world', a) FROM t4;
669: }
670: } {{0 0} {1 0}}
671:
672: # Test that auxilary data is preserved between calls for SQL variables.
673: do_test func-13.7 {
674: set DB [sqlite3_connection_pointer db]
675: set sql "SELECT test_auxdata( ? , a ) FROM t4;"
676: set STMT [sqlite3_prepare $DB $sql -1 TAIL]
677: sqlite3_bind_text $STMT 1 hello\000 -1
678: set res [list]
679: while { "SQLITE_ROW"==[sqlite3_step $STMT] } {
680: lappend res [sqlite3_column_text $STMT 0]
681: }
682: lappend res [sqlite3_finalize $STMT]
683: } {{0 0} {1 0} SQLITE_OK}
684:
685: # Make sure that a function with a very long name is rejected
686: do_test func-14.1 {
687: catch {
688: db function [string repeat X 254] {return "hello"}
689: }
690: } {0}
691: do_test func-14.2 {
692: catch {
693: db function [string repeat X 256] {return "hello"}
694: }
695: } {1}
696:
697: do_test func-15.1 {
698: catchsql {select test_error(NULL)}
699: } {1 {}}
700: do_test func-15.2 {
701: catchsql {select test_error('this is the error message')}
702: } {1 {this is the error message}}
703: do_test func-15.3 {
704: catchsql {select test_error('this is the error message',12)}
705: } {1 {this is the error message}}
706: do_test func-15.4 {
707: db errorcode
708: } {12}
709:
710: # Test the quote function for BLOB and NULL values.
711: do_test func-16.1 {
712: execsql {
713: CREATE TABLE tbl2(a, b);
714: }
715: set STMT [sqlite3_prepare $::DB "INSERT INTO tbl2 VALUES(?, ?)" -1 TAIL]
716: sqlite3_bind_blob $::STMT 1 abc 3
717: sqlite3_step $::STMT
718: sqlite3_finalize $::STMT
719: execsql {
720: SELECT quote(a), quote(b) FROM tbl2;
721: }
722: } {X'616263' NULL}
723:
724: # Correctly handle function error messages that include %. Ticket #1354
725: #
726: do_test func-17.1 {
727: proc testfunc1 args {error "Error %d with %s percents %p"}
728: db function testfunc1 ::testfunc1
729: catchsql {
730: SELECT testfunc1(1,2,3);
731: }
732: } {1 {Error %d with %s percents %p}}
733:
734: # The SUM function should return integer results when all inputs are integer.
735: #
736: do_test func-18.1 {
737: execsql {
738: CREATE TABLE t5(x);
739: INSERT INTO t5 VALUES(1);
740: INSERT INTO t5 VALUES(-99);
741: INSERT INTO t5 VALUES(10000);
742: SELECT sum(x) FROM t5;
743: }
744: } {9902}
745: ifcapable floatingpoint {
746: do_test func-18.2 {
747: execsql {
748: INSERT INTO t5 VALUES(0.0);
749: SELECT sum(x) FROM t5;
750: }
751: } {9902.0}
752: }
753:
754: # The sum of nothing is NULL. But the sum of all NULLs is NULL.
755: #
756: # The TOTAL of nothing is 0.0.
757: #
758: do_test func-18.3 {
759: execsql {
760: DELETE FROM t5;
761: SELECT sum(x), total(x) FROM t5;
762: }
763: } {{} 0.0}
764: do_test func-18.4 {
765: execsql {
766: INSERT INTO t5 VALUES(NULL);
767: SELECT sum(x), total(x) FROM t5
768: }
769: } {{} 0.0}
770: do_test func-18.5 {
771: execsql {
772: INSERT INTO t5 VALUES(NULL);
773: SELECT sum(x), total(x) FROM t5
774: }
775: } {{} 0.0}
776: do_test func-18.6 {
777: execsql {
778: INSERT INTO t5 VALUES(123);
779: SELECT sum(x), total(x) FROM t5
780: }
781: } {123 123.0}
782:
783: # Ticket #1664, #1669, #1670, #1674: An integer overflow on SUM causes
784: # an error. The non-standard TOTAL() function continues to give a helpful
785: # result.
786: #
787: do_test func-18.10 {
788: execsql {
789: CREATE TABLE t6(x INTEGER);
790: INSERT INTO t6 VALUES(1);
791: INSERT INTO t6 VALUES(1<<62);
792: SELECT sum(x) - ((1<<62)+1) from t6;
793: }
794: } 0
795: do_test func-18.11 {
796: execsql {
797: SELECT typeof(sum(x)) FROM t6
798: }
799: } integer
800: ifcapable floatingpoint {
801: do_test func-18.12 {
802: catchsql {
803: INSERT INTO t6 VALUES(1<<62);
804: SELECT sum(x) - ((1<<62)*2.0+1) from t6;
805: }
806: } {1 {integer overflow}}
807: do_test func-18.13 {
808: execsql {
809: SELECT total(x) - ((1<<62)*2.0+1) FROM t6
810: }
811: } 0.0
812: }
813: ifcapable !floatingpoint {
814: do_test func-18.12 {
815: catchsql {
816: INSERT INTO t6 VALUES(1<<62);
817: SELECT sum(x) - ((1<<62)*2+1) from t6;
818: }
819: } {1 {integer overflow}}
820: do_test func-18.13 {
821: execsql {
822: SELECT total(x) - ((1<<62)*2+1) FROM t6
823: }
824: } 0.0
825: }
826: if {[working_64bit_int]} {
827: do_test func-18.14 {
828: execsql {
829: SELECT sum(-9223372036854775805);
830: }
831: } -9223372036854775805
832: }
833: ifcapable compound&&subquery {
834:
835: do_test func-18.15 {
836: catchsql {
837: SELECT sum(x) FROM
838: (SELECT 9223372036854775807 AS x UNION ALL
839: SELECT 10 AS x);
840: }
841: } {1 {integer overflow}}
842: if {[working_64bit_int]} {
843: do_test func-18.16 {
844: catchsql {
845: SELECT sum(x) FROM
846: (SELECT 9223372036854775807 AS x UNION ALL
847: SELECT -10 AS x);
848: }
849: } {0 9223372036854775797}
850: do_test func-18.17 {
851: catchsql {
852: SELECT sum(x) FROM
853: (SELECT -9223372036854775807 AS x UNION ALL
854: SELECT 10 AS x);
855: }
856: } {0 -9223372036854775797}
857: }
858: do_test func-18.18 {
859: catchsql {
860: SELECT sum(x) FROM
861: (SELECT -9223372036854775807 AS x UNION ALL
862: SELECT -10 AS x);
863: }
864: } {1 {integer overflow}}
865: do_test func-18.19 {
866: catchsql {
867: SELECT sum(x) FROM (SELECT 9 AS x UNION ALL SELECT -10 AS x);
868: }
869: } {0 -1}
870: do_test func-18.20 {
871: catchsql {
872: SELECT sum(x) FROM (SELECT -9 AS x UNION ALL SELECT 10 AS x);
873: }
874: } {0 1}
875: do_test func-18.21 {
876: catchsql {
877: SELECT sum(x) FROM (SELECT -10 AS x UNION ALL SELECT 9 AS x);
878: }
879: } {0 -1}
880: do_test func-18.22 {
881: catchsql {
882: SELECT sum(x) FROM (SELECT 10 AS x UNION ALL SELECT -9 AS x);
883: }
884: } {0 1}
885:
886: } ;# ifcapable compound&&subquery
887:
888: # Integer overflow on abs()
889: #
890: if {[working_64bit_int]} {
891: do_test func-18.31 {
892: catchsql {
893: SELECT abs(-9223372036854775807);
894: }
895: } {0 9223372036854775807}
896: }
897: do_test func-18.32 {
898: catchsql {
899: SELECT abs(-9223372036854775807-1);
900: }
901: } {1 {integer overflow}}
902:
903: # The MATCH function exists but is only a stub and always throws an error.
904: #
905: do_test func-19.1 {
906: execsql {
907: SELECT match(a,b) FROM t1 WHERE 0;
908: }
909: } {}
910: do_test func-19.2 {
911: catchsql {
912: SELECT 'abc' MATCH 'xyz';
913: }
914: } {1 {unable to use function MATCH in the requested context}}
915: do_test func-19.3 {
916: catchsql {
917: SELECT 'abc' NOT MATCH 'xyz';
918: }
919: } {1 {unable to use function MATCH in the requested context}}
920: do_test func-19.4 {
921: catchsql {
922: SELECT match(1,2,3);
923: }
924: } {1 {wrong number of arguments to function match()}}
925:
926: # Soundex tests.
927: #
928: if {![catch {db eval {SELECT soundex('hello')}}]} {
929: set i 0
930: foreach {name sdx} {
931: euler E460
932: EULER E460
933: Euler E460
934: ellery E460
935: gauss G200
936: ghosh G200
937: hilbert H416
938: Heilbronn H416
939: knuth K530
940: kant K530
941: Lloyd L300
942: LADD L300
943: Lukasiewicz L222
944: Lissajous L222
945: A A000
946: 12345 ?000
947: } {
948: incr i
949: do_test func-20.$i {
950: execsql {SELECT soundex($name)}
951: } $sdx
952: }
953: }
954:
955: # Tests of the REPLACE function.
956: #
957: do_test func-21.1 {
958: catchsql {
959: SELECT replace(1,2);
960: }
961: } {1 {wrong number of arguments to function replace()}}
962: do_test func-21.2 {
963: catchsql {
964: SELECT replace(1,2,3,4);
965: }
966: } {1 {wrong number of arguments to function replace()}}
967: do_test func-21.3 {
968: execsql {
969: SELECT typeof(replace("This is the main test string", NULL, "ALT"));
970: }
971: } {null}
972: do_test func-21.4 {
973: execsql {
974: SELECT typeof(replace(NULL, "main", "ALT"));
975: }
976: } {null}
977: do_test func-21.5 {
978: execsql {
979: SELECT typeof(replace("This is the main test string", "main", NULL));
980: }
981: } {null}
982: do_test func-21.6 {
983: execsql {
984: SELECT replace("This is the main test string", "main", "ALT");
985: }
986: } {{This is the ALT test string}}
987: do_test func-21.7 {
988: execsql {
989: SELECT replace("This is the main test string", "main", "larger-main");
990: }
991: } {{This is the larger-main test string}}
992: do_test func-21.8 {
993: execsql {
994: SELECT replace("aaaaaaa", "a", "0123456789");
995: }
996: } {0123456789012345678901234567890123456789012345678901234567890123456789}
997:
998: ifcapable tclvar {
999: do_test func-21.9 {
1000: # Attempt to exploit a buffer-overflow that at one time existed
1001: # in the REPLACE function.
1002: set ::str "[string repeat A 29998]CC[string repeat A 35537]"
1003: set ::rep [string repeat B 65536]
1004: execsql {
1005: SELECT LENGTH(REPLACE($::str, 'C', $::rep));
1006: }
1007: } [expr 29998 + 2*65536 + 35537]
1008: }
1009:
1010: # Tests for the TRIM, LTRIM and RTRIM functions.
1011: #
1012: do_test func-22.1 {
1013: catchsql {SELECT trim(1,2,3)}
1014: } {1 {wrong number of arguments to function trim()}}
1015: do_test func-22.2 {
1016: catchsql {SELECT ltrim(1,2,3)}
1017: } {1 {wrong number of arguments to function ltrim()}}
1018: do_test func-22.3 {
1019: catchsql {SELECT rtrim(1,2,3)}
1020: } {1 {wrong number of arguments to function rtrim()}}
1021: do_test func-22.4 {
1022: execsql {SELECT trim(' hi ');}
1023: } {hi}
1024: do_test func-22.5 {
1025: execsql {SELECT ltrim(' hi ');}
1026: } {{hi }}
1027: do_test func-22.6 {
1028: execsql {SELECT rtrim(' hi ');}
1029: } {{ hi}}
1030: do_test func-22.7 {
1031: execsql {SELECT trim(' hi ','xyz');}
1032: } {{ hi }}
1033: do_test func-22.8 {
1034: execsql {SELECT ltrim(' hi ','xyz');}
1035: } {{ hi }}
1036: do_test func-22.9 {
1037: execsql {SELECT rtrim(' hi ','xyz');}
1038: } {{ hi }}
1039: do_test func-22.10 {
1040: execsql {SELECT trim('xyxzy hi zzzy','xyz');}
1041: } {{ hi }}
1042: do_test func-22.11 {
1043: execsql {SELECT ltrim('xyxzy hi zzzy','xyz');}
1044: } {{ hi zzzy}}
1045: do_test func-22.12 {
1046: execsql {SELECT rtrim('xyxzy hi zzzy','xyz');}
1047: } {{xyxzy hi }}
1048: do_test func-22.13 {
1049: execsql {SELECT trim(' hi ','');}
1050: } {{ hi }}
1051: if {[db one {PRAGMA encoding}]=="UTF-8"} {
1052: do_test func-22.14 {
1053: execsql {SELECT hex(trim(x'c280e1bfbff48fbfbf6869',x'6162e1bfbfc280'))}
1054: } {F48FBFBF6869}
1055: do_test func-22.15 {
1056: execsql {SELECT hex(trim(x'6869c280e1bfbff48fbfbf61',
1057: x'6162e1bfbfc280f48fbfbf'))}
1058: } {6869}
1059: do_test func-22.16 {
1060: execsql {SELECT hex(trim(x'ceb1ceb2ceb3',x'ceb1'));}
1061: } {CEB2CEB3}
1062: }
1063: do_test func-22.20 {
1064: execsql {SELECT typeof(trim(NULL));}
1065: } {null}
1066: do_test func-22.21 {
1067: execsql {SELECT typeof(trim(NULL,'xyz'));}
1068: } {null}
1069: do_test func-22.22 {
1070: execsql {SELECT typeof(trim('hello',NULL));}
1071: } {null}
1072:
1073: # This is to test the deprecated sqlite3_aggregate_count() API.
1074: #
1075: ifcapable deprecated {
1076: do_test func-23.1 {
1077: sqlite3_create_aggregate db
1078: execsql {
1079: SELECT legacy_count() FROM t6;
1080: }
1081: } {3}
1082: }
1083:
1084: # The group_concat() function.
1085: #
1086: do_test func-24.1 {
1087: execsql {
1088: SELECT group_concat(t1) FROM tbl1
1089: }
1090: } {this,program,is,free,software}
1091: do_test func-24.2 {
1092: execsql {
1093: SELECT group_concat(t1,' ') FROM tbl1
1094: }
1095: } {{this program is free software}}
1096: do_test func-24.3 {
1097: execsql {
1098: SELECT group_concat(t1,' ' || rowid || ' ') FROM tbl1
1099: }
1100: } {{this 2 program 3 is 4 free 5 software}}
1101: do_test func-24.4 {
1102: execsql {
1103: SELECT group_concat(NULL,t1) FROM tbl1
1104: }
1105: } {{}}
1106: do_test func-24.5 {
1107: execsql {
1108: SELECT group_concat(t1,NULL) FROM tbl1
1109: }
1110: } {thisprogramisfreesoftware}
1111: do_test func-24.6 {
1112: execsql {
1113: SELECT 'BEGIN-'||group_concat(t1) FROM tbl1
1114: }
1115: } {BEGIN-this,program,is,free,software}
1116:
1117: # Ticket #3179: Make sure aggregate functions can take many arguments.
1118: # None of the built-in aggregates do this, so use the md5sum() from the
1119: # test extensions.
1120: #
1121: unset -nocomplain midargs
1122: set midargs {}
1123: unset -nocomplain midres
1124: set midres {}
1125: unset -nocomplain result
1126: for {set i 1} {$i<[sqlite3_limit db SQLITE_LIMIT_FUNCTION_ARG -1]} {incr i} {
1127: append midargs ,'/$i'
1128: append midres /$i
1129: set result [md5 \
1130: "this${midres}program${midres}is${midres}free${midres}software${midres}"]
1131: set sql "SELECT md5sum(t1$midargs) FROM tbl1"
1132: do_test func-24.7.$i {
1133: db eval $::sql
1134: } $result
1135: }
1136:
1137: # Ticket #3806. If the initial string in a group_concat is an empty
1138: # string, the separator that follows should still be present.
1139: #
1140: do_test func-24.8 {
1141: execsql {
1142: SELECT group_concat(CASE t1 WHEN 'this' THEN '' ELSE t1 END) FROM tbl1
1143: }
1144: } {,program,is,free,software}
1145: do_test func-24.9 {
1146: execsql {
1147: SELECT group_concat(CASE WHEN t1!='software' THEN '' ELSE t1 END) FROM tbl1
1148: }
1149: } {,,,,software}
1150:
1151: # Ticket #3923. Initial empty strings have a separator. But initial
1152: # NULLs do not.
1153: #
1154: do_test func-24.10 {
1155: execsql {
1156: SELECT group_concat(CASE t1 WHEN 'this' THEN null ELSE t1 END) FROM tbl1
1157: }
1158: } {program,is,free,software}
1159: do_test func-24.11 {
1160: execsql {
1161: SELECT group_concat(CASE WHEN t1!='software' THEN null ELSE t1 END) FROM tbl1
1162: }
1163: } {software}
1164: do_test func-24.12 {
1165: execsql {
1166: SELECT group_concat(CASE t1 WHEN 'this' THEN ''
1167: WHEN 'program' THEN null ELSE t1 END) FROM tbl1
1168: }
1169: } {,is,free,software}
1170:
1171:
1172: # Use the test_isolation function to make sure that type conversions
1173: # on function arguments do not effect subsequent arguments.
1174: #
1175: do_test func-25.1 {
1176: execsql {SELECT test_isolation(t1,t1) FROM tbl1}
1177: } {this program is free software}
1178:
1179: # Try to misuse the sqlite3_create_function() interface. Verify that
1180: # errors are returned.
1181: #
1182: do_test func-26.1 {
1183: abuse_create_function db
1184: } {}
1185:
1186: # The previous test (func-26.1) registered a function with a very long
1187: # function name that takes many arguments and always returns NULL. Verify
1188: # that this function works correctly.
1189: #
1190: do_test func-26.2 {
1191: set a {}
1192: for {set i 1} {$i<=$::SQLITE_MAX_FUNCTION_ARG} {incr i} {
1193: lappend a $i
1194: }
1195: db eval "
1196: SELECT nullx_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789([join $a ,]);
1197: "
1198: } {{}}
1199: do_test func-26.3 {
1200: set a {}
1201: for {set i 1} {$i<=$::SQLITE_MAX_FUNCTION_ARG+1} {incr i} {
1202: lappend a $i
1203: }
1204: catchsql "
1205: SELECT nullx_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789([join $a ,]);
1206: "
1207: } {1 {too many arguments on function nullx_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789}}
1208: do_test func-26.4 {
1209: set a {}
1210: for {set i 1} {$i<=$::SQLITE_MAX_FUNCTION_ARG-1} {incr i} {
1211: lappend a $i
1212: }
1213: catchsql "
1214: SELECT nullx_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789([join $a ,]);
1215: "
1216: } {1 {wrong number of arguments to function nullx_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789()}}
1217: do_test func-26.5 {
1218: catchsql "
1219: SELECT nullx_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_12345678a(0);
1220: "
1221: } {1 {no such function: nullx_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_12345678a}}
1222: do_test func-26.6 {
1223: catchsql "
1224: SELECT nullx_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789a(0);
1225: "
1226: } {1 {no such function: nullx_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789a}}
1227:
1228: do_test func-27.1 {
1229: catchsql {SELECT coalesce()}
1230: } {1 {wrong number of arguments to function coalesce()}}
1231: do_test func-27.2 {
1232: catchsql {SELECT coalesce(1)}
1233: } {1 {wrong number of arguments to function coalesce()}}
1234: do_test func-27.3 {
1235: catchsql {SELECT coalesce(1,2)}
1236: } {0 1}
1237:
1238: # Ticket 2d401a94287b5
1239: # Unknown function in a DEFAULT expression causes a segfault.
1240: #
1241: do_test func-28.1 {
1242: db eval {
1243: CREATE TABLE t28(x, y DEFAULT(nosuchfunc(1)));
1244: }
1245: catchsql {
1246: INSERT INTO t28(x) VALUES(1);
1247: }
1248: } {1 {unknown function: nosuchfunc()}}
1249:
1250: finish_test
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>