blob: 694877e4039c21b1f6a130e67da216038b7d9a54 [file] [log] [blame]
drhb19a2bc2001-09-16 00:13:26 +00001# 2001 September 15
drhff6e9112000-08-28 16:21:58 +00002#
drhb19a2bc2001-09-16 00:13:26 +00003# The author disclaims copyright to this source code. In place of
4# a legal notice, here is a blessing:
drhff6e9112000-08-28 16:21:58 +00005#
drhb19a2bc2001-09-16 00:13:26 +00006# 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.
drhff6e9112000-08-28 16:21:58 +00009#
10#***********************************************************************
11# This file implements regression tests for SQLite library. The
12# focus of this file is testing built-in functions.
13#
drhda84ca82008-03-19 16:35:24 +000014# $Id: func.test,v 1.73 2008/03/19 16:35:24 drh Exp $
drhff6e9112000-08-28 16:21:58 +000015
16set testdir [file dirname $argv0]
17source $testdir/tester.tcl
18
19# Create a table to work with.
20#
drhff6e9112000-08-28 16:21:58 +000021do_test func-0.0 {
drh297ecf12001-04-05 15:57:13 +000022 execsql {CREATE TABLE tbl1(t1 text)}
23 foreach word {this program is free software} {
24 execsql "INSERT INTO tbl1 VALUES('$word')"
25 }
drhff6e9112000-08-28 16:21:58 +000026 execsql {SELECT t1 FROM tbl1 ORDER BY t1}
27} {free is program software this}
drh832508b2002-03-02 17:04:07 +000028do_test func-0.1 {
29 execsql {
30 CREATE TABLE t2(a);
31 INSERT INTO t2 VALUES(1);
32 INSERT INTO t2 VALUES(NULL);
33 INSERT INTO t2 VALUES(345);
34 INSERT INTO t2 VALUES(NULL);
35 INSERT INTO t2 VALUES(67890);
36 SELECT * FROM t2;
37 }
38} {1 {} 345 {} 67890}
drhff6e9112000-08-28 16:21:58 +000039
40# Check out the length() function
41#
42do_test func-1.0 {
43 execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
44} {4 2 7 8 4}
45do_test func-1.1 {
46 set r [catch {execsql {SELECT length(*) FROM tbl1 ORDER BY t1}} msg]
47 lappend r $msg
drh89425d52002-02-28 03:04:48 +000048} {1 {wrong number of arguments to function length()}}
drhff6e9112000-08-28 16:21:58 +000049do_test func-1.2 {
50 set r [catch {execsql {SELECT length(t1,5) FROM tbl1 ORDER BY t1}} msg]
51 lappend r $msg
drh89425d52002-02-28 03:04:48 +000052} {1 {wrong number of arguments to function length()}}
drhff6e9112000-08-28 16:21:58 +000053do_test func-1.3 {
54 execsql {SELECT length(t1), count(*) FROM tbl1 GROUP BY length(t1)
55 ORDER BY length(t1)}
56} {2 1 4 2 7 1 8 1}
drh832508b2002-03-02 17:04:07 +000057do_test func-1.4 {
drhbb113512002-05-27 01:04:51 +000058 execsql {SELECT coalesce(length(a),-1) FROM t2}
59} {1 -1 3 -1 5}
drhff6e9112000-08-28 16:21:58 +000060
61# Check out the substr() function
62#
63do_test func-2.0 {
64 execsql {SELECT substr(t1,1,2) FROM tbl1 ORDER BY t1}
65} {fr is pr so th}
66do_test func-2.1 {
67 execsql {SELECT substr(t1,2,1) FROM tbl1 ORDER BY t1}
68} {r s r o h}
69do_test func-2.2 {
70 execsql {SELECT substr(t1,3,3) FROM tbl1 ORDER BY t1}
71} {ee {} ogr ftw is}
72do_test func-2.3 {
73 execsql {SELECT substr(t1,-1,1) FROM tbl1 ORDER BY t1}
74} {e s m e s}
75do_test func-2.4 {
76 execsql {SELECT substr(t1,-1,2) FROM tbl1 ORDER BY t1}
77} {e s m e s}
78do_test func-2.5 {
79 execsql {SELECT substr(t1,-2,1) FROM tbl1 ORDER BY t1}
80} {e i a r i}
81do_test func-2.6 {
82 execsql {SELECT substr(t1,-2,2) FROM tbl1 ORDER BY t1}
83} {ee is am re is}
84do_test func-2.7 {
85 execsql {SELECT substr(t1,-4,2) FROM tbl1 ORDER BY t1}
86} {fr {} gr wa th}
87do_test func-2.8 {
88 execsql {SELECT t1 FROM tbl1 ORDER BY substr(t1,2,20)}
89} {this software free program is}
drh832508b2002-03-02 17:04:07 +000090do_test func-2.9 {
91 execsql {SELECT substr(a,1,1) FROM t2}
92} {1 {} 3 {} 6}
93do_test func-2.10 {
94 execsql {SELECT substr(a,2,2) FROM t2}
95} {{} {} 45 {} 78}
drhff6e9112000-08-28 16:21:58 +000096
drhdf014892004-06-02 00:41:09 +000097# Only do the following tests if TCL has UTF-8 capabilities
drh297ecf12001-04-05 15:57:13 +000098#
drhdf014892004-06-02 00:41:09 +000099if {"\u1234"!="u1234"} {
drh297ecf12001-04-05 15:57:13 +0000100
101# Put some UTF-8 characters in the database
102#
103do_test func-3.0 {
104 execsql {DELETE FROM tbl1}
105 foreach word "contains UTF-8 characters hi\u1234ho" {
106 execsql "INSERT INTO tbl1 VALUES('$word')"
107 }
108 execsql {SELECT t1 FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000109} "UTF-8 characters contains hi\u1234ho"
drh297ecf12001-04-05 15:57:13 +0000110do_test func-3.1 {
111 execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000112} {5 10 8 5}
drh297ecf12001-04-05 15:57:13 +0000113do_test func-3.2 {
114 execsql {SELECT substr(t1,1,2) FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000115} {UT ch co hi}
drh297ecf12001-04-05 15:57:13 +0000116do_test func-3.3 {
117 execsql {SELECT substr(t1,1,3) FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000118} "UTF cha con hi\u1234"
drh297ecf12001-04-05 15:57:13 +0000119do_test func-3.4 {
120 execsql {SELECT substr(t1,2,2) FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000121} "TF ha on i\u1234"
drh297ecf12001-04-05 15:57:13 +0000122do_test func-3.5 {
123 execsql {SELECT substr(t1,2,3) FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000124} "TF- har ont i\u1234h"
drh297ecf12001-04-05 15:57:13 +0000125do_test func-3.6 {
126 execsql {SELECT substr(t1,3,2) FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000127} "F- ar nt \u1234h"
drh297ecf12001-04-05 15:57:13 +0000128do_test func-3.7 {
129 execsql {SELECT substr(t1,4,2) FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000130} "-8 ra ta ho"
drh297ecf12001-04-05 15:57:13 +0000131do_test func-3.8 {
132 execsql {SELECT substr(t1,-1,1) FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000133} "8 s s o"
drh297ecf12001-04-05 15:57:13 +0000134do_test func-3.9 {
135 execsql {SELECT substr(t1,-3,2) FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000136} "F- er in \u1234h"
drh297ecf12001-04-05 15:57:13 +0000137do_test func-3.10 {
138 execsql {SELECT substr(t1,-4,3) FROM tbl1 ORDER BY t1}
drha9e99ae2002-08-13 23:02:57 +0000139} "TF- ter ain i\u1234h"
drh832508b2002-03-02 17:04:07 +0000140do_test func-3.99 {
141 execsql {DELETE FROM tbl1}
142 foreach word {this program is free software} {
143 execsql "INSERT INTO tbl1 VALUES('$word')"
144 }
145 execsql {SELECT t1 FROM tbl1}
146} {this program is free software}
drh297ecf12001-04-05 15:57:13 +0000147
drhdf014892004-06-02 00:41:09 +0000148} ;# End \u1234!=u1234
drh297ecf12001-04-05 15:57:13 +0000149
drhbf4133c2001-10-13 02:59:08 +0000150# Test the abs() and round() functions.
151#
152do_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,1.2345678901234,-12345.67890);
157 INSERT INTO t1 VALUES(3,-2,-5);
158 }
159 catchsql {SELECT abs(a,b) FROM t1}
drh89425d52002-02-28 03:04:48 +0000160} {1 {wrong number of arguments to function abs()}}
drhbf4133c2001-10-13 02:59:08 +0000161do_test func-4.2 {
162 catchsql {SELECT abs() FROM t1}
drh89425d52002-02-28 03:04:48 +0000163} {1 {wrong number of arguments to function abs()}}
drhbf4133c2001-10-13 02:59:08 +0000164do_test func-4.3 {
165 catchsql {SELECT abs(b) FROM t1 ORDER BY a}
166} {0 {2 1.2345678901234 2}}
167do_test func-4.4 {
168 catchsql {SELECT abs(c) FROM t1 ORDER BY a}
danielk19773d1bfea2004-05-14 11:00:53 +0000169} {0 {3 12345.6789 5}}
drh832508b2002-03-02 17:04:07 +0000170do_test func-4.4.1 {
171 execsql {SELECT abs(a) FROM t2}
172} {1 {} 345 {} 67890}
173do_test func-4.4.2 {
174 execsql {SELECT abs(t1) FROM tbl1}
drh92febd92004-08-20 18:34:20 +0000175} {0.0 0.0 0.0 0.0 0.0}
drhbf4133c2001-10-13 02:59:08 +0000176
177do_test func-4.5 {
178 catchsql {SELECT round(a,b,c) FROM t1}
drh89425d52002-02-28 03:04:48 +0000179} {1 {wrong number of arguments to function round()}}
drhbf4133c2001-10-13 02:59:08 +0000180do_test func-4.6 {
drh8aff1012001-12-22 14:49:24 +0000181 catchsql {SELECT round(b,2) FROM t1 ORDER BY b}
drhd589a922006-03-02 03:02:48 +0000182} {0 {-2.0 1.23 2.0}}
drhbf4133c2001-10-13 02:59:08 +0000183do_test func-4.7 {
184 catchsql {SELECT round(b,0) FROM t1 ORDER BY a}
drhd589a922006-03-02 03:02:48 +0000185} {0 {2.0 1.0 -2.0}}
drhbf4133c2001-10-13 02:59:08 +0000186do_test func-4.8 {
187 catchsql {SELECT round(c) FROM t1 ORDER BY a}
drhd589a922006-03-02 03:02:48 +0000188} {0 {3.0 -12346.0 -5.0}}
drhbf4133c2001-10-13 02:59:08 +0000189do_test func-4.9 {
190 catchsql {SELECT round(c,a) FROM t1 ORDER BY a}
drhd589a922006-03-02 03:02:48 +0000191} {0 {3.0 -12345.68 -5.0}}
drhbf4133c2001-10-13 02:59:08 +0000192do_test func-4.10 {
drh01a34662001-10-20 12:30:10 +0000193 catchsql {SELECT 'x' || round(c,a) || 'y' FROM t1 ORDER BY a}
drhd589a922006-03-02 03:02:48 +0000194} {0 {x3.0y x-12345.68y x-5.0y}}
drh01a34662001-10-20 12:30:10 +0000195do_test func-4.11 {
drhbf4133c2001-10-13 02:59:08 +0000196 catchsql {SELECT round() FROM t1 ORDER BY a}
drh89425d52002-02-28 03:04:48 +0000197} {1 {wrong number of arguments to function round()}}
drh832508b2002-03-02 17:04:07 +0000198do_test func-4.12 {
drhbb113512002-05-27 01:04:51 +0000199 execsql {SELECT coalesce(round(a,2),'nil') FROM t2}
drhd589a922006-03-02 03:02:48 +0000200} {1.0 nil 345.0 nil 67890.0}
drh832508b2002-03-02 17:04:07 +0000201do_test func-4.13 {
202 execsql {SELECT round(t1,2) FROM tbl1}
drhd589a922006-03-02 03:02:48 +0000203} {0.0 0.0 0.0 0.0 0.0}
204do_test func-4.14 {
205 execsql {SELECT typeof(round(5.1,1));}
206} {real}
207do_test func-4.15 {
208 execsql {SELECT typeof(round(5.1));}
209} {real}
210
drh832508b2002-03-02 17:04:07 +0000211
212# Test the upper() and lower() functions
213#
214do_test func-5.1 {
215 execsql {SELECT upper(t1) FROM tbl1}
216} {THIS PROGRAM IS FREE SOFTWARE}
217do_test func-5.2 {
218 execsql {SELECT lower(upper(t1)) FROM tbl1}
219} {this program is free software}
220do_test func-5.3 {
221 execsql {SELECT upper(a), lower(a) FROM t2}
222} {1 1 {} {} 345 345 {} {} 67890 67890}
danielk19777de68a02007-05-07 16:58:02 +0000223ifcapable !icu {
224 do_test func-5.4 {
225 catchsql {SELECT upper(a,5) FROM t2}
226 } {1 {wrong number of arguments to function upper()}}
227}
drh832508b2002-03-02 17:04:07 +0000228do_test func-5.5 {
229 catchsql {SELECT upper(*) FROM t2}
230} {1 {wrong number of arguments to function upper()}}
231
drha9f9d1c2002-06-29 02:20:08 +0000232# Test the coalesce() and nullif() functions
drh832508b2002-03-02 17:04:07 +0000233#
234do_test func-6.1 {
235 execsql {SELECT coalesce(a,'xyz') FROM t2}
236} {1 xyz 345 xyz 67890}
237do_test func-6.2 {
238 execsql {SELECT coalesce(upper(a),'nil') FROM t2}
239} {1 nil 345 nil 67890}
drha9f9d1c2002-06-29 02:20:08 +0000240do_test func-6.3 {
241 execsql {SELECT coalesce(nullif(1,1),'nil')}
242} {nil}
243do_test func-6.4 {
244 execsql {SELECT coalesce(nullif(1,2),'nil')}
245} {1}
246do_test func-6.5 {
247 execsql {SELECT coalesce(nullif(1,NULL),'nil')}
248} {1}
249
drh832508b2002-03-02 17:04:07 +0000250
drh6ed41ad2002-04-06 14:10:47 +0000251# Test the last_insert_rowid() function
252#
253do_test func-7.1 {
254 execsql {SELECT last_insert_rowid()}
255} [db last_insert_rowid]
256
drh739105c2002-05-29 23:22:23 +0000257# Tests for aggregate functions and how they handle NULLs.
258#
259do_test func-8.1 {
danielk19774489f9b2005-01-20 02:17:01 +0000260 ifcapable explain {
261 execsql {EXPLAIN SELECT sum(a) FROM t2;}
262 }
drh739105c2002-05-29 23:22:23 +0000263 execsql {
264 SELECT sum(a), count(a), round(avg(a),2), min(a), max(a), count(*) FROM t2;
265 }
drh3d1d95e2005-09-08 10:37:01 +0000266} {68236 3 22745.33 1 67890 5}
drha9f9d1c2002-06-29 02:20:08 +0000267do_test func-8.2 {
268 execsql {
269 SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t2;
270 }
271} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
danielk197753c0f742005-03-29 03:10:59 +0000272
273ifcapable tempdb {
274 do_test func-8.3 {
275 execsql {
276 CREATE TEMP TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
277 SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
278 }
279 } {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
280} else {
281 do_test func-8.3 {
282 execsql {
283 CREATE TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
284 SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
285 }
286 } {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
287}
danielk19773aeab9e2004-06-24 00:20:04 +0000288do_test func-8.4 {
289 execsql {
290 SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
291 }
292} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
drh739105c2002-05-29 23:22:23 +0000293
drha9f9d1c2002-06-29 02:20:08 +0000294# How do you test the random() function in a meaningful, deterministic way?
295#
296do_test func-9.1 {
297 execsql {
298 SELECT random() is not null;
299 }
300} {1}
drh63cf66f2007-01-29 15:50:05 +0000301do_test func-9.2 {
302 execsql {
303 SELECT typeof(random());
304 }
305} {integer}
306do_test func-9.3 {
307 execsql {
drh137c7282007-01-29 17:58:28 +0000308 SELECT randomblob(32) is not null;
drh63cf66f2007-01-29 15:50:05 +0000309 }
310} {1}
311do_test func-9.4 {
312 execsql {
drh137c7282007-01-29 17:58:28 +0000313 SELECT typeof(randomblob(32));
drh63cf66f2007-01-29 15:50:05 +0000314 }
drh137c7282007-01-29 17:58:28 +0000315} {blob}
drh63cf66f2007-01-29 15:50:05 +0000316do_test func-9.5 {
317 execsql {
drh137c7282007-01-29 17:58:28 +0000318 SELECT length(randomblob(32)), length(randomblob(-5)),
319 length(randomblob(2000))
drh63cf66f2007-01-29 15:50:05 +0000320 }
drh137c7282007-01-29 17:58:28 +0000321} {32 1 2000}
drh63cf66f2007-01-29 15:50:05 +0000322
drh137c7282007-01-29 17:58:28 +0000323# The "hex()" function was added in order to be able to render blobs
324# generated by randomblob(). So this seems like a good place to test
325# hex().
326#
danielk19774152e672007-09-12 17:01:45 +0000327ifcapable bloblit {
328 do_test func-9.10 {
329 execsql {SELECT hex(x'00112233445566778899aAbBcCdDeEfF')}
330 } {00112233445566778899AABBCCDDEEFF}
331}
drh056c8f72007-05-15 18:35:21 +0000332set encoding [db one {PRAGMA encoding}]
333if {$encoding=="UTF-16le"} {
334 do_test func-9.11-utf16le {
335 execsql {SELECT hex(replace('abcdefg','ef','12'))}
336 } {6100620063006400310032006700}
337 do_test func-9.12-utf16le {
338 execsql {SELECT hex(replace('abcdefg','','12'))}
339 } {{}}
340 breakpoint
341 do_test func-9.13-utf16le {
342 execsql {SELECT hex(replace('aabcdefg','a','aaa'))}
343 } {610061006100610061006100620063006400650066006700}
344} elseif {$encoding=="UTF-8"} {
345 do_test func-9.11-utf8 {
346 execsql {SELECT hex(replace('abcdefg','ef','12'))}
347 } {61626364313267}
348 do_test func-9.12-utf8 {
349 execsql {SELECT hex(replace('abcdefg','','12'))}
350 } {{}}
351 breakpoint
352 do_test func-9.13-utf8 {
353 execsql {SELECT hex(replace('aabcdefg','a','aaa'))}
354 } {616161616161626364656667}
355}
356
drh6cbe1f12002-07-01 00:31:36 +0000357# Use the "sqlite_register_test_function" TCL command which is part of
358# the text fixture in order to verify correct operation of some of
359# the user-defined SQL function APIs that are not used by the built-in
360# functions.
361#
drhdddca282006-01-03 00:33:50 +0000362set ::DB [sqlite3_connection_pointer db]
drh6cbe1f12002-07-01 00:31:36 +0000363sqlite_register_test_function $::DB testfunc
364do_test func-10.1 {
365 catchsql {
366 SELECT testfunc(NULL,NULL);
367 }
danielk19776d88bad2004-05-27 14:23:36 +0000368} {1 {first argument should be one of: int int64 string double null value}}
drh6cbe1f12002-07-01 00:31:36 +0000369do_test func-10.2 {
370 execsql {
371 SELECT testfunc(
372 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
373 'int', 1234
374 );
375 }
376} {1234}
377do_test func-10.3 {
378 execsql {
379 SELECT testfunc(
380 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
381 'string', NULL
382 );
383 }
384} {{}}
385do_test func-10.4 {
386 execsql {
387 SELECT testfunc(
388 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
389 'double', 1.234
390 );
391 }
392} {1.234}
393do_test func-10.5 {
394 execsql {
395 SELECT testfunc(
396 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
397 'int', 1234,
398 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
399 'string', NULL,
400 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
401 'double', 1.234,
402 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
403 'int', 1234,
404 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
405 'string', NULL,
406 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
407 'double', 1.234
408 );
409 }
410} {1.234}
411
drh647cb0e2002-11-04 19:32:25 +0000412# Test the built-in sqlite_version(*) SQL function.
413#
414do_test func-11.1 {
415 execsql {
416 SELECT sqlite_version(*);
417 }
drhef4ac8f2004-06-19 00:16:31 +0000418} [sqlite3 -version]
drh647cb0e2002-11-04 19:32:25 +0000419
drhef4ac8f2004-06-19 00:16:31 +0000420# Test that destructors passed to sqlite3 by calls to sqlite3_result_text()
danielk19773f6b0872004-06-17 05:36:44 +0000421# etc. are called. These tests use two special user-defined functions
422# (implemented in func.c) only available in test builds.
423#
424# Function test_destructor() takes one argument and returns a copy of the
425# text form of that argument. A destructor is associated with the return
426# value. Function test_destructor_count() returns the number of outstanding
427# destructor calls for values returned by test_destructor().
428#
drhda84ca82008-03-19 16:35:24 +0000429if {[db eval {PRAGMA encoding}]=="UTF-8"} {
430 do_test func-12.1-utf8 {
431 execsql {
432 SELECT test_destructor('hello world'), test_destructor_count();
433 }
434 } {{hello world} 1}
435} else {
436 do_test func-12.1-utf16 {
437 execsql {
438 SELECT test_destructor16('hello world'), test_destructor_count();
439 }
440 } {{hello world} 1}
441}
danielk1977d8123362004-06-12 09:25:12 +0000442do_test func-12.2 {
443 execsql {
444 SELECT test_destructor_count();
445 }
446} {0}
447do_test func-12.3 {
448 execsql {
drh2dcef112008-01-12 19:03:48 +0000449 SELECT test_destructor('hello')||' world'
danielk1977d8123362004-06-12 09:25:12 +0000450 }
drh2dcef112008-01-12 19:03:48 +0000451} {{hello world}}
danielk1977d8123362004-06-12 09:25:12 +0000452do_test func-12.4 {
453 execsql {
454 SELECT test_destructor_count();
455 }
456} {0}
457do_test func-12.5 {
458 execsql {
459 CREATE TABLE t4(x);
460 INSERT INTO t4 VALUES(test_destructor('hello'));
461 INSERT INTO t4 VALUES(test_destructor('world'));
462 SELECT min(test_destructor(x)), max(test_destructor(x)) FROM t4;
463 }
464} {hello world}
465do_test func-12.6 {
466 execsql {
467 SELECT test_destructor_count();
468 }
469} {0}
danielk19773f6b0872004-06-17 05:36:44 +0000470do_test func-12.7 {
471 execsql {
472 DROP TABLE t4;
473 }
474} {}
475
drha4e5d582007-10-20 15:41:57 +0000476
danielk19773f6b0872004-06-17 05:36:44 +0000477# Test that the auxdata API for scalar functions works. This test uses
478# a special user-defined function only available in test builds,
479# test_auxdata(). Function test_auxdata() takes any number of arguments.
480do_test func-13.1 {
481 execsql {
482 SELECT test_auxdata('hello world');
483 }
484} {0}
danielk1977ece80f12004-06-23 01:05:26 +0000485
danielk19773f6b0872004-06-17 05:36:44 +0000486do_test func-13.2 {
487 execsql {
488 CREATE TABLE t4(a, b);
489 INSERT INTO t4 VALUES('abc', 'def');
490 INSERT INTO t4 VALUES('ghi', 'jkl');
491 }
492} {}
493do_test func-13.3 {
494 execsql {
495 SELECT test_auxdata('hello world') FROM t4;
496 }
497} {0 1}
498do_test func-13.4 {
499 execsql {
500 SELECT test_auxdata('hello world', 123) FROM t4;
501 }
502} {{0 0} {1 1}}
503do_test func-13.5 {
504 execsql {
505 SELECT test_auxdata('hello world', a) FROM t4;
506 }
507} {{0 0} {1 0}}
508do_test func-13.6 {
509 execsql {
510 SELECT test_auxdata('hello'||'world', a) FROM t4;
511 }
512} {{0 0} {1 0}}
513
514# Test that auxilary data is preserved between calls for SQL variables.
515do_test func-13.7 {
drhdddca282006-01-03 00:33:50 +0000516 set DB [sqlite3_connection_pointer db]
danielk19773f6b0872004-06-17 05:36:44 +0000517 set sql "SELECT test_auxdata( ? , a ) FROM t4;"
518 set STMT [sqlite3_prepare $DB $sql -1 TAIL]
519 sqlite3_bind_text $STMT 1 hello -1
520 set res [list]
521 while { "SQLITE_ROW"==[sqlite3_step $STMT] } {
522 lappend res [sqlite3_column_text $STMT 0]
523 }
524 lappend res [sqlite3_finalize $STMT]
525} {{0 0} {1 0} SQLITE_OK}
danielk1977d8123362004-06-12 09:25:12 +0000526
danielk1977312d6b32004-06-29 13:18:23 +0000527# Make sure that a function with a very long name is rejected
528do_test func-14.1 {
529 catch {
530 db function [string repeat X 254] {return "hello"}
531 }
532} {0}
533do_test func-14.2 {
534 catch {
535 db function [string repeat X 256] {return "hello"}
536 }
537} {1}
538
danielk197701427a62005-01-11 13:02:33 +0000539do_test func-15.1 {
540 catchsql {
541 select test_error(NULL);
542 }
drh90669c12006-01-20 15:45:36 +0000543} {1 {}}
danielk197701427a62005-01-11 13:02:33 +0000544
danielk1977576ec6b2005-01-21 11:55:25 +0000545# Test the quote function for BLOB and NULL values.
546do_test func-16.1 {
547 execsql {
548 CREATE TABLE tbl2(a, b);
549 }
550 set STMT [sqlite3_prepare $::DB "INSERT INTO tbl2 VALUES(?, ?)" -1 TAIL]
551 sqlite3_bind_blob $::STMT 1 abc 3
552 sqlite3_step $::STMT
553 sqlite3_finalize $::STMT
554 execsql {
555 SELECT quote(a), quote(b) FROM tbl2;
556 }
557} {X'616263' NULL}
558
drh2501eb12005-08-12 23:20:53 +0000559# Correctly handle function error messages that include %. Ticket #1354
560#
561do_test func-17.1 {
562 proc testfunc1 args {error "Error %d with %s percents %p"}
563 db function testfunc1 ::testfunc1
564 catchsql {
565 SELECT testfunc1(1,2,3);
566 }
567} {1 {Error %d with %s percents %p}}
568
drh3d1d95e2005-09-08 10:37:01 +0000569# The SUM function should return integer results when all inputs are integer.
570#
571do_test func-18.1 {
572 execsql {
573 CREATE TABLE t5(x);
574 INSERT INTO t5 VALUES(1);
575 INSERT INTO t5 VALUES(-99);
576 INSERT INTO t5 VALUES(10000);
577 SELECT sum(x) FROM t5;
578 }
579} {9902}
580do_test func-18.2 {
581 execsql {
582 INSERT INTO t5 VALUES(0.0);
583 SELECT sum(x) FROM t5;
584 }
drh8a512562005-11-14 22:29:05 +0000585} {9902.0}
danielk1977576ec6b2005-01-21 11:55:25 +0000586
drhc2bd9132005-09-08 20:37:43 +0000587# The sum of nothing is NULL. But the sum of all NULLs is NULL.
drh3f219f42005-09-08 19:45:57 +0000588#
drh76c730c2006-02-09 17:47:42 +0000589# The TOTAL of nothing is 0.0.
590#
drh3f219f42005-09-08 19:45:57 +0000591do_test func-18.3 {
592 execsql {
593 DELETE FROM t5;
drh76c730c2006-02-09 17:47:42 +0000594 SELECT sum(x), total(x) FROM t5;
drh3f219f42005-09-08 19:45:57 +0000595 }
drh76c730c2006-02-09 17:47:42 +0000596} {{} 0.0}
drh3f219f42005-09-08 19:45:57 +0000597do_test func-18.4 {
598 execsql {
599 INSERT INTO t5 VALUES(NULL);
drh76c730c2006-02-09 17:47:42 +0000600 SELECT sum(x), total(x) FROM t5
drh3f219f42005-09-08 19:45:57 +0000601 }
drh76c730c2006-02-09 17:47:42 +0000602} {{} 0.0}
drh3f219f42005-09-08 19:45:57 +0000603do_test func-18.5 {
604 execsql {
605 INSERT INTO t5 VALUES(NULL);
drh76c730c2006-02-09 17:47:42 +0000606 SELECT sum(x), total(x) FROM t5
drh3f219f42005-09-08 19:45:57 +0000607 }
drh76c730c2006-02-09 17:47:42 +0000608} {{} 0.0}
drh3f219f42005-09-08 19:45:57 +0000609do_test func-18.6 {
610 execsql {
611 INSERT INTO t5 VALUES(123);
drh76c730c2006-02-09 17:47:42 +0000612 SELECT sum(x), total(x) FROM t5
drh3f219f42005-09-08 19:45:57 +0000613 }
drh76c730c2006-02-09 17:47:42 +0000614} {123 123.0}
drh5708d2d2005-06-22 10:53:59 +0000615
drh8c08e862006-02-11 17:34:00 +0000616# Ticket #1664, #1669, #1670, #1674: An integer overflow on SUM causes
617# an error. The non-standard TOTAL() function continues to give a helpful
618# result.
drhfc6ad392006-02-09 13:38:19 +0000619#
620do_test func-18.10 {
621 execsql {
622 CREATE TABLE t6(x INTEGER);
623 INSERT INTO t6 VALUES(1);
624 INSERT INTO t6 VALUES(1<<62);
625 SELECT sum(x) - ((1<<62)+1) from t6;
626 }
627} 0
drh76c730c2006-02-09 17:47:42 +0000628do_test func-18.11 {
629 execsql {
630 SELECT typeof(sum(x)) FROM t6
631 }
632} integer
633do_test func-18.12 {
drh8c08e862006-02-11 17:34:00 +0000634 catchsql {
drh76c730c2006-02-09 17:47:42 +0000635 INSERT INTO t6 VALUES(1<<62);
636 SELECT sum(x) - ((1<<62)*2.0+1) from t6;
637 }
drh8c08e862006-02-11 17:34:00 +0000638} {1 {integer overflow}}
drh76c730c2006-02-09 17:47:42 +0000639do_test func-18.13 {
640 execsql {
641 SELECT total(x) - ((1<<62)*2.0+1) FROM t6
642 }
643} 0.0
drh8c08e862006-02-11 17:34:00 +0000644do_test func-18.14 {
645 execsql {
646 SELECT sum(-9223372036854775805);
647 }
648} -9223372036854775805
danielk19774b2688a2006-06-20 11:01:07 +0000649
650ifcapable compound&&subquery {
651
drh8c08e862006-02-11 17:34:00 +0000652do_test func-18.15 {
653 catchsql {
654 SELECT sum(x) FROM
655 (SELECT 9223372036854775807 AS x UNION ALL
656 SELECT 10 AS x);
657 }
658} {1 {integer overflow}}
659do_test func-18.16 {
660 catchsql {
661 SELECT sum(x) FROM
662 (SELECT 9223372036854775807 AS x UNION ALL
663 SELECT -10 AS x);
664 }
665} {0 9223372036854775797}
666do_test func-18.17 {
667 catchsql {
668 SELECT sum(x) FROM
669 (SELECT -9223372036854775807 AS x UNION ALL
670 SELECT 10 AS x);
671 }
672} {0 -9223372036854775797}
673do_test func-18.18 {
674 catchsql {
675 SELECT sum(x) FROM
676 (SELECT -9223372036854775807 AS x UNION ALL
677 SELECT -10 AS x);
678 }
679} {1 {integer overflow}}
680do_test func-18.19 {
681 catchsql {
682 SELECT sum(x) FROM (SELECT 9 AS x UNION ALL SELECT -10 AS x);
683 }
684} {0 -1}
685do_test func-18.20 {
686 catchsql {
687 SELECT sum(x) FROM (SELECT -9 AS x UNION ALL SELECT 10 AS x);
688 }
689} {0 1}
690do_test func-18.21 {
691 catchsql {
692 SELECT sum(x) FROM (SELECT -10 AS x UNION ALL SELECT 9 AS x);
693 }
694} {0 -1}
695do_test func-18.22 {
696 catchsql {
697 SELECT sum(x) FROM (SELECT 10 AS x UNION ALL SELECT -9 AS x);
698 }
699} {0 1}
drh76c730c2006-02-09 17:47:42 +0000700
danielk19774b2688a2006-06-20 11:01:07 +0000701} ;# ifcapable compound&&subquery
702
drh52fc8492006-02-23 21:43:55 +0000703# Integer overflow on abs()
704#
705do_test func-18.31 {
706 catchsql {
707 SELECT abs(-9223372036854775807);
708 }
709} {0 9223372036854775807}
710do_test func-18.32 {
711 catchsql {
712 SELECT abs(-9223372036854775807-1);
713 }
714} {1 {integer overflow}}
715
drh7f375902006-06-13 17:38:59 +0000716# The MATCH function exists but is only a stub and always throws an error.
717#
718do_test func-19.1 {
719 execsql {
720 SELECT match(a,b) FROM t1 WHERE 0;
721 }
722} {}
723do_test func-19.2 {
724 catchsql {
725 SELECT 'abc' MATCH 'xyz';
726 }
drhb7481e72006-09-16 21:45:14 +0000727} {1 {unable to use function MATCH in the requested context}}
drh7f375902006-06-13 17:38:59 +0000728do_test func-19.3 {
729 catchsql {
730 SELECT 'abc' NOT MATCH 'xyz';
731 }
drhb7481e72006-09-16 21:45:14 +0000732} {1 {unable to use function MATCH in the requested context}}
drh7f375902006-06-13 17:38:59 +0000733do_test func-19.4 {
734 catchsql {
735 SELECT match(1,2,3);
736 }
737} {1 {wrong number of arguments to function match()}}
drh76c730c2006-02-09 17:47:42 +0000738
drhbdf67e02006-08-19 11:34:01 +0000739# Soundex tests.
740#
741if {![catch {db eval {SELECT soundex('hello')}}]} {
742 set i 0
743 foreach {name sdx} {
744 euler E460
745 EULER E460
746 Euler E460
747 ellery E460
748 gauss G200
749 ghosh G200
750 hilbert H416
751 Heilbronn H416
752 knuth K530
753 kant K530
754 Lloyd L300
755 LADD L300
756 Lukasiewicz L222
757 Lissajous L222
758 A A000
759 12345 ?000
760 } {
761 incr i
762 do_test func-20.$i {
763 execsql {SELECT soundex($name)}
764 } $sdx
765 }
766}
767
drh26b6d902007-03-17 13:27:54 +0000768# Tests of the REPLACE function.
769#
770do_test func-21.1 {
771 catchsql {
772 SELECT replace(1,2);
773 }
774} {1 {wrong number of arguments to function replace()}}
775do_test func-21.2 {
776 catchsql {
777 SELECT replace(1,2,3,4);
778 }
779} {1 {wrong number of arguments to function replace()}}
780do_test func-21.3 {
781 execsql {
782 SELECT typeof(replace("This is the main test string", NULL, "ALT"));
783 }
784} {null}
785do_test func-21.4 {
786 execsql {
787 SELECT typeof(replace(NULL, "main", "ALT"));
788 }
789} {null}
790do_test func-21.5 {
791 execsql {
792 SELECT typeof(replace("This is the main test string", "main", NULL));
793 }
794} {null}
795do_test func-21.6 {
796 execsql {
797 SELECT replace("This is the main test string", "main", "ALT");
798 }
799} {{This is the ALT test string}}
800do_test func-21.7 {
801 execsql {
802 SELECT replace("This is the main test string", "main", "larger-main");
803 }
804} {{This is the larger-main test string}}
805do_test func-21.8 {
806 execsql {
807 SELECT replace("aaaaaaa", "a", "0123456789");
808 }
809} {0123456789012345678901234567890123456789012345678901234567890123456789}
810
danielk19774152e672007-09-12 17:01:45 +0000811ifcapable tclvar {
812 do_test func-21.9 {
813 # Attempt to exploit a buffer-overflow that at one time existed
814 # in the REPLACE function.
815 set ::str "[string repeat A 29998]CC[string repeat A 35537]"
816 set ::rep [string repeat B 65536]
817 execsql {
818 SELECT LENGTH(REPLACE($::str, 'C', $::rep));
819 }
820 } [expr 29998 + 2*65536 + 35537]
821}
danielk197717374e82007-05-08 14:39:04 +0000822
drh309b3382007-03-17 17:52:42 +0000823# Tests for the TRIM, LTRIM and RTRIM functions.
824#
825do_test func-22.1 {
826 catchsql {SELECT trim(1,2,3)}
827} {1 {wrong number of arguments to function trim()}}
828do_test func-22.2 {
829 catchsql {SELECT ltrim(1,2,3)}
830} {1 {wrong number of arguments to function ltrim()}}
831do_test func-22.3 {
832 catchsql {SELECT rtrim(1,2,3)}
833} {1 {wrong number of arguments to function rtrim()}}
834do_test func-22.4 {
835 execsql {SELECT trim(' hi ');}
836} {hi}
837do_test func-22.5 {
838 execsql {SELECT ltrim(' hi ');}
839} {{hi }}
840do_test func-22.6 {
841 execsql {SELECT rtrim(' hi ');}
842} {{ hi}}
843do_test func-22.7 {
844 execsql {SELECT trim(' hi ','xyz');}
845} {{ hi }}
846do_test func-22.8 {
847 execsql {SELECT ltrim(' hi ','xyz');}
848} {{ hi }}
849do_test func-22.9 {
850 execsql {SELECT rtrim(' hi ','xyz');}
851} {{ hi }}
852do_test func-22.10 {
853 execsql {SELECT trim('xyxzy hi zzzy','xyz');}
854} {{ hi }}
855do_test func-22.11 {
856 execsql {SELECT ltrim('xyxzy hi zzzy','xyz');}
857} {{ hi zzzy}}
858do_test func-22.12 {
859 execsql {SELECT rtrim('xyxzy hi zzzy','xyz');}
860} {{xyxzy hi }}
861do_test func-22.13 {
862 execsql {SELECT trim(' hi ','');}
863} {{ hi }}
drh4e05c832007-05-11 01:44:50 +0000864if {[db one {PRAGMA encoding}]=="UTF-8"} {
865 do_test func-22.14 {
866 execsql {SELECT hex(trim(x'c280e1bfbff48fbfbf6869',x'6162e1bfbfc280'))}
867 } {F48FBFBF6869}
868 do_test func-22.15 {
869 execsql {SELECT hex(trim(x'6869c280e1bfbff48fbfbf61',
870 x'6162e1bfbfc280f48fbfbf'))}
871 } {6869}
872 do_test func-22.16 {
873 execsql {SELECT hex(trim(x'ceb1ceb2ceb3',x'ceb1'));}
874 } {CEB2CEB3}
875}
drh309b3382007-03-17 17:52:42 +0000876do_test func-22.20 {
877 execsql {SELECT typeof(trim(NULL));}
878} {null}
879do_test func-22.21 {
880 execsql {SELECT typeof(trim(NULL,'xyz'));}
881} {null}
882do_test func-22.22 {
883 execsql {SELECT typeof(trim('hello',NULL));}
884} {null}
drh26b6d902007-03-17 13:27:54 +0000885
danielk1977fa18bec2007-09-03 11:04:22 +0000886# This is to test the deprecated sqlite3_aggregate_count() API.
887#
888do_test func-23.1 {
889 sqlite3_create_aggregate db
890 execsql {
891 SELECT legacy_count() FROM t6;
892 }
893} {3}
894
drhade86482007-11-28 22:36:40 +0000895# The group_concat() function.
896#
897do_test func-24.1 {
898 execsql {
899 SELECT group_concat(t1) FROM tbl1
900 }
901} {this,program,is,free,software}
902do_test func-24.2 {
903 execsql {
904 SELECT group_concat(t1,' ') FROM tbl1
905 }
906} {{this program is free software}}
907do_test func-24.3 {
908 execsql {
909 SELECT group_concat(t1,' ' || rowid || ' ') FROM tbl1
910 }
911} {{this 2 program 3 is 4 free 5 software}}
912do_test func-24.4 {
913 execsql {
914 SELECT group_concat(NULL,t1) FROM tbl1
915 }
916} {{}}
917do_test func-24.5 {
918 execsql {
919 SELECT group_concat(t1,NULL) FROM tbl1
920 }
921} {thisprogramisfreesoftware}
922
drh5708d2d2005-06-22 10:53:59 +0000923finish_test