xref: /sqlite-3.40.0/test/func.test (revision 194f8972)
1# 2001 September 15
2#
3# The author disclaims copyright to this source code.  In place of
4# a legal notice, here is a blessing:
5#
6#    May you do good and not evil.
7#    May you find forgiveness for yourself and forgive others.
8#    May you share freely, never taking more than you give.
9#
10#***********************************************************************
11# This file implements regression tests for SQLite library.  The
12# focus of this file is testing built-in functions.
13#
14# $Id: func.test,v 1.59 2007/03/17 17:52:42 drh Exp $
15
16set testdir [file dirname $argv0]
17source $testdir/tester.tcl
18
19# Create a table to work with.
20#
21do_test func-0.0 {
22  execsql {CREATE TABLE tbl1(t1 text)}
23  foreach word {this program is free software} {
24    execsql "INSERT INTO tbl1 VALUES('$word')"
25  }
26  execsql {SELECT t1 FROM tbl1 ORDER BY t1}
27} {free is program software this}
28do_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}
39
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
48} {1 {wrong number of arguments to function length()}}
49do_test func-1.2 {
50  set r [catch {execsql {SELECT length(t1,5) FROM tbl1 ORDER BY t1}} msg]
51  lappend r $msg
52} {1 {wrong number of arguments to function length()}}
53do_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}
57do_test func-1.4 {
58  execsql {SELECT coalesce(length(a),-1) FROM t2}
59} {1 -1 3 -1 5}
60
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}
90do_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}
96
97# Only do the following tests if TCL has UTF-8 capabilities
98#
99if {"\u1234"!="u1234"} {
100
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}
109} "UTF-8 characters contains hi\u1234ho"
110do_test func-3.1 {
111  execsql {SELECT length(t1) FROM tbl1 ORDER BY t1}
112} {5 10 8 5}
113do_test func-3.2 {
114  execsql {SELECT substr(t1,1,2) FROM tbl1 ORDER BY t1}
115} {UT ch co hi}
116do_test func-3.3 {
117  execsql {SELECT substr(t1,1,3) FROM tbl1 ORDER BY t1}
118} "UTF cha con hi\u1234"
119do_test func-3.4 {
120  execsql {SELECT substr(t1,2,2) FROM tbl1 ORDER BY t1}
121} "TF ha on i\u1234"
122do_test func-3.5 {
123  execsql {SELECT substr(t1,2,3) FROM tbl1 ORDER BY t1}
124} "TF- har ont i\u1234h"
125do_test func-3.6 {
126  execsql {SELECT substr(t1,3,2) FROM tbl1 ORDER BY t1}
127} "F- ar nt \u1234h"
128do_test func-3.7 {
129  execsql {SELECT substr(t1,4,2) FROM tbl1 ORDER BY t1}
130} "-8 ra ta ho"
131do_test func-3.8 {
132  execsql {SELECT substr(t1,-1,1) FROM tbl1 ORDER BY t1}
133} "8 s s o"
134do_test func-3.9 {
135  execsql {SELECT substr(t1,-3,2) FROM tbl1 ORDER BY t1}
136} "F- er in \u1234h"
137do_test func-3.10 {
138  execsql {SELECT substr(t1,-4,3) FROM tbl1 ORDER BY t1}
139} "TF- ter ain i\u1234h"
140do_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}
147
148} ;# End \u1234!=u1234
149
150# 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}
160} {1 {wrong number of arguments to function abs()}}
161do_test func-4.2 {
162  catchsql {SELECT abs() FROM t1}
163} {1 {wrong number of arguments to function abs()}}
164do_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}
169} {0 {3 12345.6789 5}}
170do_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}
175} {0.0 0.0 0.0 0.0 0.0}
176
177do_test func-4.5 {
178  catchsql {SELECT round(a,b,c) FROM t1}
179} {1 {wrong number of arguments to function round()}}
180do_test func-4.6 {
181  catchsql {SELECT round(b,2) FROM t1 ORDER BY b}
182} {0 {-2.0 1.23 2.0}}
183do_test func-4.7 {
184  catchsql {SELECT round(b,0) FROM t1 ORDER BY a}
185} {0 {2.0 1.0 -2.0}}
186do_test func-4.8 {
187  catchsql {SELECT round(c) FROM t1 ORDER BY a}
188} {0 {3.0 -12346.0 -5.0}}
189do_test func-4.9 {
190  catchsql {SELECT round(c,a) FROM t1 ORDER BY a}
191} {0 {3.0 -12345.68 -5.0}}
192do_test func-4.10 {
193  catchsql {SELECT 'x' || round(c,a) || 'y' FROM t1 ORDER BY a}
194} {0 {x3.0y x-12345.68y x-5.0y}}
195do_test func-4.11 {
196  catchsql {SELECT round() FROM t1 ORDER BY a}
197} {1 {wrong number of arguments to function round()}}
198do_test func-4.12 {
199  execsql {SELECT coalesce(round(a,2),'nil') FROM t2}
200} {1.0 nil 345.0 nil 67890.0}
201do_test func-4.13 {
202  execsql {SELECT round(t1,2) FROM tbl1}
203} {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
211
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}
223do_test func-5.4 {
224  catchsql {SELECT upper(a,5) FROM t2}
225} {1 {wrong number of arguments to function upper()}}
226do_test func-5.5 {
227  catchsql {SELECT upper(*) FROM t2}
228} {1 {wrong number of arguments to function upper()}}
229
230# Test the coalesce() and nullif() functions
231#
232do_test func-6.1 {
233  execsql {SELECT coalesce(a,'xyz') FROM t2}
234} {1 xyz 345 xyz 67890}
235do_test func-6.2 {
236  execsql {SELECT coalesce(upper(a),'nil') FROM t2}
237} {1 nil 345 nil 67890}
238do_test func-6.3 {
239  execsql {SELECT coalesce(nullif(1,1),'nil')}
240} {nil}
241do_test func-6.4 {
242  execsql {SELECT coalesce(nullif(1,2),'nil')}
243} {1}
244do_test func-6.5 {
245  execsql {SELECT coalesce(nullif(1,NULL),'nil')}
246} {1}
247
248
249# Test the last_insert_rowid() function
250#
251do_test func-7.1 {
252  execsql {SELECT last_insert_rowid()}
253} [db last_insert_rowid]
254
255# Tests for aggregate functions and how they handle NULLs.
256#
257do_test func-8.1 {
258  ifcapable explain {
259    execsql {EXPLAIN SELECT sum(a) FROM t2;}
260  }
261  execsql {
262    SELECT sum(a), count(a), round(avg(a),2), min(a), max(a), count(*) FROM t2;
263  }
264} {68236 3 22745.33 1 67890 5}
265do_test func-8.2 {
266  execsql {
267    SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t2;
268  }
269} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
270
271ifcapable tempdb {
272  do_test func-8.3 {
273    execsql {
274      CREATE TEMP TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
275      SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
276    }
277  } {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
278} else {
279  do_test func-8.3 {
280    execsql {
281      CREATE TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
282      SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
283    }
284  } {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
285}
286do_test func-8.4 {
287  execsql {
288    SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
289  }
290} {z+67890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
291
292# How do you test the random() function in a meaningful, deterministic way?
293#
294do_test func-9.1 {
295  execsql {
296    SELECT random() is not null;
297  }
298} {1}
299do_test func-9.2 {
300  execsql {
301    SELECT typeof(random());
302  }
303} {integer}
304do_test func-9.3 {
305  execsql {
306    SELECT randomblob(32) is not null;
307  }
308} {1}
309do_test func-9.4 {
310  execsql {
311    SELECT typeof(randomblob(32));
312  }
313} {blob}
314do_test func-9.5 {
315  execsql {
316    SELECT length(randomblob(32)), length(randomblob(-5)),
317           length(randomblob(2000))
318  }
319} {32 1 2000}
320
321# The "hex()" function was added in order to be able to render blobs
322# generated by randomblob().  So this seems like a good place to test
323# hex().
324#
325do_test func-9.10 {
326  execsql {SELECT hex(x'00112233445566778899aAbBcCdDeEfF')}
327} {00112233445566778899AABBCCDDEEFF}
328
329# Use the "sqlite_register_test_function" TCL command which is part of
330# the text fixture in order to verify correct operation of some of
331# the user-defined SQL function APIs that are not used by the built-in
332# functions.
333#
334set ::DB [sqlite3_connection_pointer db]
335sqlite_register_test_function $::DB testfunc
336do_test func-10.1 {
337  catchsql {
338    SELECT testfunc(NULL,NULL);
339  }
340} {1 {first argument should be one of: int int64 string double null value}}
341do_test func-10.2 {
342  execsql {
343    SELECT testfunc(
344     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
345     'int', 1234
346    );
347  }
348} {1234}
349do_test func-10.3 {
350  execsql {
351    SELECT testfunc(
352     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
353     'string', NULL
354    );
355  }
356} {{}}
357do_test func-10.4 {
358  execsql {
359    SELECT testfunc(
360     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
361     'double', 1.234
362    );
363  }
364} {1.234}
365do_test func-10.5 {
366  execsql {
367    SELECT testfunc(
368     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
369     'int', 1234,
370     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
371     'string', NULL,
372     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
373     'double', 1.234,
374     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
375     'int', 1234,
376     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
377     'string', NULL,
378     'string', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
379     'double', 1.234
380    );
381  }
382} {1.234}
383
384# Test the built-in sqlite_version(*) SQL function.
385#
386do_test func-11.1 {
387  execsql {
388    SELECT sqlite_version(*);
389  }
390} [sqlite3 -version]
391
392# Test that destructors passed to sqlite3 by calls to sqlite3_result_text()
393# etc. are called. These tests use two special user-defined functions
394# (implemented in func.c) only available in test builds.
395#
396# Function test_destructor() takes one argument and returns a copy of the
397# text form of that argument. A destructor is associated with the return
398# value. Function test_destructor_count() returns the number of outstanding
399# destructor calls for values returned by test_destructor().
400#
401do_test func-12.1 {
402  execsql {
403    SELECT test_destructor('hello world'), test_destructor_count();
404  }
405} {{hello world} 1}
406do_test func-12.2 {
407  execsql {
408    SELECT test_destructor_count();
409  }
410} {0}
411do_test func-12.3 {
412  execsql {
413    SELECT test_destructor('hello')||' world', test_destructor_count();
414  }
415} {{hello world} 0}
416do_test func-12.4 {
417  execsql {
418    SELECT test_destructor_count();
419  }
420} {0}
421do_test func-12.5 {
422  execsql {
423    CREATE TABLE t4(x);
424    INSERT INTO t4 VALUES(test_destructor('hello'));
425    INSERT INTO t4 VALUES(test_destructor('world'));
426    SELECT min(test_destructor(x)), max(test_destructor(x)) FROM t4;
427  }
428} {hello world}
429do_test func-12.6 {
430  execsql {
431    SELECT test_destructor_count();
432  }
433} {0}
434do_test func-12.7 {
435  execsql {
436    DROP TABLE t4;
437  }
438} {}
439
440# Test that the auxdata API for scalar functions works. This test uses
441# a special user-defined function only available in test builds,
442# test_auxdata(). Function test_auxdata() takes any number of arguments.
443do_test func-13.1 {
444  execsql {
445    SELECT test_auxdata('hello world');
446  }
447} {0}
448
449do_test func-13.2 {
450  execsql {
451    CREATE TABLE t4(a, b);
452    INSERT INTO t4 VALUES('abc', 'def');
453    INSERT INTO t4 VALUES('ghi', 'jkl');
454  }
455} {}
456do_test func-13.3 {
457  execsql {
458    SELECT test_auxdata('hello world') FROM t4;
459  }
460} {0 1}
461do_test func-13.4 {
462  execsql {
463    SELECT test_auxdata('hello world', 123) FROM t4;
464  }
465} {{0 0} {1 1}}
466do_test func-13.5 {
467  execsql {
468    SELECT test_auxdata('hello world', a) FROM t4;
469  }
470} {{0 0} {1 0}}
471do_test func-13.6 {
472  execsql {
473    SELECT test_auxdata('hello'||'world', a) FROM t4;
474  }
475} {{0 0} {1 0}}
476
477# Test that auxilary data is preserved between calls for SQL variables.
478do_test func-13.7 {
479  set DB [sqlite3_connection_pointer db]
480  set sql "SELECT test_auxdata( ? , a ) FROM t4;"
481  set STMT [sqlite3_prepare $DB $sql -1 TAIL]
482  sqlite3_bind_text $STMT 1 hello -1
483  set res [list]
484  while { "SQLITE_ROW"==[sqlite3_step $STMT] } {
485    lappend res [sqlite3_column_text $STMT 0]
486  }
487  lappend res [sqlite3_finalize $STMT]
488} {{0 0} {1 0} SQLITE_OK}
489
490# Make sure that a function with a very long name is rejected
491do_test func-14.1 {
492  catch {
493    db function [string repeat X 254] {return "hello"}
494  }
495} {0}
496do_test func-14.2 {
497  catch {
498    db function [string repeat X 256] {return "hello"}
499  }
500} {1}
501
502do_test func-15.1 {
503  catchsql {
504    select test_error(NULL);
505  }
506} {1 {}}
507
508# Test the quote function for BLOB and NULL values.
509do_test func-16.1 {
510  execsql {
511    CREATE TABLE tbl2(a, b);
512  }
513  set STMT [sqlite3_prepare $::DB "INSERT INTO tbl2 VALUES(?, ?)" -1 TAIL]
514  sqlite3_bind_blob $::STMT 1 abc 3
515  sqlite3_step $::STMT
516  sqlite3_finalize $::STMT
517  execsql {
518    SELECT quote(a), quote(b) FROM tbl2;
519  }
520} {X'616263' NULL}
521
522# Correctly handle function error messages that include %.  Ticket #1354
523#
524do_test func-17.1 {
525  proc testfunc1 args {error "Error %d with %s percents %p"}
526  db function testfunc1 ::testfunc1
527  catchsql {
528    SELECT testfunc1(1,2,3);
529  }
530} {1 {Error %d with %s percents %p}}
531
532# The SUM function should return integer results when all inputs are integer.
533#
534do_test func-18.1 {
535  execsql {
536    CREATE TABLE t5(x);
537    INSERT INTO t5 VALUES(1);
538    INSERT INTO t5 VALUES(-99);
539    INSERT INTO t5 VALUES(10000);
540    SELECT sum(x) FROM t5;
541  }
542} {9902}
543do_test func-18.2 {
544  execsql {
545    INSERT INTO t5 VALUES(0.0);
546    SELECT sum(x) FROM t5;
547  }
548} {9902.0}
549
550# The sum of nothing is NULL.  But the sum of all NULLs is NULL.
551#
552# The TOTAL of nothing is 0.0.
553#
554do_test func-18.3 {
555  execsql {
556    DELETE FROM t5;
557    SELECT sum(x), total(x) FROM t5;
558  }
559} {{} 0.0}
560do_test func-18.4 {
561  execsql {
562    INSERT INTO t5 VALUES(NULL);
563    SELECT sum(x), total(x) FROM t5
564  }
565} {{} 0.0}
566do_test func-18.5 {
567  execsql {
568    INSERT INTO t5 VALUES(NULL);
569    SELECT sum(x), total(x) FROM t5
570  }
571} {{} 0.0}
572do_test func-18.6 {
573  execsql {
574    INSERT INTO t5 VALUES(123);
575    SELECT sum(x), total(x) FROM t5
576  }
577} {123 123.0}
578
579# Ticket #1664, #1669, #1670, #1674: An integer overflow on SUM causes
580# an error. The non-standard TOTAL() function continues to give a helpful
581# result.
582#
583do_test func-18.10 {
584  execsql {
585    CREATE TABLE t6(x INTEGER);
586    INSERT INTO t6 VALUES(1);
587    INSERT INTO t6 VALUES(1<<62);
588    SELECT sum(x) - ((1<<62)+1) from t6;
589  }
590} 0
591do_test func-18.11 {
592  execsql {
593    SELECT typeof(sum(x)) FROM t6
594  }
595} integer
596do_test func-18.12 {
597  catchsql {
598    INSERT INTO t6 VALUES(1<<62);
599    SELECT sum(x) - ((1<<62)*2.0+1) from t6;
600  }
601} {1 {integer overflow}}
602do_test func-18.13 {
603  execsql {
604    SELECT total(x) - ((1<<62)*2.0+1) FROM t6
605  }
606} 0.0
607do_test func-18.14 {
608  execsql {
609    SELECT sum(-9223372036854775805);
610  }
611} -9223372036854775805
612
613ifcapable compound&&subquery {
614
615do_test func-18.15 {
616  catchsql {
617    SELECT sum(x) FROM
618       (SELECT 9223372036854775807 AS x UNION ALL
619        SELECT 10 AS x);
620  }
621} {1 {integer overflow}}
622do_test func-18.16 {
623  catchsql {
624    SELECT sum(x) FROM
625       (SELECT 9223372036854775807 AS x UNION ALL
626        SELECT -10 AS x);
627  }
628} {0 9223372036854775797}
629do_test func-18.17 {
630  catchsql {
631    SELECT sum(x) FROM
632       (SELECT -9223372036854775807 AS x UNION ALL
633        SELECT 10 AS x);
634  }
635} {0 -9223372036854775797}
636do_test func-18.18 {
637  catchsql {
638    SELECT sum(x) FROM
639       (SELECT -9223372036854775807 AS x UNION ALL
640        SELECT -10 AS x);
641  }
642} {1 {integer overflow}}
643do_test func-18.19 {
644  catchsql {
645    SELECT sum(x) FROM (SELECT 9 AS x UNION ALL SELECT -10 AS x);
646  }
647} {0 -1}
648do_test func-18.20 {
649  catchsql {
650    SELECT sum(x) FROM (SELECT -9 AS x UNION ALL SELECT 10 AS x);
651  }
652} {0 1}
653do_test func-18.21 {
654  catchsql {
655    SELECT sum(x) FROM (SELECT -10 AS x UNION ALL SELECT 9 AS x);
656  }
657} {0 -1}
658do_test func-18.22 {
659  catchsql {
660    SELECT sum(x) FROM (SELECT 10 AS x UNION ALL SELECT -9 AS x);
661  }
662} {0 1}
663
664} ;# ifcapable compound&&subquery
665
666# Integer overflow on abs()
667#
668do_test func-18.31 {
669  catchsql {
670    SELECT abs(-9223372036854775807);
671  }
672} {0 9223372036854775807}
673do_test func-18.32 {
674  catchsql {
675    SELECT abs(-9223372036854775807-1);
676  }
677} {1 {integer overflow}}
678
679# The MATCH function exists but is only a stub and always throws an error.
680#
681do_test func-19.1 {
682  execsql {
683    SELECT match(a,b) FROM t1 WHERE 0;
684  }
685} {}
686do_test func-19.2 {
687  catchsql {
688    SELECT 'abc' MATCH 'xyz';
689  }
690} {1 {unable to use function MATCH in the requested context}}
691do_test func-19.3 {
692  catchsql {
693    SELECT 'abc' NOT MATCH 'xyz';
694  }
695} {1 {unable to use function MATCH in the requested context}}
696do_test func-19.4 {
697  catchsql {
698    SELECT match(1,2,3);
699  }
700} {1 {wrong number of arguments to function match()}}
701
702# Soundex tests.
703#
704if {![catch {db eval {SELECT soundex('hello')}}]} {
705  set i 0
706  foreach {name sdx} {
707    euler        E460
708    EULER        E460
709    Euler        E460
710    ellery       E460
711    gauss        G200
712    ghosh        G200
713    hilbert      H416
714    Heilbronn    H416
715    knuth        K530
716    kant         K530
717    Lloyd        L300
718    LADD         L300
719    Lukasiewicz  L222
720    Lissajous    L222
721    A            A000
722    12345        ?000
723  } {
724    incr i
725    do_test func-20.$i {
726      execsql {SELECT soundex($name)}
727    } $sdx
728  }
729}
730
731# Tests of the REPLACE function.
732#
733do_test func-21.1 {
734  catchsql {
735    SELECT replace(1,2);
736  }
737} {1 {wrong number of arguments to function replace()}}
738do_test func-21.2 {
739  catchsql {
740    SELECT replace(1,2,3,4);
741  }
742} {1 {wrong number of arguments to function replace()}}
743do_test func-21.3 {
744  execsql {
745    SELECT typeof(replace("This is the main test string", NULL, "ALT"));
746  }
747} {null}
748do_test func-21.4 {
749  execsql {
750    SELECT typeof(replace(NULL, "main", "ALT"));
751  }
752} {null}
753do_test func-21.5 {
754  execsql {
755    SELECT typeof(replace("This is the main test string", "main", NULL));
756  }
757} {null}
758do_test func-21.6 {
759  execsql {
760    SELECT replace("This is the main test string", "main", "ALT");
761  }
762} {{This is the ALT test string}}
763do_test func-21.7 {
764  execsql {
765    SELECT replace("This is the main test string", "main", "larger-main");
766  }
767} {{This is the larger-main test string}}
768do_test func-21.8 {
769  execsql {
770    SELECT replace("aaaaaaa", "a", "0123456789");
771  }
772} {0123456789012345678901234567890123456789012345678901234567890123456789}
773
774# Tests for the TRIM, LTRIM and RTRIM functions.
775#
776do_test func-22.1 {
777  catchsql {SELECT trim(1,2,3)}
778} {1 {wrong number of arguments to function trim()}}
779do_test func-22.2 {
780  catchsql {SELECT ltrim(1,2,3)}
781} {1 {wrong number of arguments to function ltrim()}}
782do_test func-22.3 {
783  catchsql {SELECT rtrim(1,2,3)}
784} {1 {wrong number of arguments to function rtrim()}}
785do_test func-22.4 {
786  execsql {SELECT trim('  hi  ');}
787} {hi}
788do_test func-22.5 {
789  execsql {SELECT ltrim('  hi  ');}
790} {{hi  }}
791do_test func-22.6 {
792  execsql {SELECT rtrim('  hi  ');}
793} {{  hi}}
794do_test func-22.7 {
795  execsql {SELECT trim('  hi  ','xyz');}
796} {{  hi  }}
797do_test func-22.8 {
798  execsql {SELECT ltrim('  hi  ','xyz');}
799} {{  hi  }}
800do_test func-22.9 {
801  execsql {SELECT rtrim('  hi  ','xyz');}
802} {{  hi  }}
803do_test func-22.10 {
804  execsql {SELECT trim('xyxzy  hi  zzzy','xyz');}
805} {{  hi  }}
806do_test func-22.11 {
807  execsql {SELECT ltrim('xyxzy  hi  zzzy','xyz');}
808} {{  hi  zzzy}}
809do_test func-22.12 {
810  execsql {SELECT rtrim('xyxzy  hi  zzzy','xyz');}
811} {{xyxzy  hi  }}
812do_test func-22.13 {
813  execsql {SELECT trim('  hi  ','');}
814} {{  hi  }}
815do_test func-22.20 {
816  execsql {SELECT typeof(trim(NULL));}
817} {null}
818do_test func-22.21 {
819  execsql {SELECT typeof(trim(NULL,'xyz'));}
820} {null}
821do_test func-22.22 {
822  execsql {SELECT typeof(trim('hello',NULL));}
823} {null}
824
825finish_test
826