blob: f64c8b71216aedef2483a6249f83937108478fe7 [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#
danielk19777de68a02007-05-07 16:58:02 +000014# $Id: func.test,v 1.64 2007/05/07 16:58:02 danielk1977 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#
327do_test func-9.10 {
328 execsql {SELECT hex(x'00112233445566778899aAbBcCdDeEfF')}
329} {00112233445566778899AABBCCDDEEFF}
drh1eb25382007-04-10 13:51:17 +0000330do_test func-9.11 {
331 execsql {SELECT hex(replace('abcdefg','ef','12'))}
332} {61626364313267}
drh709cff32007-04-27 01:18:02 +0000333do_test func-9.12 {
334 execsql {SELECT hex(replace('abcdefg','','12'))}
335} {{}}
336do_test func-9.13 {
337 execsql {SELECT hex(replace('aabcdefg','a','aaa'))}
338} {616161616161626364656667}
drhbf4133c2001-10-13 02:59:08 +0000339
drh6cbe1f12002-07-01 00:31:36 +0000340# Use the "sqlite_register_test_function" TCL command which is part of
341# the text fixture in order to verify correct operation of some of
342# the user-defined SQL function APIs that are not used by the built-in
343# functions.
344#
drhdddca282006-01-03 00:33:50 +0000345set ::DB [sqlite3_connection_pointer db]
drh6cbe1f12002-07-01 00:31:36 +0000346sqlite_register_test_function $::DB testfunc
347do_test func-10.1 {
348 catchsql {
349 SELECT testfunc(NULL,NULL);
350 }
danielk19776d88bad2004-05-27 14:23:36 +0000351} {1 {first argument should be one of: int int64 string double null value}}
drh6cbe1f12002-07-01 00:31:36 +0000352do_test func-10.2 {
353 execsql {
354 SELECT testfunc(
355 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
356 'int', 1234
357 );
358 }
359} {1234}
360do_test func-10.3 {
361 execsql {
362 SELECT testfunc(
363 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
364 'string', NULL
365 );
366 }
367} {{}}
368do_test func-10.4 {
369 execsql {
370 SELECT testfunc(
371 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
372 'double', 1.234
373 );
374 }
375} {1.234}
376do_test func-10.5 {
377 execsql {
378 SELECT testfunc(
379 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
380 'int', 1234,
381 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
382 'string', NULL,
383 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
384 'double', 1.234,
385 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
386 'int', 1234,
387 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
388 'string', NULL,
389 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
390 'double', 1.234
391 );
392 }
393} {1.234}
394
drh647cb0e2002-11-04 19:32:25 +0000395# Test the built-in sqlite_version(*) SQL function.
396#
397do_test func-11.1 {
398 execsql {
399 SELECT sqlite_version(*);
400 }
drhef4ac8f2004-06-19 00:16:31 +0000401} [sqlite3 -version]
drh647cb0e2002-11-04 19:32:25 +0000402
drhef4ac8f2004-06-19 00:16:31 +0000403# Test that destructors passed to sqlite3 by calls to sqlite3_result_text()
danielk19773f6b0872004-06-17 05:36:44 +0000404# etc. are called. These tests use two special user-defined functions
405# (implemented in func.c) only available in test builds.
406#
407# Function test_destructor() takes one argument and returns a copy of the
408# text form of that argument. A destructor is associated with the return
409# value. Function test_destructor_count() returns the number of outstanding
410# destructor calls for values returned by test_destructor().
411#
danielk1977d8123362004-06-12 09:25:12 +0000412do_test func-12.1 {
413 execsql {
414 SELECT test_destructor('hello world'), test_destructor_count();
415 }
416} {{hello world} 1}
417do_test func-12.2 {
418 execsql {
419 SELECT test_destructor_count();
420 }
421} {0}
422do_test func-12.3 {
423 execsql {
424 SELECT test_destructor('hello')||' world', test_destructor_count();
425 }
426} {{hello world} 0}
427do_test func-12.4 {
428 execsql {
429 SELECT test_destructor_count();
430 }
431} {0}
432do_test func-12.5 {
433 execsql {
434 CREATE TABLE t4(x);
435 INSERT INTO t4 VALUES(test_destructor('hello'));
436 INSERT INTO t4 VALUES(test_destructor('world'));
437 SELECT min(test_destructor(x)), max(test_destructor(x)) FROM t4;
438 }
439} {hello world}
440do_test func-12.6 {
441 execsql {
442 SELECT test_destructor_count();
443 }
444} {0}
danielk19773f6b0872004-06-17 05:36:44 +0000445do_test func-12.7 {
446 execsql {
447 DROP TABLE t4;
448 }
449} {}
450
451# Test that the auxdata API for scalar functions works. This test uses
452# a special user-defined function only available in test builds,
453# test_auxdata(). Function test_auxdata() takes any number of arguments.
454do_test func-13.1 {
455 execsql {
456 SELECT test_auxdata('hello world');
457 }
458} {0}
danielk1977ece80f12004-06-23 01:05:26 +0000459
danielk19773f6b0872004-06-17 05:36:44 +0000460do_test func-13.2 {
461 execsql {
462 CREATE TABLE t4(a, b);
463 INSERT INTO t4 VALUES('abc', 'def');
464 INSERT INTO t4 VALUES('ghi', 'jkl');
465 }
466} {}
467do_test func-13.3 {
468 execsql {
469 SELECT test_auxdata('hello world') FROM t4;
470 }
471} {0 1}
472do_test func-13.4 {
473 execsql {
474 SELECT test_auxdata('hello world', 123) FROM t4;
475 }
476} {{0 0} {1 1}}
477do_test func-13.5 {
478 execsql {
479 SELECT test_auxdata('hello world', a) FROM t4;
480 }
481} {{0 0} {1 0}}
482do_test func-13.6 {
483 execsql {
484 SELECT test_auxdata('hello'||'world', a) FROM t4;
485 }
486} {{0 0} {1 0}}
487
488# Test that auxilary data is preserved between calls for SQL variables.
489do_test func-13.7 {
drhdddca282006-01-03 00:33:50 +0000490 set DB [sqlite3_connection_pointer db]
danielk19773f6b0872004-06-17 05:36:44 +0000491 set sql "SELECT test_auxdata( ? , a ) FROM t4;"
492 set STMT [sqlite3_prepare $DB $sql -1 TAIL]
493 sqlite3_bind_text $STMT 1 hello -1
494 set res [list]
495 while { "SQLITE_ROW"==[sqlite3_step $STMT] } {
496 lappend res [sqlite3_column_text $STMT 0]
497 }
498 lappend res [sqlite3_finalize $STMT]
499} {{0 0} {1 0} SQLITE_OK}
danielk1977d8123362004-06-12 09:25:12 +0000500
danielk1977312d6b32004-06-29 13:18:23 +0000501# Make sure that a function with a very long name is rejected
502do_test func-14.1 {
503 catch {
504 db function [string repeat X 254] {return "hello"}
505 }
506} {0}
507do_test func-14.2 {
508 catch {
509 db function [string repeat X 256] {return "hello"}
510 }
511} {1}
512
danielk197701427a62005-01-11 13:02:33 +0000513do_test func-15.1 {
514 catchsql {
515 select test_error(NULL);
516 }
drh90669c12006-01-20 15:45:36 +0000517} {1 {}}
danielk197701427a62005-01-11 13:02:33 +0000518
danielk1977576ec6b2005-01-21 11:55:25 +0000519# Test the quote function for BLOB and NULL values.
520do_test func-16.1 {
521 execsql {
522 CREATE TABLE tbl2(a, b);
523 }
524 set STMT [sqlite3_prepare $::DB "INSERT INTO tbl2 VALUES(?, ?)" -1 TAIL]
525 sqlite3_bind_blob $::STMT 1 abc 3
526 sqlite3_step $::STMT
527 sqlite3_finalize $::STMT
528 execsql {
529 SELECT quote(a), quote(b) FROM tbl2;
530 }
531} {X'616263' NULL}
532
drh2501eb12005-08-12 23:20:53 +0000533# Correctly handle function error messages that include %. Ticket #1354
534#
535do_test func-17.1 {
536 proc testfunc1 args {error "Error %d with %s percents %p"}
537 db function testfunc1 ::testfunc1
538 catchsql {
539 SELECT testfunc1(1,2,3);
540 }
541} {1 {Error %d with %s percents %p}}
542
drh3d1d95e2005-09-08 10:37:01 +0000543# The SUM function should return integer results when all inputs are integer.
544#
545do_test func-18.1 {
546 execsql {
547 CREATE TABLE t5(x);
548 INSERT INTO t5 VALUES(1);
549 INSERT INTO t5 VALUES(-99);
550 INSERT INTO t5 VALUES(10000);
551 SELECT sum(x) FROM t5;
552 }
553} {9902}
554do_test func-18.2 {
555 execsql {
556 INSERT INTO t5 VALUES(0.0);
557 SELECT sum(x) FROM t5;
558 }
drh8a512562005-11-14 22:29:05 +0000559} {9902.0}
danielk1977576ec6b2005-01-21 11:55:25 +0000560
drhc2bd9132005-09-08 20:37:43 +0000561# The sum of nothing is NULL. But the sum of all NULLs is NULL.
drh3f219f42005-09-08 19:45:57 +0000562#
drh76c730c2006-02-09 17:47:42 +0000563# The TOTAL of nothing is 0.0.
564#
drh3f219f42005-09-08 19:45:57 +0000565do_test func-18.3 {
566 execsql {
567 DELETE FROM t5;
drh76c730c2006-02-09 17:47:42 +0000568 SELECT sum(x), total(x) FROM t5;
drh3f219f42005-09-08 19:45:57 +0000569 }
drh76c730c2006-02-09 17:47:42 +0000570} {{} 0.0}
drh3f219f42005-09-08 19:45:57 +0000571do_test func-18.4 {
572 execsql {
573 INSERT INTO t5 VALUES(NULL);
drh76c730c2006-02-09 17:47:42 +0000574 SELECT sum(x), total(x) FROM t5
drh3f219f42005-09-08 19:45:57 +0000575 }
drh76c730c2006-02-09 17:47:42 +0000576} {{} 0.0}
drh3f219f42005-09-08 19:45:57 +0000577do_test func-18.5 {
578 execsql {
579 INSERT INTO t5 VALUES(NULL);
drh76c730c2006-02-09 17:47:42 +0000580 SELECT sum(x), total(x) FROM t5
drh3f219f42005-09-08 19:45:57 +0000581 }
drh76c730c2006-02-09 17:47:42 +0000582} {{} 0.0}
drh3f219f42005-09-08 19:45:57 +0000583do_test func-18.6 {
584 execsql {
585 INSERT INTO t5 VALUES(123);
drh76c730c2006-02-09 17:47:42 +0000586 SELECT sum(x), total(x) FROM t5
drh3f219f42005-09-08 19:45:57 +0000587 }
drh76c730c2006-02-09 17:47:42 +0000588} {123 123.0}
drh5708d2d2005-06-22 10:53:59 +0000589
drh8c08e862006-02-11 17:34:00 +0000590# Ticket #1664, #1669, #1670, #1674: An integer overflow on SUM causes
591# an error. The non-standard TOTAL() function continues to give a helpful
592# result.
drhfc6ad392006-02-09 13:38:19 +0000593#
594do_test func-18.10 {
595 execsql {
596 CREATE TABLE t6(x INTEGER);
597 INSERT INTO t6 VALUES(1);
598 INSERT INTO t6 VALUES(1<<62);
599 SELECT sum(x) - ((1<<62)+1) from t6;
600 }
601} 0
drh76c730c2006-02-09 17:47:42 +0000602do_test func-18.11 {
603 execsql {
604 SELECT typeof(sum(x)) FROM t6
605 }
606} integer
607do_test func-18.12 {
drh8c08e862006-02-11 17:34:00 +0000608 catchsql {
drh76c730c2006-02-09 17:47:42 +0000609 INSERT INTO t6 VALUES(1<<62);
610 SELECT sum(x) - ((1<<62)*2.0+1) from t6;
611 }
drh8c08e862006-02-11 17:34:00 +0000612} {1 {integer overflow}}
drh76c730c2006-02-09 17:47:42 +0000613do_test func-18.13 {
614 execsql {
615 SELECT total(x) - ((1<<62)*2.0+1) FROM t6
616 }
617} 0.0
drh8c08e862006-02-11 17:34:00 +0000618do_test func-18.14 {
619 execsql {
620 SELECT sum(-9223372036854775805);
621 }
622} -9223372036854775805
danielk19774b2688a2006-06-20 11:01:07 +0000623
624ifcapable compound&&subquery {
625
drh8c08e862006-02-11 17:34:00 +0000626do_test func-18.15 {
627 catchsql {
628 SELECT sum(x) FROM
629 (SELECT 9223372036854775807 AS x UNION ALL
630 SELECT 10 AS x);
631 }
632} {1 {integer overflow}}
633do_test func-18.16 {
634 catchsql {
635 SELECT sum(x) FROM
636 (SELECT 9223372036854775807 AS x UNION ALL
637 SELECT -10 AS x);
638 }
639} {0 9223372036854775797}
640do_test func-18.17 {
641 catchsql {
642 SELECT sum(x) FROM
643 (SELECT -9223372036854775807 AS x UNION ALL
644 SELECT 10 AS x);
645 }
646} {0 -9223372036854775797}
647do_test func-18.18 {
648 catchsql {
649 SELECT sum(x) FROM
650 (SELECT -9223372036854775807 AS x UNION ALL
651 SELECT -10 AS x);
652 }
653} {1 {integer overflow}}
654do_test func-18.19 {
655 catchsql {
656 SELECT sum(x) FROM (SELECT 9 AS x UNION ALL SELECT -10 AS x);
657 }
658} {0 -1}
659do_test func-18.20 {
660 catchsql {
661 SELECT sum(x) FROM (SELECT -9 AS x UNION ALL SELECT 10 AS x);
662 }
663} {0 1}
664do_test func-18.21 {
665 catchsql {
666 SELECT sum(x) FROM (SELECT -10 AS x UNION ALL SELECT 9 AS x);
667 }
668} {0 -1}
669do_test func-18.22 {
670 catchsql {
671 SELECT sum(x) FROM (SELECT 10 AS x UNION ALL SELECT -9 AS x);
672 }
673} {0 1}
drh76c730c2006-02-09 17:47:42 +0000674
danielk19774b2688a2006-06-20 11:01:07 +0000675} ;# ifcapable compound&&subquery
676
drh52fc8492006-02-23 21:43:55 +0000677# Integer overflow on abs()
678#
679do_test func-18.31 {
680 catchsql {
681 SELECT abs(-9223372036854775807);
682 }
683} {0 9223372036854775807}
684do_test func-18.32 {
685 catchsql {
686 SELECT abs(-9223372036854775807-1);
687 }
688} {1 {integer overflow}}
689
drh7f375902006-06-13 17:38:59 +0000690# The MATCH function exists but is only a stub and always throws an error.
691#
692do_test func-19.1 {
693 execsql {
694 SELECT match(a,b) FROM t1 WHERE 0;
695 }
696} {}
697do_test func-19.2 {
698 catchsql {
699 SELECT 'abc' MATCH 'xyz';
700 }
drhb7481e72006-09-16 21:45:14 +0000701} {1 {unable to use function MATCH in the requested context}}
drh7f375902006-06-13 17:38:59 +0000702do_test func-19.3 {
703 catchsql {
704 SELECT 'abc' NOT MATCH 'xyz';
705 }
drhb7481e72006-09-16 21:45:14 +0000706} {1 {unable to use function MATCH in the requested context}}
drh7f375902006-06-13 17:38:59 +0000707do_test func-19.4 {
708 catchsql {
709 SELECT match(1,2,3);
710 }
711} {1 {wrong number of arguments to function match()}}
drh76c730c2006-02-09 17:47:42 +0000712
drhbdf67e02006-08-19 11:34:01 +0000713# Soundex tests.
714#
715if {![catch {db eval {SELECT soundex('hello')}}]} {
716 set i 0
717 foreach {name sdx} {
718 euler E460
719 EULER E460
720 Euler E460
721 ellery E460
722 gauss G200
723 ghosh G200
724 hilbert H416
725 Heilbronn H416
726 knuth K530
727 kant K530
728 Lloyd L300
729 LADD L300
730 Lukasiewicz L222
731 Lissajous L222
732 A A000
733 12345 ?000
734 } {
735 incr i
736 do_test func-20.$i {
737 execsql {SELECT soundex($name)}
738 } $sdx
739 }
740}
741
drh26b6d902007-03-17 13:27:54 +0000742# Tests of the REPLACE function.
743#
744do_test func-21.1 {
745 catchsql {
746 SELECT replace(1,2);
747 }
748} {1 {wrong number of arguments to function replace()}}
749do_test func-21.2 {
750 catchsql {
751 SELECT replace(1,2,3,4);
752 }
753} {1 {wrong number of arguments to function replace()}}
754do_test func-21.3 {
755 execsql {
756 SELECT typeof(replace("This is the main test string", NULL, "ALT"));
757 }
758} {null}
759do_test func-21.4 {
760 execsql {
761 SELECT typeof(replace(NULL, "main", "ALT"));
762 }
763} {null}
764do_test func-21.5 {
765 execsql {
766 SELECT typeof(replace("This is the main test string", "main", NULL));
767 }
768} {null}
769do_test func-21.6 {
770 execsql {
771 SELECT replace("This is the main test string", "main", "ALT");
772 }
773} {{This is the ALT test string}}
774do_test func-21.7 {
775 execsql {
776 SELECT replace("This is the main test string", "main", "larger-main");
777 }
778} {{This is the larger-main test string}}
779do_test func-21.8 {
780 execsql {
781 SELECT replace("aaaaaaa", "a", "0123456789");
782 }
783} {0123456789012345678901234567890123456789012345678901234567890123456789}
784
drh309b3382007-03-17 17:52:42 +0000785# Tests for the TRIM, LTRIM and RTRIM functions.
786#
787do_test func-22.1 {
788 catchsql {SELECT trim(1,2,3)}
789} {1 {wrong number of arguments to function trim()}}
790do_test func-22.2 {
791 catchsql {SELECT ltrim(1,2,3)}
792} {1 {wrong number of arguments to function ltrim()}}
793do_test func-22.3 {
794 catchsql {SELECT rtrim(1,2,3)}
795} {1 {wrong number of arguments to function rtrim()}}
796do_test func-22.4 {
797 execsql {SELECT trim(' hi ');}
798} {hi}
799do_test func-22.5 {
800 execsql {SELECT ltrim(' hi ');}
801} {{hi }}
802do_test func-22.6 {
803 execsql {SELECT rtrim(' hi ');}
804} {{ hi}}
805do_test func-22.7 {
806 execsql {SELECT trim(' hi ','xyz');}
807} {{ hi }}
808do_test func-22.8 {
809 execsql {SELECT ltrim(' hi ','xyz');}
810} {{ hi }}
811do_test func-22.9 {
812 execsql {SELECT rtrim(' hi ','xyz');}
813} {{ hi }}
814do_test func-22.10 {
815 execsql {SELECT trim('xyxzy hi zzzy','xyz');}
816} {{ hi }}
817do_test func-22.11 {
818 execsql {SELECT ltrim('xyxzy hi zzzy','xyz');}
819} {{ hi zzzy}}
820do_test func-22.12 {
821 execsql {SELECT rtrim('xyxzy hi zzzy','xyz');}
822} {{xyxzy hi }}
823do_test func-22.13 {
824 execsql {SELECT trim(' hi ','');}
825} {{ hi }}
drhd1e3a612007-04-27 21:59:52 +0000826do_test func-22.14 {
drh7a928d72007-05-02 15:36:01 +0000827 execsql {SELECT hex(trim(x'c280e1bfbff48fbfbf6869',x'6162e1bfbfc280'))}
828} {F48FBFBF6869}
drhd1e3a612007-04-27 21:59:52 +0000829do_test func-22.15 {
drh7a928d72007-05-02 15:36:01 +0000830 execsql {SELECT hex(trim(x'6869c280e1bfbff48fbfbf61',
831 x'6162e1bfbfc280f48fbfbf'))}
drhd1e3a612007-04-27 21:59:52 +0000832} {6869}
833do_test func-22.16 {
834 execsql {SELECT hex(trim(x'ceb1ceb2ceb3',x'ceb1'));}
835} {CEB2CEB3}
drh309b3382007-03-17 17:52:42 +0000836do_test func-22.20 {
837 execsql {SELECT typeof(trim(NULL));}
838} {null}
839do_test func-22.21 {
840 execsql {SELECT typeof(trim(NULL,'xyz'));}
841} {null}
842do_test func-22.22 {
843 execsql {SELECT typeof(trim('hello',NULL));}
844} {null}
drh26b6d902007-03-17 13:27:54 +0000845
drh5708d2d2005-06-22 10:53:59 +0000846finish_test