blob: 7c7d55e1b706a9c16bd321cb3e3f4f0722645e4c [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#
drhff6e9112000-08-28 16:21:58 +000014
15set testdir [file dirname $argv0]
16source $testdir/tester.tcl
mistachkin9ed04eb2013-07-19 23:58:41 +000017set testprefix func
drhff6e9112000-08-28 16:21:58 +000018
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#
shanefbd60f82009-02-04 03:59:25 +0000152ifcapable !floatingpoint {
153 do_test func-4.1 {
154 execsql {
155 CREATE TABLE t1(a,b,c);
156 INSERT INTO t1 VALUES(1,2,3);
157 INSERT INTO t1 VALUES(2,12345678901234,-1234567890);
158 INSERT INTO t1 VALUES(3,-2,-5);
159 }
160 catchsql {SELECT abs(a,b) FROM t1}
161 } {1 {wrong number of arguments to function abs()}}
162}
163ifcapable floatingpoint {
164 do_test func-4.1 {
165 execsql {
166 CREATE TABLE t1(a,b,c);
167 INSERT INTO t1 VALUES(1,2,3);
168 INSERT INTO t1 VALUES(2,1.2345678901234,-12345.67890);
169 INSERT INTO t1 VALUES(3,-2,-5);
170 }
171 catchsql {SELECT abs(a,b) FROM t1}
172 } {1 {wrong number of arguments to function abs()}}
173}
drhbf4133c2001-10-13 02:59:08 +0000174do_test func-4.2 {
175 catchsql {SELECT abs() FROM t1}
drh89425d52002-02-28 03:04:48 +0000176} {1 {wrong number of arguments to function abs()}}
shanefbd60f82009-02-04 03:59:25 +0000177ifcapable floatingpoint {
178 do_test func-4.3 {
179 catchsql {SELECT abs(b) FROM t1 ORDER BY a}
180 } {0 {2 1.2345678901234 2}}
181 do_test func-4.4 {
182 catchsql {SELECT abs(c) FROM t1 ORDER BY a}
183 } {0 {3 12345.6789 5}}
184}
185ifcapable !floatingpoint {
186 if {[working_64bit_int]} {
187 do_test func-4.3 {
188 catchsql {SELECT abs(b) FROM t1 ORDER BY a}
189 } {0 {2 12345678901234 2}}
190 }
191 do_test func-4.4 {
192 catchsql {SELECT abs(c) FROM t1 ORDER BY a}
193 } {0 {3 1234567890 5}}
194}
drh832508b2002-03-02 17:04:07 +0000195do_test func-4.4.1 {
196 execsql {SELECT abs(a) FROM t2}
197} {1 {} 345 {} 67890}
198do_test func-4.4.2 {
199 execsql {SELECT abs(t1) FROM tbl1}
drh92febd92004-08-20 18:34:20 +0000200} {0.0 0.0 0.0 0.0 0.0}
drhbf4133c2001-10-13 02:59:08 +0000201
shanefbd60f82009-02-04 03:59:25 +0000202ifcapable floatingpoint {
203 do_test func-4.5 {
204 catchsql {SELECT round(a,b,c) FROM t1}
205 } {1 {wrong number of arguments to function round()}}
206 do_test func-4.6 {
207 catchsql {SELECT round(b,2) FROM t1 ORDER BY b}
208 } {0 {-2.0 1.23 2.0}}
209 do_test func-4.7 {
210 catchsql {SELECT round(b,0) FROM t1 ORDER BY a}
211 } {0 {2.0 1.0 -2.0}}
212 do_test func-4.8 {
213 catchsql {SELECT round(c) FROM t1 ORDER BY a}
214 } {0 {3.0 -12346.0 -5.0}}
215 do_test func-4.9 {
216 catchsql {SELECT round(c,a) FROM t1 ORDER BY a}
217 } {0 {3.0 -12345.68 -5.0}}
218 do_test func-4.10 {
219 catchsql {SELECT 'x' || round(c,a) || 'y' FROM t1 ORDER BY a}
220 } {0 {x3.0y x-12345.68y x-5.0y}}
221 do_test func-4.11 {
222 catchsql {SELECT round() FROM t1 ORDER BY a}
223 } {1 {wrong number of arguments to function round()}}
224 do_test func-4.12 {
225 execsql {SELECT coalesce(round(a,2),'nil') FROM t2}
226 } {1.0 nil 345.0 nil 67890.0}
227 do_test func-4.13 {
228 execsql {SELECT round(t1,2) FROM tbl1}
229 } {0.0 0.0 0.0 0.0 0.0}
230 do_test func-4.14 {
231 execsql {SELECT typeof(round(5.1,1));}
232 } {real}
233 do_test func-4.15 {
234 execsql {SELECT typeof(round(5.1));}
235 } {real}
236 do_test func-4.16 {
237 catchsql {SELECT round(b,2.0) FROM t1 ORDER BY b}
238 } {0 {-2.0 1.23 2.0}}
shaneh4a0b43c2010-02-16 22:00:35 +0000239 # Verify some values reported on the mailing list.
240 # Some of these fail on MSVC builds with 64-bit
241 # long doubles, but not on GCC builds with 80-bit
242 # long doubles.
243 for {set i 1} {$i<999} {incr i} {
shaneh35c1a792010-02-17 03:57:58 +0000244 set x1 [expr 40222.5 + $i]
shaneh4a0b43c2010-02-16 22:00:35 +0000245 set x2 [expr 40223.0 + $i]
246 do_test func-4.17.$i {
247 execsql {SELECT round($x1);}
248 } $x2
249 }
shaneh35c1a792010-02-17 03:57:58 +0000250 for {set i 1} {$i<999} {incr i} {
251 set x1 [expr 40222.05 + $i]
252 set x2 [expr 40222.10 + $i]
253 do_test func-4.18.$i {
254 execsql {SELECT round($x1,1);}
255 } $x2
256 }
shaneh4a0b43c2010-02-16 22:00:35 +0000257 do_test func-4.20 {
258 execsql {SELECT round(40223.4999999999);}
259 } {40223.0}
260 do_test func-4.21 {
261 execsql {SELECT round(40224.4999999999);}
262 } {40224.0}
263 do_test func-4.22 {
264 execsql {SELECT round(40225.4999999999);}
265 } {40225.0}
266 for {set i 1} {$i<10} {incr i} {
267 do_test func-4.23.$i {
268 execsql {SELECT round(40223.4999999999,$i);}
269 } {40223.5}
270 do_test func-4.24.$i {
271 execsql {SELECT round(40224.4999999999,$i);}
272 } {40224.5}
273 do_test func-4.25.$i {
274 execsql {SELECT round(40225.4999999999,$i);}
275 } {40225.5}
276 }
277 for {set i 10} {$i<32} {incr i} {
278 do_test func-4.26.$i {
279 execsql {SELECT round(40223.4999999999,$i);}
280 } {40223.4999999999}
281 do_test func-4.27.$i {
282 execsql {SELECT round(40224.4999999999,$i);}
283 } {40224.4999999999}
284 do_test func-4.28.$i {
285 execsql {SELECT round(40225.4999999999,$i);}
286 } {40225.4999999999}
287 }
288 do_test func-4.29 {
289 execsql {SELECT round(1234567890.5);}
290 } {1234567891.0}
291 do_test func-4.30 {
292 execsql {SELECT round(12345678901.5);}
293 } {12345678902.0}
294 do_test func-4.31 {
295 execsql {SELECT round(123456789012.5);}
296 } {123456789013.0}
297 do_test func-4.32 {
298 execsql {SELECT round(1234567890123.5);}
299 } {1234567890124.0}
300 do_test func-4.33 {
301 execsql {SELECT round(12345678901234.5);}
302 } {12345678901235.0}
303 do_test func-4.34 {
304 execsql {SELECT round(1234567890123.35,1);}
305 } {1234567890123.4}
306 do_test func-4.35 {
307 execsql {SELECT round(1234567890123.445,2);}
308 } {1234567890123.45}
309 do_test func-4.36 {
310 execsql {SELECT round(99999999999994.5);}
311 } {99999999999995.0}
312 do_test func-4.37 {
313 execsql {SELECT round(9999999999999.55,1);}
314 } {9999999999999.6}
315 do_test func-4.38 {
drh4aaf1552012-06-19 03:59:30 +0000316 execsql {SELECT round(9999999999999.556,2);}
shaneh4a0b43c2010-02-16 22:00:35 +0000317 } {9999999999999.56}
shanefbd60f82009-02-04 03:59:25 +0000318}
drh832508b2002-03-02 17:04:07 +0000319
320# Test the upper() and lower() functions
321#
322do_test func-5.1 {
323 execsql {SELECT upper(t1) FROM tbl1}
324} {THIS PROGRAM IS FREE SOFTWARE}
325do_test func-5.2 {
326 execsql {SELECT lower(upper(t1)) FROM tbl1}
327} {this program is free software}
328do_test func-5.3 {
329 execsql {SELECT upper(a), lower(a) FROM t2}
330} {1 1 {} {} 345 345 {} {} 67890 67890}
danielk19777de68a02007-05-07 16:58:02 +0000331ifcapable !icu {
332 do_test func-5.4 {
333 catchsql {SELECT upper(a,5) FROM t2}
334 } {1 {wrong number of arguments to function upper()}}
335}
drh832508b2002-03-02 17:04:07 +0000336do_test func-5.5 {
337 catchsql {SELECT upper(*) FROM t2}
338} {1 {wrong number of arguments to function upper()}}
339
drha9f9d1c2002-06-29 02:20:08 +0000340# Test the coalesce() and nullif() functions
drh832508b2002-03-02 17:04:07 +0000341#
342do_test func-6.1 {
343 execsql {SELECT coalesce(a,'xyz') FROM t2}
344} {1 xyz 345 xyz 67890}
345do_test func-6.2 {
346 execsql {SELECT coalesce(upper(a),'nil') FROM t2}
347} {1 nil 345 nil 67890}
drha9f9d1c2002-06-29 02:20:08 +0000348do_test func-6.3 {
349 execsql {SELECT coalesce(nullif(1,1),'nil')}
350} {nil}
351do_test func-6.4 {
352 execsql {SELECT coalesce(nullif(1,2),'nil')}
353} {1}
354do_test func-6.5 {
355 execsql {SELECT coalesce(nullif(1,NULL),'nil')}
356} {1}
357
drh832508b2002-03-02 17:04:07 +0000358
drh6ed41ad2002-04-06 14:10:47 +0000359# Test the last_insert_rowid() function
360#
361do_test func-7.1 {
362 execsql {SELECT last_insert_rowid()}
363} [db last_insert_rowid]
364
drh739105c2002-05-29 23:22:23 +0000365# Tests for aggregate functions and how they handle NULLs.
366#
shanefbd60f82009-02-04 03:59:25 +0000367ifcapable floatingpoint {
368 do_test func-8.1 {
369 ifcapable explain {
370 execsql {EXPLAIN SELECT sum(a) FROM t2;}
371 }
372 execsql {
373 SELECT sum(a), count(a), round(avg(a),2), min(a), max(a), count(*) FROM t2;
374 }
375 } {68236 3 22745.33 1 67890 5}
376}
377ifcapable !floatingpoint {
378 do_test func-8.1 {
379 ifcapable explain {
380 execsql {EXPLAIN SELECT sum(a) FROM t2;}
381 }
382 execsql {
383 SELECT sum(a), count(a), avg(a), min(a), max(a), count(*) FROM t2;
384 }
385 } {68236 3 22745.0 1 67890 5}
386}
drha9f9d1c2002-06-29 02:20:08 +0000387do_test func-8.2 {
388 execsql {
389 SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t2;
390 }
391} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
danielk197753c0f742005-03-29 03:10:59 +0000392
393ifcapable tempdb {
394 do_test func-8.3 {
395 execsql {
396 CREATE TEMP TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
397 SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
398 }
399 } {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
400} else {
401 do_test func-8.3 {
402 execsql {
403 CREATE TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
404 SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
405 }
406 } {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
407}
danielk19773aeab9e2004-06-24 00:20:04 +0000408do_test func-8.4 {
409 execsql {
410 SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
411 }
412} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
danielk1977de3e41e2008-08-04 03:51:24 +0000413ifcapable compound {
414 do_test func-8.5 {
415 execsql {
416 SELECT sum(x) FROM (SELECT '9223372036' || '854775807' AS x
417 UNION ALL SELECT -9223372036854775807)
418 }
419 } {0}
420 do_test func-8.6 {
421 execsql {
422 SELECT typeof(sum(x)) FROM (SELECT '9223372036' || '854775807' AS x
423 UNION ALL SELECT -9223372036854775807)
424 }
425 } {integer}
426 do_test func-8.7 {
427 execsql {
428 SELECT typeof(sum(x)) FROM (SELECT '9223372036' || '854775808' AS x
429 UNION ALL SELECT -9223372036854775807)
430 }
431 } {real}
shanefbd60f82009-02-04 03:59:25 +0000432ifcapable floatingpoint {
danielk1977de3e41e2008-08-04 03:51:24 +0000433 do_test func-8.8 {
434 execsql {
435 SELECT sum(x)>0.0 FROM (SELECT '9223372036' || '854775808' AS x
436 UNION ALL SELECT -9223372036850000000)
437 }
438 } {1}
439}
shanefbd60f82009-02-04 03:59:25 +0000440ifcapable !floatingpoint {
441 do_test func-8.8 {
442 execsql {
443 SELECT sum(x)>0 FROM (SELECT '9223372036' || '854775808' AS x
444 UNION ALL SELECT -9223372036850000000)
445 }
446 } {1}
447}
448}
drh739105c2002-05-29 23:22:23 +0000449
drha9f9d1c2002-06-29 02:20:08 +0000450# How do you test the random() function in a meaningful, deterministic way?
451#
452do_test func-9.1 {
453 execsql {
454 SELECT random() is not null;
455 }
456} {1}
drh63cf66f2007-01-29 15:50:05 +0000457do_test func-9.2 {
458 execsql {
459 SELECT typeof(random());
460 }
461} {integer}
462do_test func-9.3 {
463 execsql {
drh137c7282007-01-29 17:58:28 +0000464 SELECT randomblob(32) is not null;
drh63cf66f2007-01-29 15:50:05 +0000465 }
466} {1}
467do_test func-9.4 {
468 execsql {
drh137c7282007-01-29 17:58:28 +0000469 SELECT typeof(randomblob(32));
drh63cf66f2007-01-29 15:50:05 +0000470 }
drh137c7282007-01-29 17:58:28 +0000471} {blob}
drh63cf66f2007-01-29 15:50:05 +0000472do_test func-9.5 {
473 execsql {
drh137c7282007-01-29 17:58:28 +0000474 SELECT length(randomblob(32)), length(randomblob(-5)),
475 length(randomblob(2000))
drh63cf66f2007-01-29 15:50:05 +0000476 }
drh137c7282007-01-29 17:58:28 +0000477} {32 1 2000}
drh63cf66f2007-01-29 15:50:05 +0000478
drh137c7282007-01-29 17:58:28 +0000479# The "hex()" function was added in order to be able to render blobs
480# generated by randomblob(). So this seems like a good place to test
481# hex().
482#
danielk19774152e672007-09-12 17:01:45 +0000483ifcapable bloblit {
484 do_test func-9.10 {
485 execsql {SELECT hex(x'00112233445566778899aAbBcCdDeEfF')}
486 } {00112233445566778899AABBCCDDEEFF}
487}
drh056c8f72007-05-15 18:35:21 +0000488set encoding [db one {PRAGMA encoding}]
489if {$encoding=="UTF-16le"} {
490 do_test func-9.11-utf16le {
491 execsql {SELECT hex(replace('abcdefg','ef','12'))}
492 } {6100620063006400310032006700}
493 do_test func-9.12-utf16le {
494 execsql {SELECT hex(replace('abcdefg','','12'))}
drha605fe82009-02-01 18:08:40 +0000495 } {6100620063006400650066006700}
drh056c8f72007-05-15 18:35:21 +0000496 do_test func-9.13-utf16le {
497 execsql {SELECT hex(replace('aabcdefg','a','aaa'))}
498 } {610061006100610061006100620063006400650066006700}
499} elseif {$encoding=="UTF-8"} {
500 do_test func-9.11-utf8 {
501 execsql {SELECT hex(replace('abcdefg','ef','12'))}
502 } {61626364313267}
503 do_test func-9.12-utf8 {
504 execsql {SELECT hex(replace('abcdefg','','12'))}
drha605fe82009-02-01 18:08:40 +0000505 } {61626364656667}
drh056c8f72007-05-15 18:35:21 +0000506 do_test func-9.13-utf8 {
507 execsql {SELECT hex(replace('aabcdefg','a','aaa'))}
508 } {616161616161626364656667}
509}
510
drh6cbe1f12002-07-01 00:31:36 +0000511# Use the "sqlite_register_test_function" TCL command which is part of
512# the text fixture in order to verify correct operation of some of
513# the user-defined SQL function APIs that are not used by the built-in
514# functions.
515#
drhdddca282006-01-03 00:33:50 +0000516set ::DB [sqlite3_connection_pointer db]
drh6cbe1f12002-07-01 00:31:36 +0000517sqlite_register_test_function $::DB testfunc
518do_test func-10.1 {
519 catchsql {
520 SELECT testfunc(NULL,NULL);
521 }
danielk19776d88bad2004-05-27 14:23:36 +0000522} {1 {first argument should be one of: int int64 string double null value}}
drh6cbe1f12002-07-01 00:31:36 +0000523do_test func-10.2 {
524 execsql {
525 SELECT testfunc(
526 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
527 'int', 1234
528 );
529 }
530} {1234}
531do_test func-10.3 {
532 execsql {
533 SELECT testfunc(
534 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
535 'string', NULL
536 );
537 }
538} {{}}
shanefbd60f82009-02-04 03:59:25 +0000539
540ifcapable floatingpoint {
541 do_test func-10.4 {
542 execsql {
543 SELECT testfunc(
544 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
545 'double', 1.234
546 );
547 }
548 } {1.234}
549 do_test func-10.5 {
550 execsql {
551 SELECT testfunc(
552 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
553 'int', 1234,
554 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
555 'string', NULL,
556 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
557 'double', 1.234,
558 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
559 'int', 1234,
560 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
561 'string', NULL,
562 'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
563 'double', 1.234
564 );
565 }
566 } {1.234}
567}
drh6cbe1f12002-07-01 00:31:36 +0000568
drh647cb0e2002-11-04 19:32:25 +0000569# Test the built-in sqlite_version(*) SQL function.
570#
571do_test func-11.1 {
572 execsql {
573 SELECT sqlite_version(*);
574 }
drhef4ac8f2004-06-19 00:16:31 +0000575} [sqlite3 -version]
drh647cb0e2002-11-04 19:32:25 +0000576
drhef4ac8f2004-06-19 00:16:31 +0000577# Test that destructors passed to sqlite3 by calls to sqlite3_result_text()
danielk19773f6b0872004-06-17 05:36:44 +0000578# etc. are called. These tests use two special user-defined functions
579# (implemented in func.c) only available in test builds.
580#
581# Function test_destructor() takes one argument and returns a copy of the
582# text form of that argument. A destructor is associated with the return
583# value. Function test_destructor_count() returns the number of outstanding
584# destructor calls for values returned by test_destructor().
585#
drhda84ca82008-03-19 16:35:24 +0000586if {[db eval {PRAGMA encoding}]=="UTF-8"} {
587 do_test func-12.1-utf8 {
588 execsql {
589 SELECT test_destructor('hello world'), test_destructor_count();
590 }
591 } {{hello world} 1}
592} else {
shane2a5fc4d2008-07-31 01:47:11 +0000593 ifcapable {utf16} {
594 do_test func-12.1-utf16 {
595 execsql {
596 SELECT test_destructor16('hello world'), test_destructor_count();
597 }
598 } {{hello world} 1}
drhda84ca82008-03-19 16:35:24 +0000599 }
drhda84ca82008-03-19 16:35:24 +0000600}
danielk1977d8123362004-06-12 09:25:12 +0000601do_test func-12.2 {
602 execsql {
603 SELECT test_destructor_count();
604 }
605} {0}
606do_test func-12.3 {
607 execsql {
drh2dcef112008-01-12 19:03:48 +0000608 SELECT test_destructor('hello')||' world'
danielk1977d8123362004-06-12 09:25:12 +0000609 }
drh2dcef112008-01-12 19:03:48 +0000610} {{hello world}}
danielk1977d8123362004-06-12 09:25:12 +0000611do_test func-12.4 {
612 execsql {
613 SELECT test_destructor_count();
614 }
615} {0}
616do_test func-12.5 {
617 execsql {
618 CREATE TABLE t4(x);
619 INSERT INTO t4 VALUES(test_destructor('hello'));
620 INSERT INTO t4 VALUES(test_destructor('world'));
621 SELECT min(test_destructor(x)), max(test_destructor(x)) FROM t4;
622 }
623} {hello world}
624do_test func-12.6 {
625 execsql {
626 SELECT test_destructor_count();
627 }
628} {0}
danielk19773f6b0872004-06-17 05:36:44 +0000629do_test func-12.7 {
630 execsql {
631 DROP TABLE t4;
632 }
633} {}
634
drha4e5d582007-10-20 15:41:57 +0000635
danielk19773f6b0872004-06-17 05:36:44 +0000636# Test that the auxdata API for scalar functions works. This test uses
637# a special user-defined function only available in test builds,
638# test_auxdata(). Function test_auxdata() takes any number of arguments.
639do_test func-13.1 {
640 execsql {
641 SELECT test_auxdata('hello world');
642 }
643} {0}
danielk1977ece80f12004-06-23 01:05:26 +0000644
danielk19773f6b0872004-06-17 05:36:44 +0000645do_test func-13.2 {
646 execsql {
647 CREATE TABLE t4(a, b);
648 INSERT INTO t4 VALUES('abc', 'def');
649 INSERT INTO t4 VALUES('ghi', 'jkl');
650 }
651} {}
652do_test func-13.3 {
653 execsql {
654 SELECT test_auxdata('hello world') FROM t4;
655 }
656} {0 1}
657do_test func-13.4 {
658 execsql {
659 SELECT test_auxdata('hello world', 123) FROM t4;
660 }
661} {{0 0} {1 1}}
662do_test func-13.5 {
663 execsql {
664 SELECT test_auxdata('hello world', a) FROM t4;
665 }
666} {{0 0} {1 0}}
667do_test func-13.6 {
668 execsql {
669 SELECT test_auxdata('hello'||'world', a) FROM t4;
670 }
671} {{0 0} {1 0}}
672
673# Test that auxilary data is preserved between calls for SQL variables.
674do_test func-13.7 {
drhdddca282006-01-03 00:33:50 +0000675 set DB [sqlite3_connection_pointer db]
danielk19773f6b0872004-06-17 05:36:44 +0000676 set sql "SELECT test_auxdata( ? , a ) FROM t4;"
677 set STMT [sqlite3_prepare $DB $sql -1 TAIL]
drh10dfbbb2008-04-16 12:58:53 +0000678 sqlite3_bind_text $STMT 1 hello\000 -1
danielk19773f6b0872004-06-17 05:36:44 +0000679 set res [list]
680 while { "SQLITE_ROW"==[sqlite3_step $STMT] } {
681 lappend res [sqlite3_column_text $STMT 0]
682 }
683 lappend res [sqlite3_finalize $STMT]
684} {{0 0} {1 0} SQLITE_OK}
danielk1977d8123362004-06-12 09:25:12 +0000685
dan0c547792013-07-18 17:12:08 +0000686# Test that auxiliary data is discarded when a statement is reset.
687do_execsql_test 13.8.1 {
688 SELECT test_auxdata('constant') FROM t4;
689} {0 1}
690do_execsql_test 13.8.2 {
691 SELECT test_auxdata('constant') FROM t4;
692} {0 1}
693db cache flush
694do_execsql_test 13.8.3 {
695 SELECT test_auxdata('constant') FROM t4;
696} {0 1}
697set V "one"
698do_execsql_test 13.8.4 {
699 SELECT test_auxdata($V), $V FROM t4;
700} {0 one 1 one}
701set V "two"
702do_execsql_test 13.8.5 {
703 SELECT test_auxdata($V), $V FROM t4;
704} {0 two 1 two}
705db cache flush
706set V "three"
mistachkin9ed04eb2013-07-19 23:58:41 +0000707do_execsql_test 13.8.6 {
dan0c547792013-07-18 17:12:08 +0000708 SELECT test_auxdata($V), $V FROM t4;
709} {0 three 1 three}
710
711
danielk1977312d6b32004-06-29 13:18:23 +0000712# Make sure that a function with a very long name is rejected
713do_test func-14.1 {
714 catch {
715 db function [string repeat X 254] {return "hello"}
716 }
717} {0}
718do_test func-14.2 {
719 catch {
720 db function [string repeat X 256] {return "hello"}
721 }
722} {1}
723
danielk197701427a62005-01-11 13:02:33 +0000724do_test func-15.1 {
drh00e087b2008-04-10 17:14:07 +0000725 catchsql {select test_error(NULL)}
drh90669c12006-01-20 15:45:36 +0000726} {1 {}}
drh00e087b2008-04-10 17:14:07 +0000727do_test func-15.2 {
728 catchsql {select test_error('this is the error message')}
729} {1 {this is the error message}}
730do_test func-15.3 {
731 catchsql {select test_error('this is the error message',12)}
732} {1 {this is the error message}}
733do_test func-15.4 {
734 db errorcode
735} {12}
danielk197701427a62005-01-11 13:02:33 +0000736
danielk1977576ec6b2005-01-21 11:55:25 +0000737# Test the quote function for BLOB and NULL values.
738do_test func-16.1 {
739 execsql {
740 CREATE TABLE tbl2(a, b);
741 }
742 set STMT [sqlite3_prepare $::DB "INSERT INTO tbl2 VALUES(?, ?)" -1 TAIL]
743 sqlite3_bind_blob $::STMT 1 abc 3
744 sqlite3_step $::STMT
745 sqlite3_finalize $::STMT
746 execsql {
747 SELECT quote(a), quote(b) FROM tbl2;
748 }
749} {X'616263' NULL}
750
drh2501eb12005-08-12 23:20:53 +0000751# Correctly handle function error messages that include %. Ticket #1354
752#
753do_test func-17.1 {
754 proc testfunc1 args {error "Error %d with %s percents %p"}
755 db function testfunc1 ::testfunc1
756 catchsql {
757 SELECT testfunc1(1,2,3);
758 }
759} {1 {Error %d with %s percents %p}}
760
drh3d1d95e2005-09-08 10:37:01 +0000761# The SUM function should return integer results when all inputs are integer.
762#
763do_test func-18.1 {
764 execsql {
765 CREATE TABLE t5(x);
766 INSERT INTO t5 VALUES(1);
767 INSERT INTO t5 VALUES(-99);
768 INSERT INTO t5 VALUES(10000);
769 SELECT sum(x) FROM t5;
770 }
771} {9902}
shanefbd60f82009-02-04 03:59:25 +0000772ifcapable floatingpoint {
773 do_test func-18.2 {
774 execsql {
775 INSERT INTO t5 VALUES(0.0);
776 SELECT sum(x) FROM t5;
777 }
778 } {9902.0}
779}
danielk1977576ec6b2005-01-21 11:55:25 +0000780
drhc2bd9132005-09-08 20:37:43 +0000781# The sum of nothing is NULL. But the sum of all NULLs is NULL.
drh3f219f42005-09-08 19:45:57 +0000782#
drh76c730c2006-02-09 17:47:42 +0000783# The TOTAL of nothing is 0.0.
784#
drh3f219f42005-09-08 19:45:57 +0000785do_test func-18.3 {
786 execsql {
787 DELETE FROM t5;
drh76c730c2006-02-09 17:47:42 +0000788 SELECT sum(x), total(x) FROM t5;
drh3f219f42005-09-08 19:45:57 +0000789 }
drh76c730c2006-02-09 17:47:42 +0000790} {{} 0.0}
drh3f219f42005-09-08 19:45:57 +0000791do_test func-18.4 {
792 execsql {
793 INSERT INTO t5 VALUES(NULL);
drh76c730c2006-02-09 17:47:42 +0000794 SELECT sum(x), total(x) FROM t5
drh3f219f42005-09-08 19:45:57 +0000795 }
drh76c730c2006-02-09 17:47:42 +0000796} {{} 0.0}
drh3f219f42005-09-08 19:45:57 +0000797do_test func-18.5 {
798 execsql {
799 INSERT INTO t5 VALUES(NULL);
drh76c730c2006-02-09 17:47:42 +0000800 SELECT sum(x), total(x) FROM t5
drh3f219f42005-09-08 19:45:57 +0000801 }
drh76c730c2006-02-09 17:47:42 +0000802} {{} 0.0}
drh3f219f42005-09-08 19:45:57 +0000803do_test func-18.6 {
804 execsql {
805 INSERT INTO t5 VALUES(123);
drh76c730c2006-02-09 17:47:42 +0000806 SELECT sum(x), total(x) FROM t5
drh3f219f42005-09-08 19:45:57 +0000807 }
drh76c730c2006-02-09 17:47:42 +0000808} {123 123.0}
drh5708d2d2005-06-22 10:53:59 +0000809
drh8c08e862006-02-11 17:34:00 +0000810# Ticket #1664, #1669, #1670, #1674: An integer overflow on SUM causes
811# an error. The non-standard TOTAL() function continues to give a helpful
812# result.
drhfc6ad392006-02-09 13:38:19 +0000813#
814do_test func-18.10 {
815 execsql {
816 CREATE TABLE t6(x INTEGER);
817 INSERT INTO t6 VALUES(1);
818 INSERT INTO t6 VALUES(1<<62);
819 SELECT sum(x) - ((1<<62)+1) from t6;
820 }
821} 0
drh76c730c2006-02-09 17:47:42 +0000822do_test func-18.11 {
823 execsql {
824 SELECT typeof(sum(x)) FROM t6
825 }
826} integer
shanefbd60f82009-02-04 03:59:25 +0000827ifcapable floatingpoint {
828 do_test func-18.12 {
829 catchsql {
830 INSERT INTO t6 VALUES(1<<62);
831 SELECT sum(x) - ((1<<62)*2.0+1) from t6;
832 }
833 } {1 {integer overflow}}
834 do_test func-18.13 {
835 execsql {
836 SELECT total(x) - ((1<<62)*2.0+1) FROM t6
837 }
838 } 0.0
839}
840ifcapable !floatingpoint {
841 do_test func-18.12 {
842 catchsql {
843 INSERT INTO t6 VALUES(1<<62);
844 SELECT sum(x) - ((1<<62)*2+1) from t6;
845 }
846 } {1 {integer overflow}}
847 do_test func-18.13 {
848 execsql {
849 SELECT total(x) - ((1<<62)*2+1) FROM t6
850 }
851 } 0.0
852}
853if {[working_64bit_int]} {
854 do_test func-18.14 {
855 execsql {
856 SELECT sum(-9223372036854775805);
857 }
858 } -9223372036854775805
859}
danielk19774b2688a2006-06-20 11:01:07 +0000860ifcapable compound&&subquery {
861
drh8c08e862006-02-11 17:34:00 +0000862do_test func-18.15 {
863 catchsql {
864 SELECT sum(x) FROM
865 (SELECT 9223372036854775807 AS x UNION ALL
866 SELECT 10 AS x);
867 }
868} {1 {integer overflow}}
shanefbd60f82009-02-04 03:59:25 +0000869if {[working_64bit_int]} {
870 do_test func-18.16 {
871 catchsql {
872 SELECT sum(x) FROM
873 (SELECT 9223372036854775807 AS x UNION ALL
874 SELECT -10 AS x);
875 }
876 } {0 9223372036854775797}
877 do_test func-18.17 {
878 catchsql {
879 SELECT sum(x) FROM
880 (SELECT -9223372036854775807 AS x UNION ALL
881 SELECT 10 AS x);
882 }
883 } {0 -9223372036854775797}
884}
drh8c08e862006-02-11 17:34:00 +0000885do_test func-18.18 {
886 catchsql {
887 SELECT sum(x) FROM
888 (SELECT -9223372036854775807 AS x UNION ALL
889 SELECT -10 AS x);
890 }
891} {1 {integer overflow}}
892do_test func-18.19 {
893 catchsql {
894 SELECT sum(x) FROM (SELECT 9 AS x UNION ALL SELECT -10 AS x);
895 }
896} {0 -1}
897do_test func-18.20 {
898 catchsql {
899 SELECT sum(x) FROM (SELECT -9 AS x UNION ALL SELECT 10 AS x);
900 }
901} {0 1}
902do_test func-18.21 {
903 catchsql {
904 SELECT sum(x) FROM (SELECT -10 AS x UNION ALL SELECT 9 AS x);
905 }
906} {0 -1}
907do_test func-18.22 {
908 catchsql {
909 SELECT sum(x) FROM (SELECT 10 AS x UNION ALL SELECT -9 AS x);
910 }
911} {0 1}
drh76c730c2006-02-09 17:47:42 +0000912
danielk19774b2688a2006-06-20 11:01:07 +0000913} ;# ifcapable compound&&subquery
914
drh52fc8492006-02-23 21:43:55 +0000915# Integer overflow on abs()
916#
shanefbd60f82009-02-04 03:59:25 +0000917if {[working_64bit_int]} {
918 do_test func-18.31 {
919 catchsql {
920 SELECT abs(-9223372036854775807);
921 }
922 } {0 9223372036854775807}
923}
drh52fc8492006-02-23 21:43:55 +0000924do_test func-18.32 {
925 catchsql {
926 SELECT abs(-9223372036854775807-1);
927 }
928} {1 {integer overflow}}
929
drh7f375902006-06-13 17:38:59 +0000930# The MATCH function exists but is only a stub and always throws an error.
931#
932do_test func-19.1 {
933 execsql {
934 SELECT match(a,b) FROM t1 WHERE 0;
935 }
936} {}
937do_test func-19.2 {
938 catchsql {
939 SELECT 'abc' MATCH 'xyz';
940 }
drhb7481e72006-09-16 21:45:14 +0000941} {1 {unable to use function MATCH in the requested context}}
drh7f375902006-06-13 17:38:59 +0000942do_test func-19.3 {
943 catchsql {
944 SELECT 'abc' NOT MATCH 'xyz';
945 }
drhb7481e72006-09-16 21:45:14 +0000946} {1 {unable to use function MATCH in the requested context}}
drh7f375902006-06-13 17:38:59 +0000947do_test func-19.4 {
948 catchsql {
949 SELECT match(1,2,3);
950 }
951} {1 {wrong number of arguments to function match()}}
drh76c730c2006-02-09 17:47:42 +0000952
drhbdf67e02006-08-19 11:34:01 +0000953# Soundex tests.
954#
955if {![catch {db eval {SELECT soundex('hello')}}]} {
956 set i 0
957 foreach {name sdx} {
958 euler E460
959 EULER E460
960 Euler E460
961 ellery E460
962 gauss G200
963 ghosh G200
964 hilbert H416
965 Heilbronn H416
966 knuth K530
967 kant K530
968 Lloyd L300
969 LADD L300
970 Lukasiewicz L222
971 Lissajous L222
972 A A000
973 12345 ?000
974 } {
975 incr i
976 do_test func-20.$i {
977 execsql {SELECT soundex($name)}
978 } $sdx
979 }
980}
981
drh26b6d902007-03-17 13:27:54 +0000982# Tests of the REPLACE function.
983#
984do_test func-21.1 {
985 catchsql {
986 SELECT replace(1,2);
987 }
988} {1 {wrong number of arguments to function replace()}}
989do_test func-21.2 {
990 catchsql {
991 SELECT replace(1,2,3,4);
992 }
993} {1 {wrong number of arguments to function replace()}}
994do_test func-21.3 {
995 execsql {
996 SELECT typeof(replace("This is the main test string", NULL, "ALT"));
997 }
998} {null}
999do_test func-21.4 {
1000 execsql {
1001 SELECT typeof(replace(NULL, "main", "ALT"));
1002 }
1003} {null}
1004do_test func-21.5 {
1005 execsql {
1006 SELECT typeof(replace("This is the main test string", "main", NULL));
1007 }
1008} {null}
1009do_test func-21.6 {
1010 execsql {
1011 SELECT replace("This is the main test string", "main", "ALT");
1012 }
1013} {{This is the ALT test string}}
1014do_test func-21.7 {
1015 execsql {
1016 SELECT replace("This is the main test string", "main", "larger-main");
1017 }
1018} {{This is the larger-main test string}}
1019do_test func-21.8 {
1020 execsql {
1021 SELECT replace("aaaaaaa", "a", "0123456789");
1022 }
1023} {0123456789012345678901234567890123456789012345678901234567890123456789}
1024
danielk19774152e672007-09-12 17:01:45 +00001025ifcapable tclvar {
1026 do_test func-21.9 {
1027 # Attempt to exploit a buffer-overflow that at one time existed
1028 # in the REPLACE function.
1029 set ::str "[string repeat A 29998]CC[string repeat A 35537]"
1030 set ::rep [string repeat B 65536]
1031 execsql {
1032 SELECT LENGTH(REPLACE($::str, 'C', $::rep));
1033 }
1034 } [expr 29998 + 2*65536 + 35537]
1035}
danielk197717374e82007-05-08 14:39:04 +00001036
drh309b3382007-03-17 17:52:42 +00001037# Tests for the TRIM, LTRIM and RTRIM functions.
1038#
1039do_test func-22.1 {
1040 catchsql {SELECT trim(1,2,3)}
1041} {1 {wrong number of arguments to function trim()}}
1042do_test func-22.2 {
1043 catchsql {SELECT ltrim(1,2,3)}
1044} {1 {wrong number of arguments to function ltrim()}}
1045do_test func-22.3 {
1046 catchsql {SELECT rtrim(1,2,3)}
1047} {1 {wrong number of arguments to function rtrim()}}
1048do_test func-22.4 {
1049 execsql {SELECT trim(' hi ');}
1050} {hi}
1051do_test func-22.5 {
1052 execsql {SELECT ltrim(' hi ');}
1053} {{hi }}
1054do_test func-22.6 {
1055 execsql {SELECT rtrim(' hi ');}
1056} {{ hi}}
1057do_test func-22.7 {
1058 execsql {SELECT trim(' hi ','xyz');}
1059} {{ hi }}
1060do_test func-22.8 {
1061 execsql {SELECT ltrim(' hi ','xyz');}
1062} {{ hi }}
1063do_test func-22.9 {
1064 execsql {SELECT rtrim(' hi ','xyz');}
1065} {{ hi }}
1066do_test func-22.10 {
1067 execsql {SELECT trim('xyxzy hi zzzy','xyz');}
1068} {{ hi }}
1069do_test func-22.11 {
1070 execsql {SELECT ltrim('xyxzy hi zzzy','xyz');}
1071} {{ hi zzzy}}
1072do_test func-22.12 {
1073 execsql {SELECT rtrim('xyxzy hi zzzy','xyz');}
1074} {{xyxzy hi }}
1075do_test func-22.13 {
1076 execsql {SELECT trim(' hi ','');}
1077} {{ hi }}
drh4e05c832007-05-11 01:44:50 +00001078if {[db one {PRAGMA encoding}]=="UTF-8"} {
1079 do_test func-22.14 {
1080 execsql {SELECT hex(trim(x'c280e1bfbff48fbfbf6869',x'6162e1bfbfc280'))}
1081 } {F48FBFBF6869}
1082 do_test func-22.15 {
1083 execsql {SELECT hex(trim(x'6869c280e1bfbff48fbfbf61',
1084 x'6162e1bfbfc280f48fbfbf'))}
1085 } {6869}
1086 do_test func-22.16 {
1087 execsql {SELECT hex(trim(x'ceb1ceb2ceb3',x'ceb1'));}
1088 } {CEB2CEB3}
1089}
drh309b3382007-03-17 17:52:42 +00001090do_test func-22.20 {
1091 execsql {SELECT typeof(trim(NULL));}
1092} {null}
1093do_test func-22.21 {
1094 execsql {SELECT typeof(trim(NULL,'xyz'));}
1095} {null}
1096do_test func-22.22 {
1097 execsql {SELECT typeof(trim('hello',NULL));}
1098} {null}
drh26b6d902007-03-17 13:27:54 +00001099
danielk1977fa18bec2007-09-03 11:04:22 +00001100# This is to test the deprecated sqlite3_aggregate_count() API.
1101#
shaneeec556d2008-10-12 00:27:53 +00001102ifcapable deprecated {
1103 do_test func-23.1 {
1104 sqlite3_create_aggregate db
1105 execsql {
1106 SELECT legacy_count() FROM t6;
1107 }
1108 } {3}
1109}
danielk1977fa18bec2007-09-03 11:04:22 +00001110
drhade86482007-11-28 22:36:40 +00001111# The group_concat() function.
1112#
1113do_test func-24.1 {
1114 execsql {
1115 SELECT group_concat(t1) FROM tbl1
1116 }
1117} {this,program,is,free,software}
1118do_test func-24.2 {
1119 execsql {
1120 SELECT group_concat(t1,' ') FROM tbl1
1121 }
1122} {{this program is free software}}
1123do_test func-24.3 {
1124 execsql {
1125 SELECT group_concat(t1,' ' || rowid || ' ') FROM tbl1
1126 }
1127} {{this 2 program 3 is 4 free 5 software}}
1128do_test func-24.4 {
1129 execsql {
1130 SELECT group_concat(NULL,t1) FROM tbl1
1131 }
1132} {{}}
1133do_test func-24.5 {
1134 execsql {
1135 SELECT group_concat(t1,NULL) FROM tbl1
1136 }
1137} {thisprogramisfreesoftware}
drh2dca8682008-03-21 17:13:13 +00001138do_test func-24.6 {
1139 execsql {
1140 SELECT 'BEGIN-'||group_concat(t1) FROM tbl1
1141 }
1142} {BEGIN-this,program,is,free,software}
drh07d31172009-02-02 21:57:05 +00001143
1144# Ticket #3179: Make sure aggregate functions can take many arguments.
1145# None of the built-in aggregates do this, so use the md5sum() from the
1146# test extensions.
1147#
drh3780b5d2008-06-19 18:39:11 +00001148unset -nocomplain midargs
drha2baf3a2008-06-18 15:34:09 +00001149set midargs {}
drh3780b5d2008-06-19 18:39:11 +00001150unset -nocomplain midres
drha2baf3a2008-06-18 15:34:09 +00001151set midres {}
drh3780b5d2008-06-19 18:39:11 +00001152unset -nocomplain result
drh07d31172009-02-02 21:57:05 +00001153for {set i 1} {$i<[sqlite3_limit db SQLITE_LIMIT_FUNCTION_ARG -1]} {incr i} {
drha2baf3a2008-06-18 15:34:09 +00001154 append midargs ,'/$i'
1155 append midres /$i
drh07d31172009-02-02 21:57:05 +00001156 set result [md5 \
1157 "this${midres}program${midres}is${midres}free${midres}software${midres}"]
1158 set sql "SELECT md5sum(t1$midargs) FROM tbl1"
drha2baf3a2008-06-18 15:34:09 +00001159 do_test func-24.7.$i {
1160 db eval $::sql
1161 } $result
1162}
drhade86482007-11-28 22:36:40 +00001163
drh8dc09a02009-04-15 15:16:53 +00001164# Ticket #3806. If the initial string in a group_concat is an empty
drh8bfd7192009-06-19 16:44:41 +00001165# string, the separator that follows should still be present.
drh8dc09a02009-04-15 15:16:53 +00001166#
1167do_test func-24.8 {
1168 execsql {
1169 SELECT group_concat(CASE t1 WHEN 'this' THEN '' ELSE t1 END) FROM tbl1
1170 }
1171} {,program,is,free,software}
1172do_test func-24.9 {
1173 execsql {
1174 SELECT group_concat(CASE WHEN t1!='software' THEN '' ELSE t1 END) FROM tbl1
1175 }
1176} {,,,,software}
1177
drh8bfd7192009-06-19 16:44:41 +00001178# Ticket #3923. Initial empty strings have a separator. But initial
1179# NULLs do not.
1180#
1181do_test func-24.10 {
1182 execsql {
1183 SELECT group_concat(CASE t1 WHEN 'this' THEN null ELSE t1 END) FROM tbl1
1184 }
1185} {program,is,free,software}
1186do_test func-24.11 {
1187 execsql {
1188 SELECT group_concat(CASE WHEN t1!='software' THEN null ELSE t1 END) FROM tbl1
1189 }
1190} {software}
1191do_test func-24.12 {
1192 execsql {
1193 SELECT group_concat(CASE t1 WHEN 'this' THEN ''
1194 WHEN 'program' THEN null ELSE t1 END) FROM tbl1
1195 }
1196} {,is,free,software}
1197
1198
drh191b54c2008-04-15 12:14:21 +00001199# Use the test_isolation function to make sure that type conversions
1200# on function arguments do not effect subsequent arguments.
1201#
1202do_test func-25.1 {
1203 execsql {SELECT test_isolation(t1,t1) FROM tbl1}
1204} {this program is free software}
1205
drh24b58dd2008-07-07 14:50:14 +00001206# Try to misuse the sqlite3_create_function() interface. Verify that
1207# errors are returned.
1208#
1209do_test func-26.1 {
1210 abuse_create_function db
1211} {}
1212
1213# The previous test (func-26.1) registered a function with a very long
1214# function name that takes many arguments and always returns NULL. Verify
1215# that this function works correctly.
1216#
1217do_test func-26.2 {
1218 set a {}
1219 for {set i 1} {$i<=$::SQLITE_MAX_FUNCTION_ARG} {incr i} {
1220 lappend a $i
1221 }
1222 db eval "
1223 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 ,]);
1224 "
1225} {{}}
1226do_test func-26.3 {
1227 set a {}
1228 for {set i 1} {$i<=$::SQLITE_MAX_FUNCTION_ARG+1} {incr i} {
1229 lappend a $i
1230 }
1231 catchsql "
1232 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 ,]);
1233 "
1234} {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}}
1235do_test func-26.4 {
1236 set a {}
1237 for {set i 1} {$i<=$::SQLITE_MAX_FUNCTION_ARG-1} {incr i} {
1238 lappend a $i
1239 }
1240 catchsql "
1241 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 ,]);
1242 "
1243} {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()}}
1244do_test func-26.5 {
1245 catchsql "
1246 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);
1247 "
1248} {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}}
1249do_test func-26.6 {
1250 catchsql "
1251 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);
1252 "
1253} {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}}
1254
drhdfbc3a82009-01-31 22:28:48 +00001255do_test func-27.1 {
1256 catchsql {SELECT coalesce()}
1257} {1 {wrong number of arguments to function coalesce()}}
1258do_test func-27.2 {
1259 catchsql {SELECT coalesce(1)}
1260} {1 {wrong number of arguments to function coalesce()}}
1261do_test func-27.3 {
1262 catchsql {SELECT coalesce(1,2)}
1263} {0 1}
1264
drhfeb306f2009-08-18 16:05:46 +00001265# Ticket 2d401a94287b5
1266# Unknown function in a DEFAULT expression causes a segfault.
1267#
1268do_test func-28.1 {
1269 db eval {
1270 CREATE TABLE t28(x, y DEFAULT(nosuchfunc(1)));
1271 }
1272 catchsql {
1273 INSERT INTO t28(x) VALUES(1);
1274 }
1275} {1 {unknown function: nosuchfunc()}}
1276
drha748fdc2012-03-28 01:34:47 +00001277# Verify that the length() and typeof() functions do not actually load
1278# the content of their argument.
1279#
1280do_test func-29.1 {
1281 db eval {
1282 CREATE TABLE t29(id INTEGER PRIMARY KEY, x, y);
1283 INSERT INTO t29 VALUES(1, 2, 3), (2, NULL, 4), (3, 4.5, 5);
1284 INSERT INTO t29 VALUES(4, randomblob(1000000), 6);
1285 INSERT INTO t29 VALUES(5, "hello", 7);
1286 }
1287 db close
1288 sqlite3 db test.db
1289 sqlite3_db_status db CACHE_MISS 1
1290 db eval {SELECT typeof(x), length(x), typeof(y) FROM t29 ORDER BY id}
1291} {integer 1 integer null {} integer real 3 integer blob 1000000 integer text 5 integer}
1292do_test func-29.2 {
1293 set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
1294 if {$x<5} {set x 1}
1295 set x
1296} {1}
1297do_test func-29.3 {
1298 db close
1299 sqlite3 db test.db
1300 sqlite3_db_status db CACHE_MISS 1
1301 db eval {SELECT typeof(+x) FROM t29 ORDER BY id}
1302} {integer null real blob text}
drh9b4c59f2013-04-15 17:03:42 +00001303if {[permutation] != "mmap"} {
dan5d8a1372013-03-19 19:28:06 +00001304 do_test func-29.4 {
1305 set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
1306 if {$x>100} {set x many}
1307 set x
1308 } {many}
1309}
drh3c888b72012-03-28 02:51:51 +00001310do_test func-29.5 {
1311 db close
1312 sqlite3 db test.db
1313 sqlite3_db_status db CACHE_MISS 1
1314 db eval {SELECT sum(length(x)) FROM t29}
1315} {1000009}
1316do_test func-29.6 {
1317 set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
1318 if {$x<5} {set x 1}
1319 set x
1320} {1}
drhd495d8c2013-02-22 19:34:25 +00001321
drh3432daa2013-10-11 16:35:49 +00001322# EVIDENCE-OF: R-29701-50711 The unicode(X) function returns the numeric
1323# unicode code point corresponding to the first character of the string
1324# X.
1325#
1326# EVIDENCE-OF: R-55469-62130 The char(X1,X2,...,XN) function returns a
1327# string composed of characters having the unicode code point values of
1328# integers X1 through XN, respectively.
1329#
drhd495d8c2013-02-22 19:34:25 +00001330do_execsql_test func-30.1 {SELECT unicode('$');} 36
mistachkin8d0b81d2013-02-26 05:44:33 +00001331do_execsql_test func-30.2 [subst {SELECT unicode('\u00A2');}] 162
1332do_execsql_test func-30.3 [subst {SELECT unicode('\u20AC');}] 8364
1333do_execsql_test func-30.4 {SELECT char(36,162,8364);} [subst {$\u00A2\u20AC}]
drha748fdc2012-03-28 01:34:47 +00001334
drhfbc1ddf2013-02-25 14:39:47 +00001335for {set i 1} {$i<0xd800} {incr i 13} {
1336 do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
1337}
1338for {set i 57344} {$i<=0xfffd} {incr i 17} {
1339 if {$i==0xfeff} continue
1340 do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
1341}
1342for {set i 65536} {$i<=0x10ffff} {incr i 139} {
1343 do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
1344}
drhff6e9112000-08-28 16:21:58 +00001345
1346finish_test