blob: 92425aeffb7468483783f58d70078adb41b0b424 [file] [log] [blame]
drhb19a2bc2001-09-16 00:13:26 +00001# 2001 September 15
drh960e8c62001-04-03 16:53:21 +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:
drh960e8c62001-04-03 16:53:21 +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.
drh960e8c62001-04-03 16:53:21 +00009#
10#***********************************************************************
11# This file implements regression tests for TCL interface to the
12# SQLite library.
13#
14# Actually, all tests are based on the TCL interface, so the main
15# interface is pretty well tested. This file contains some addition
16# tests for fringe issues that the main test suite does not cover.
17#
danielk1977404ca072009-03-16 13:19:36 +000018# $Id: tclsqlite.test,v 1.73 2009/03/16 13:19:36 danielk1977 Exp $
drh960e8c62001-04-03 16:53:21 +000019
drhc6727c82018-09-19 15:08:21 +000020catch {sqlite3}
21
drh960e8c62001-04-03 16:53:21 +000022set testdir [file dirname $argv0]
23source $testdir/tester.tcl
dan89d24932019-02-27 16:38:19 +000024set testprefix tcl
drh960e8c62001-04-03 16:53:21 +000025
26# Check the error messages generated by tclsqlite
27#
drh4dcac402018-01-03 13:20:02 +000028set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
drhef4ac8f2004-06-19 00:16:31 +000029if {[sqlite3 -has-codec]} {
drh7da56b42016-03-14 18:34:42 +000030 append r " ?-key CODECKEY?"
drh22fbcb82004-02-01 01:22:50 +000031}
drh960e8c62001-04-03 16:53:21 +000032do_test tcl-1.1 {
drh4dcac402018-01-03 13:20:02 +000033 set v [catch {sqlite3 -bogus} msg]
drhdf81a252008-08-25 19:09:01 +000034 regsub {really_sqlite3} $msg {sqlite3} msg
drh960e8c62001-04-03 16:53:21 +000035 lappend v $msg
drh22fbcb82004-02-01 01:22:50 +000036} [list 1 "wrong # args: should be \"$r\""]
drhc6727c82018-09-19 15:08:21 +000037do_test tcl-1.1.1 {
38 set v [catch {sqlite3} msg]
39 regsub {really_sqlite3} $msg {sqlite3} msg
40 lappend v $msg
41} [list 1 "wrong # args: should be \"$r\""]
drh960e8c62001-04-03 16:53:21 +000042do_test tcl-1.2 {
43 set v [catch {db bogus} msg]
44 lappend v $msg
drh11d88e62019-08-15 21:27:20 +000045} {1 {bad option "bogus": must be authorizer, backup, bind_fallback, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, config, copy, deserialize, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, serialize, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}}
danielk1977191fadc2007-10-23 08:17:48 +000046do_test tcl-1.2.1 {
47 set v [catch {db cache bogus} msg]
48 lappend v $msg
49} {1 {bad option "bogus": must be flush or size}}
50do_test tcl-1.2.2 {
51 set v [catch {db cache} msg]
52 lappend v $msg
53} {1 {wrong # args: should be "db cache option ?arg?"}}
drh960e8c62001-04-03 16:53:21 +000054do_test tcl-1.3 {
55 execsql {CREATE TABLE t1(a int, b int)}
56 execsql {INSERT INTO t1 VALUES(10,20)}
57 set v [catch {
58 db eval {SELECT * FROM t1} data {
59 error "The error message"
60 }
61 } msg]
62 lappend v $msg
63} {1 {The error message}}
64do_test tcl-1.4 {
65 set v [catch {
66 db eval {SELECT * FROM t2} data {
67 error "The error message"
68 }
69 } msg]
70 lappend v $msg
71} {1 {no such table: t2}}
72do_test tcl-1.5 {
73 set v [catch {
74 db eval {SELECT * FROM t1} data {
75 break
76 }
77 } msg]
78 lappend v $msg
79} {0 {}}
drhd65e5302008-04-28 13:02:57 +000080catch {expr x*} msg
drh960e8c62001-04-03 16:53:21 +000081do_test tcl-1.6 {
82 set v [catch {
83 db eval {SELECT * FROM t1} data {
84 expr x*
85 }
86 } msg]
87 lappend v $msg
drhd65e5302008-04-28 13:02:57 +000088} [list 1 $msg]
drh0f14e2e2004-06-29 12:39:08 +000089do_test tcl-1.7 {
90 set v [catch {db} msg]
91 lappend v $msg
92} {1 {wrong # args: should be "db SUBCOMMAND ..."}}
drh1211de32004-07-26 12:24:22 +000093if {[catch {db auth {}}]==0} {
94 do_test tcl-1.8 {
95 set v [catch {db authorizer 1 2 3} msg]
96 lappend v $msg
97 } {1 {wrong # args: should be "db authorizer ?CALLBACK?"}}
98}
drh0f14e2e2004-06-29 12:39:08 +000099do_test tcl-1.9 {
100 set v [catch {db busy 1 2 3} msg]
101 lappend v $msg
102} {1 {wrong # args: should be "db busy CALLBACK"}}
103do_test tcl-1.10 {
104 set v [catch {db progress 1} msg]
105 lappend v $msg
106} {1 {wrong # args: should be "db progress N CALLBACK"}}
107do_test tcl-1.11 {
108 set v [catch {db changes xyz} msg]
109 lappend v $msg
110} {1 {wrong # args: should be "db changes "}}
111do_test tcl-1.12 {
112 set v [catch {db commit_hook a b c} msg]
113 lappend v $msg
114} {1 {wrong # args: should be "db commit_hook ?CALLBACK?"}}
drhccae6022005-02-26 17:31:26 +0000115ifcapable {complete} {
116 do_test tcl-1.13 {
117 set v [catch {db complete} msg]
118 lappend v $msg
119 } {1 {wrong # args: should be "db complete SQL"}}
120}
drh0f14e2e2004-06-29 12:39:08 +0000121do_test tcl-1.14 {
122 set v [catch {db eval} msg]
123 lappend v $msg
drhaf38cdb2017-06-26 21:08:32 +0000124} {1 {wrong # args: should be "db eval ?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?"}}
drh0f14e2e2004-06-29 12:39:08 +0000125do_test tcl-1.15 {
126 set v [catch {db function} msg]
127 lappend v $msg
dan3df30592015-03-13 08:31:54 +0000128} {1 {wrong # args: should be "db function NAME ?SWITCHES? SCRIPT"}}
danielk19777ddad962005-12-12 06:53:03 +0000129do_test tcl-1.16 {
drh0f14e2e2004-06-29 12:39:08 +0000130 set v [catch {db last_insert_rowid xyz} msg]
131 lappend v $msg
132} {1 {wrong # args: should be "db last_insert_rowid "}}
danielk19777ddad962005-12-12 06:53:03 +0000133do_test tcl-1.17 {
drh0f14e2e2004-06-29 12:39:08 +0000134 set v [catch {db rekey} msg]
135 lappend v $msg
136} {1 {wrong # args: should be "db rekey KEY"}}
danielk19777ddad962005-12-12 06:53:03 +0000137do_test tcl-1.18 {
drh0f14e2e2004-06-29 12:39:08 +0000138 set v [catch {db timeout} msg]
139 lappend v $msg
140} {1 {wrong # args: should be "db timeout MILLISECONDS"}}
danielk19777ddad962005-12-12 06:53:03 +0000141do_test tcl-1.19 {
drh0f14e2e2004-06-29 12:39:08 +0000142 set v [catch {db collate} msg]
143 lappend v $msg
144} {1 {wrong # args: should be "db collate NAME SCRIPT"}}
danielk19777ddad962005-12-12 06:53:03 +0000145do_test tcl-1.20 {
drh0f14e2e2004-06-29 12:39:08 +0000146 set v [catch {db collation_needed} msg]
147 lappend v $msg
148} {1 {wrong # args: should be "db collation_needed SCRIPT"}}
danielk19777ddad962005-12-12 06:53:03 +0000149do_test tcl-1.21 {
drh0f14e2e2004-06-29 12:39:08 +0000150 set v [catch {db total_changes xyz} msg]
151 lappend v $msg
152} {1 {wrong # args: should be "db total_changes "}}
mistachkin1c9ee262012-09-10 23:44:12 +0000153do_test tcl-1.22 {
tpoindex1067fe12004-12-17 15:41:11 +0000154 set v [catch {db copy} msg]
155 lappend v $msg
156} {1 {wrong # args: should be "db copy CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?"}}
mistachkin1c9ee262012-09-10 23:44:12 +0000157do_test tcl-1.23 {
danielk197795c8a542007-09-01 06:51:27 +0000158 set v [catch {sqlite3 db2 test.db -vfs nosuchvfs} msg]
159 lappend v $msg
160} {1 {no such vfs: nosuchvfs}}
drh960e8c62001-04-03 16:53:21 +0000161
drh3570ad92007-08-31 14:31:44 +0000162catch {unset ::result}
163do_test tcl-2.1 {
164 execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)"
165} {}
166ifcapable schema_pragmas {
167 do_test tcl-2.2 {
168 execsql "PRAGMA table_info(t\u0123x)"
169 } "0 a int 0 {} 0 1 b\u1235 float 0 {} 0"
drh6d4abfb2001-10-22 02:58:08 +0000170}
drh3570ad92007-08-31 14:31:44 +0000171do_test tcl-2.3 {
172 execsql "INSERT INTO t\u0123x VALUES(1,2.3)"
173 db eval "SELECT * FROM t\u0123x" result break
174 set result(*)
175} "a b\u1235"
drh6d4abfb2001-10-22 02:58:08 +0000176
drh6d4abfb2001-10-22 02:58:08 +0000177
drh5d9d7572003-08-19 14:31:01 +0000178# Test the onecolumn method
179#
180do_test tcl-3.1 {
181 execsql {
182 INSERT INTO t1 SELECT a*2, b*2 FROM t1;
183 INSERT INTO t1 SELECT a*2+1, b*2+1 FROM t1;
184 INSERT INTO t1 SELECT a*2+3, b*2+3 FROM t1;
185 }
drh22fbcb82004-02-01 01:22:50 +0000186 set rc [catch {db onecolumn {SELECT * FROM t1 ORDER BY a}} msg]
187 lappend rc $msg
188} {0 10}
drh5d9d7572003-08-19 14:31:01 +0000189do_test tcl-3.2 {
190 db onecolumn {SELECT * FROM t1 WHERE a<0}
191} {}
192do_test tcl-3.3 {
193 set rc [catch {db onecolumn} errmsg]
194 lappend rc $errmsg
195} {1 {wrong # args: should be "db onecolumn SQL"}}
drh0f14e2e2004-06-29 12:39:08 +0000196do_test tcl-3.4 {
197 set rc [catch {db onecolumn {SELECT bogus}} errmsg]
198 lappend rc $errmsg
199} {1 {no such column: bogus}}
drh6bf89572004-11-03 16:27:01 +0000200ifcapable {tclvar} {
201 do_test tcl-3.5 {
202 set b 50
203 set rc [catch {db one {SELECT * FROM t1 WHERE b>$b}} msg]
204 lappend rc $msg
205 } {0 41}
206 do_test tcl-3.6 {
207 set b 500
208 set rc [catch {db one {SELECT * FROM t1 WHERE b>$b}} msg]
209 lappend rc $msg
210 } {0 {}}
211 do_test tcl-3.7 {
212 set b 500
213 set rc [catch {db one {
214 INSERT INTO t1 VALUES(99,510);
215 SELECT * FROM t1 WHERE b>$b
216 }} msg]
217 lappend rc $msg
218 } {0 99}
219}
220ifcapable {!tclvar} {
221 execsql {INSERT INTO t1 VALUES(99,510)}
222}
drh5d9d7572003-08-19 14:31:01 +0000223
drh0f14e2e2004-06-29 12:39:08 +0000224# Turn the busy handler on and off
225#
226do_test tcl-4.1 {
227 proc busy_callback {cnt} {
228 break
229 }
230 db busy busy_callback
231 db busy
232} {busy_callback}
233do_test tcl-4.2 {
234 db busy {}
235 db busy
236} {}
drh6d4abfb2001-10-22 02:58:08 +0000237
drh6bf89572004-11-03 16:27:01 +0000238ifcapable {tclvar} {
239 # Parsing of TCL variable names within SQL into bound parameters.
240 #
241 do_test tcl-5.1 {
242 execsql {CREATE TABLE t3(a,b,c)}
243 catch {unset x}
danielk19777a1d17f2008-08-29 15:54:56 +0000244 set x(1) A
245 set x(2) B
drh6bf89572004-11-03 16:27:01 +0000246 execsql {
247 INSERT INTO t3 VALUES($::x(1),$::x(2),$::x(3));
248 SELECT * FROM t3
249 }
danielk19777a1d17f2008-08-29 15:54:56 +0000250 } {A B {}}
drh6bf89572004-11-03 16:27:01 +0000251 do_test tcl-5.2 {
252 execsql {
253 SELECT typeof(a), typeof(b), typeof(c) FROM t3
254 }
255 } {text text null}
256 do_test tcl-5.3 {
257 catch {unset x}
258 set x [binary format h12 686900686f00]
259 execsql {
260 UPDATE t3 SET a=$::x;
261 }
262 db eval {
263 SELECT a FROM t3
264 } break
265 binary scan $a h12 adata
266 set adata
267 } {686900686f00}
268 do_test tcl-5.4 {
269 execsql {
270 SELECT typeof(a), typeof(b), typeof(c) FROM t3
271 }
272 } {blob text null}
273}
drh92febd92004-08-20 18:34:20 +0000274
drhfd241b02004-09-13 13:46:01 +0000275# Operation of "break" and "continue" within row scripts
276#
277do_test tcl-6.1 {
278 db eval {SELECT * FROM t1} {
279 break
280 }
281 lappend a $b
282} {10 20}
283do_test tcl-6.2 {
284 set cnt 0
285 db eval {SELECT * FROM t1} {
286 if {$a>40} continue
287 incr cnt
288 }
289 set cnt
290} {4}
291do_test tcl-6.3 {
292 set cnt 0
293 db eval {SELECT * FROM t1} {
294 if {$a<40} continue
295 incr cnt
296 }
297 set cnt
298} {5}
299do_test tcl-6.4 {
300 proc return_test {x} {
301 db eval {SELECT * FROM t1} {
302 if {$a==$x} {return $b}
303 }
304 }
305 return_test 10
306} 20
307do_test tcl-6.5 {
308 return_test 20
309} 40
310do_test tcl-6.6 {
311 return_test 99
312} 510
313do_test tcl-6.7 {
314 return_test 0
315} {}
316
danielk19774397de52005-01-12 12:44:03 +0000317do_test tcl-7.1 {
318 db version
319 expr 0
320} {0}
321
danielk197755c45f22005-04-03 23:54:43 +0000322# modify and reset the NULL representation
323#
324do_test tcl-8.1 {
325 db nullvalue NaN
326 execsql {INSERT INTO t1 VALUES(30,NULL)}
327 db eval {SELECT * FROM t1 WHERE b IS NULL}
328} {30 NaN}
drhc45e6712012-10-03 11:02:33 +0000329proc concatFunc args {return [join $args {}]}
danielk197755c45f22005-04-03 23:54:43 +0000330do_test tcl-8.2 {
drhc45e6712012-10-03 11:02:33 +0000331 db function concat concatFunc
332 db eval {SELECT concat('a', b, 'z') FROM t1 WHERE b is NULL}
333} {aNaNz}
334do_test tcl-8.3 {
danielk197755c45f22005-04-03 23:54:43 +0000335 db nullvalue NULL
336 db nullvalue
337} {NULL}
drhc45e6712012-10-03 11:02:33 +0000338do_test tcl-8.4 {
danielk197755c45f22005-04-03 23:54:43 +0000339 db nullvalue {}
340 db eval {SELECT * FROM t1 WHERE b IS NULL}
341} {30 {}}
drhc45e6712012-10-03 11:02:33 +0000342do_test tcl-8.5 {
343 db function concat concatFunc
344 db eval {SELECT concat('a', b, 'z') FROM t1 WHERE b is NULL}
345} {az}
danielk197755c45f22005-04-03 23:54:43 +0000346
drhc7f269d2005-05-05 10:30:29 +0000347# Test the return type of user-defined functions
348#
349do_test tcl-9.1 {
350 db function ret_str {return "hi"}
351 execsql {SELECT typeof(ret_str())}
352} {text}
353do_test tcl-9.2 {
drh9645d8d2006-09-01 15:49:05 +0000354 db function ret_dbl {return [expr {rand()*0.5}]}
drhc7f269d2005-05-05 10:30:29 +0000355 execsql {SELECT typeof(ret_dbl())}
356} {real}
357do_test tcl-9.3 {
drh9645d8d2006-09-01 15:49:05 +0000358 db function ret_int {return [expr {int(rand()*200)}]}
drhc7f269d2005-05-05 10:30:29 +0000359 execsql {SELECT typeof(ret_int())}
360} {integer}
361
drhd1e47332005-06-26 17:55:33 +0000362# Recursive calls to the same user-defined function
363#
danielk19773bdca9c2006-01-17 09:35:01 +0000364ifcapable tclvar {
365 do_test tcl-9.10 {
366 proc userfunc_r1 {n} {
367 if {$n<=0} {return 0}
368 set nm1 [expr {$n-1}]
369 return [expr {[db eval {SELECT r1($nm1)}]+$n}]
370 }
371 db function r1 userfunc_r1
372 execsql {SELECT r1(10)}
373 } {55}
374 do_test tcl-9.11 {
375 execsql {SELECT r1(100)}
376 } {5050}
377}
drhd1e47332005-06-26 17:55:33 +0000378
drhb5555e72005-08-02 17:15:14 +0000379# Tests for the new transaction method
380#
381do_test tcl-10.1 {
382 db transaction {}
383} {}
384do_test tcl-10.2 {
385 db transaction deferred {}
386} {}
387do_test tcl-10.3 {
388 db transaction immediate {}
389} {}
390do_test tcl-10.4 {
391 db transaction exclusive {}
392} {}
393do_test tcl-10.5 {
394 set rc [catch {db transaction xyzzy {}} msg]
395 lappend rc $msg
396} {1 {bad transaction type "xyzzy": must be deferred, exclusive, or immediate}}
397do_test tcl-10.6 {
398 set rc [catch {db transaction {error test-error}} msg]
399 lappend rc $msg
400} {1 test-error}
401do_test tcl-10.7 {
402 db transaction {
403 db eval {CREATE TABLE t4(x)}
404 db transaction {
405 db eval {INSERT INTO t4 VALUES(1)}
406 }
407 }
408 db eval {SELECT * FROM t4}
409} 1
410do_test tcl-10.8 {
411 catch {
412 db transaction {
413 db eval {INSERT INTO t4 VALUES(2)}
414 db eval {INSERT INTO t4 VALUES(3)}
415 db eval {INSERT INTO t4 VALUES(4)}
416 error test-error
417 }
418 }
419 db eval {SELECT * FROM t4}
420} 1
421do_test tcl-10.9 {
422 db transaction {
423 db eval {INSERT INTO t4 VALUES(2)}
424 catch {
425 db transaction {
426 db eval {INSERT INTO t4 VALUES(3)}
427 db eval {INSERT INTO t4 VALUES(4)}
428 error test-error
429 }
430 }
431 }
432 db eval {SELECT * FROM t4}
danielk1977cd38d522009-01-02 17:33:46 +0000433} {1 2}
drhb5555e72005-08-02 17:15:14 +0000434do_test tcl-10.10 {
435 for {set i 0} {$i<1} {incr i} {
436 db transaction {
437 db eval {INSERT INTO t4 VALUES(5)}
438 continue
439 }
danielk1977cd38d522009-01-02 17:33:46 +0000440 error "This line should not be run"
drhb5555e72005-08-02 17:15:14 +0000441 }
442 db eval {SELECT * FROM t4}
danielk1977cd38d522009-01-02 17:33:46 +0000443} {1 2 5}
drhb5555e72005-08-02 17:15:14 +0000444do_test tcl-10.11 {
445 for {set i 0} {$i<10} {incr i} {
446 db transaction {
447 db eval {INSERT INTO t4 VALUES(6)}
448 break
449 }
450 }
451 db eval {SELECT * FROM t4}
danielk1977cd38d522009-01-02 17:33:46 +0000452} {1 2 5 6}
drhb5555e72005-08-02 17:15:14 +0000453do_test tcl-10.12 {
454 set rc [catch {
455 for {set i 0} {$i<10} {incr i} {
456 db transaction {
457 db eval {INSERT INTO t4 VALUES(7)}
458 return
459 }
460 }
461 }]
462} {2}
463do_test tcl-10.13 {
464 db eval {SELECT * FROM t4}
danielk1977cd38d522009-01-02 17:33:46 +0000465} {1 2 5 6 7}
466
467# Now test that [db transaction] commands may be nested with
468# the expected results.
469#
470do_test tcl-10.14 {
471 db transaction {
472 db eval {
473 DELETE FROM t4;
474 INSERT INTO t4 VALUES('one');
475 }
476
477 catch {
478 db transaction {
479 db eval { INSERT INTO t4 VALUES('two') }
480 db transaction {
481 db eval { INSERT INTO t4 VALUES('three') }
482 error "throw an error!"
483 }
484 }
485 }
486 }
487
488 db eval {SELECT * FROM t4}
489} {one}
490do_test tcl-10.15 {
491 # Make sure a transaction has not been left open.
492 db eval {BEGIN ; COMMIT}
493} {}
494do_test tcl-10.16 {
495 db transaction {
496 db eval { INSERT INTO t4 VALUES('two'); }
497 db transaction {
498 db eval { INSERT INTO t4 VALUES('three') }
499 db transaction {
500 db eval { INSERT INTO t4 VALUES('four') }
501 }
502 }
503 }
504 db eval {SELECT * FROM t4}
505} {one two three four}
506do_test tcl-10.17 {
507 catch {
508 db transaction {
509 db eval { INSERT INTO t4 VALUES('A'); }
510 db transaction {
511 db eval { INSERT INTO t4 VALUES('B') }
512 db transaction {
513 db eval { INSERT INTO t4 VALUES('C') }
514 error "throw an error!"
515 }
516 }
517 }
518 }
519 db eval {SELECT * FROM t4}
520} {one two three four}
521do_test tcl-10.18 {
522 # Make sure a transaction has not been left open.
523 db eval {BEGIN ; COMMIT}
524} {}
525
526# Mess up a [db transaction] command by locking the database using a
527# second connection when it tries to commit. Make sure the transaction
528# is not still open after the "database is locked" exception is thrown.
529#
530do_test tcl-10.18 {
531 sqlite3 db2 test.db
532 db2 eval {
533 BEGIN;
534 SELECT * FROM sqlite_master;
535 }
536
537 set rc [catch {
538 db transaction {
539 db eval {INSERT INTO t4 VALUES('five')}
540 }
541 } msg]
542 list $rc $msg
543} {1 {database is locked}}
544do_test tcl-10.19 {
545 db eval {BEGIN ; COMMIT}
546} {}
547
548# Thwart a [db transaction] command by locking the database using a
549# second connection with "BEGIN EXCLUSIVE". Make sure no transaction is
550# open after the "database is locked" exception is thrown.
551#
552do_test tcl-10.20 {
553 db2 eval {
554 COMMIT;
555 BEGIN EXCLUSIVE;
556 }
557 set rc [catch {
558 db transaction {
559 db eval {INSERT INTO t4 VALUES('five')}
560 }
561 } msg]
562 list $rc $msg
563} {1 {database is locked}}
564do_test tcl-10.21 {
565 db2 close
566 db eval {BEGIN ; COMMIT}
567} {}
568do_test tcl-10.22 {
569 sqlite3 db2 test.db
570 db transaction exclusive {
571 catch { db2 eval {SELECT * FROM sqlite_master} } msg
572 set msg "db2: $msg"
573 }
574 set msg
575} {db2: database is locked}
576db2 close
drhc7f269d2005-05-05 10:30:29 +0000577
drh97f2ebc2005-12-10 21:19:04 +0000578do_test tcl-11.1 {
danielk1977cd38d522009-01-02 17:33:46 +0000579 db eval {INSERT INTO t4 VALUES(6)}
580 db exists {SELECT x,x*2,x+x FROM t4 WHERE x==6}
drh97f2ebc2005-12-10 21:19:04 +0000581} {1}
582do_test tcl-11.2 {
danielk1977cd38d522009-01-02 17:33:46 +0000583 db exists {SELECT 0 FROM t4 WHERE x==6}
drh97f2ebc2005-12-10 21:19:04 +0000584} {1}
585do_test tcl-11.3 {
586 db exists {SELECT 1 FROM t4 WHERE x==8}
587} {0}
drha2c8a952009-10-13 18:38:34 +0000588do_test tcl-11.3.1 {
589 tcl_objproc db exists {SELECT 1 FROM t4 WHERE x==8}
590} {0}
drh97f2ebc2005-12-10 21:19:04 +0000591
danielk1977161fb792006-01-24 10:58:21 +0000592do_test tcl-12.1 {
593 unset -nocomplain a b c version
594 set version [db version]
595 scan $version "%d.%d.%d" a b c
596 expr $a*1000000 + $b*1000 + $c
597} [sqlite3_libversion_number]
598
drh4f5e80f2007-06-19 17:15:46 +0000599
600# Check to see that when bindings of the form @aaa are used instead
drh1c747812007-06-19 23:01:41 +0000601# of $aaa, that objects are treated as bytearray and are inserted
602# as BLOBs.
drh4f5e80f2007-06-19 17:15:46 +0000603#
danielk19774152e672007-09-12 17:01:45 +0000604ifcapable tclvar {
605 do_test tcl-13.1 {
606 db eval {CREATE TABLE t5(x BLOB)}
607 set x abc123
608 db eval {INSERT INTO t5 VALUES($x)}
609 db eval {SELECT typeof(x) FROM t5}
610 } {text}
611 do_test tcl-13.2 {
612 binary scan $x H notUsed
613 db eval {
614 DELETE FROM t5;
615 INSERT INTO t5 VALUES($x);
616 SELECT typeof(x) FROM t5;
617 }
618 } {text}
619 do_test tcl-13.3 {
620 db eval {
621 DELETE FROM t5;
622 INSERT INTO t5 VALUES(@x);
623 SELECT typeof(x) FROM t5;
624 }
625 } {blob}
626 do_test tcl-13.4 {
627 set y 1234
628 db eval {
629 DELETE FROM t5;
630 INSERT INTO t5 VALUES(@y);
631 SELECT hex(x), typeof(x) FROM t5
632 }
633 } {31323334 blob}
634}
drh1c747812007-06-19 23:01:41 +0000635
dand5f12cd2011-08-18 17:47:57 +0000636db func xCall xCall
637proc xCall {} { return "value" }
638do_execsql_test tcl-14.1 {
639 CREATE TABLE t6(x);
640 INSERT INTO t6 VALUES(1);
641}
642do_test tcl-14.2 {
643 db one {SELECT x FROM t6 WHERE xCall()!='value'}
644} {}
645
drhedc40242016-06-13 12:34:38 +0000646# Verify that the "exists" and "onecolumn" methods work when
647# a "profile" is registered.
648#
649catch {db close}
650sqlite3 db :memory:
651proc noop-profile {args} {
652 return
653}
654do_test tcl-15.0 {
655 db eval {CREATE TABLE t1(a); INSERT INTO t1 VALUES(1),(2),(3);}
656 db onecolumn {SELECT a FROM t1 WHERE a>2}
657} {3}
658do_test tcl-15.1 {
659 db exists {SELECT a FROM t1 WHERE a>2}
660} {1}
661do_test tcl-15.2 {
662 db exists {SELECT a FROM t1 WHERE a>3}
663} {0}
664db profile noop-profile
665do_test tcl-15.3 {
666 db onecolumn {SELECT a FROM t1 WHERE a>2}
667} {3}
668do_test tcl-15.4 {
669 db exists {SELECT a FROM t1 WHERE a>2}
670} {1}
671do_test tcl-15.5 {
672 db exists {SELECT a FROM t1 WHERE a>3}
673} {0}
674
675
drhaf38cdb2017-06-26 21:08:32 +0000676# 2017-06-26: The --withoutnulls flag to "db eval".
677#
678# In the "db eval --withoutnulls SQL ARRAY" form, NULL results cause the
679# corresponding array entry to be unset. The default behavior (without
680# the -withoutnulls flags) is for the corresponding array value to get
681# the [db nullvalue] string.
682#
683catch {db close}
684forcedelete test.db
685sqlite3 db test.db
686do_execsql_test tcl-16.100 {
687 CREATE TABLE t1(a,b);
688 INSERT INTO t1 VALUES(1,2),(2,NULL),(3,'xyz');
689}
690do_test tcl-16.101 {
691 set res {}
692 unset -nocomplain x
693 db eval {SELECT * FROM t1} x {
694 lappend res $x(a) [array names x]
695 }
696 set res
697} {1 {a b *} 2 {a b *} 3 {a b *}}
698do_test tcl-16.102 {
699 set res [catch {
700 db eval -unknown {SELECT * FROM t1} x {
701 lappend res $x(a) [array names x]
702 }
703 } rc]
704 lappend res $rc
705} {1 {unknown option: "-unknown"}}
706do_test tcl-16.103 {
707 set res {}
708 unset -nocomplain x
709 db eval -withoutnulls {SELECT * FROM t1} x {
710 lappend res $x(a) [array names x]
711 }
712 set res
713} {1 {a b *} 2 {a *} 3 {a b *}}
drhedc40242016-06-13 12:34:38 +0000714
dan89d24932019-02-27 16:38:19 +0000715#-------------------------------------------------------------------------
716# Test the -type option to [db function].
717#
718reset_db
719proc add {a b} { return [expr $a + $b] }
720proc ret {a} { return $a }
drhedc40242016-06-13 12:34:38 +0000721
dan89d24932019-02-27 16:38:19 +0000722db function add_i -returntype integer add
723db function add_r -ret real add
724db function add_t -return text add
725db function add_b -returntype blob add
726db function add_a -returntype any add
drhedc40242016-06-13 12:34:38 +0000727
dan89d24932019-02-27 16:38:19 +0000728db function ret_i -returntype int ret
729db function ret_r -returntype real ret
730db function ret_t -returntype text ret
731db function ret_b -returntype blob ret
732db function ret_a -r any ret
dand5f12cd2011-08-18 17:47:57 +0000733
dan89d24932019-02-27 16:38:19 +0000734do_execsql_test 17.0 {
735 SELECT quote( add_i(2, 3) );
736 SELECT quote( add_r(2, 3) );
737 SELECT quote( add_t(2, 3) );
738 SELECT quote( add_b(2, 3) );
739 SELECT quote( add_a(2, 3) );
740} {5 5.0 '5' X'35' 5}
741
742do_execsql_test 17.1 {
743 SELECT quote( add_i(2.2, 3.3) );
744 SELECT quote( add_r(2.2, 3.3) );
745 SELECT quote( add_t(2.2, 3.3) );
746 SELECT quote( add_b(2.2, 3.3) );
747 SELECT quote( add_a(2.2, 3.3) );
748} {5.5 5.5 '5.5' X'352E35' 5.5}
749
750do_execsql_test 17.2 {
751 SELECT quote( ret_i(2.5) );
752 SELECT quote( ret_r(2.5) );
753 SELECT quote( ret_t(2.5) );
754 SELECT quote( ret_b(2.5) );
755 SELECT quote( ret_a(2.5) );
756} {2.5 2.5 '2.5' X'322E35' 2.5}
757
758do_execsql_test 17.3 {
759 SELECT quote( ret_i('2.5') );
760 SELECT quote( ret_r('2.5') );
761 SELECT quote( ret_t('2.5') );
762 SELECT quote( ret_b('2.5') );
763 SELECT quote( ret_a('2.5') );
764} {2.5 2.5 '2.5' X'322E35' '2.5'}
765
766do_execsql_test 17.4 {
767 SELECT quote( ret_i('abc') );
768 SELECT quote( ret_r('abc') );
769 SELECT quote( ret_t('abc') );
770 SELECT quote( ret_b('abc') );
771 SELECT quote( ret_a('abc') );
772} {'abc' 'abc' 'abc' X'616263' 'abc'}
773
774do_execsql_test 17.5 {
775 SELECT quote( ret_i(X'616263') );
776 SELECT quote( ret_r(X'616263') );
777 SELECT quote( ret_t(X'616263') );
778 SELECT quote( ret_b(X'616263') );
779 SELECT quote( ret_a(X'616263') );
780} {'abc' 'abc' 'abc' X'616263' X'616263'}
781
782do_test 17.6.1 {
783 list [catch { db function xyz -return object ret } msg] $msg
784} {1 {bad type "object": must be integer, real, text, blob, or any}}
785
786do_test 17.6.2 {
787 list [catch { db function xyz -return ret } msg] $msg
788} {1 {option requires an argument: -return}}
789
790do_test 17.6.3 {
791 list [catch { db function xyz -n object ret } msg] $msg
drh42d2fce2019-08-15 20:04:09 +0000792} {1 {bad option "-n": must be -argcount, -deterministic, -directonly, or -returntype}}
drh4f5e80f2007-06-19 17:15:46 +0000793
drhc06ede12019-02-28 17:29:19 +0000794# 2019-02-28: The "bind_fallback" command.
795#
796do_test 18.100 {
797 unset -nocomplain bindings abc def ghi jkl mno e01 e02
798 set bindings(abc) [expr {1+2}]
799 set bindings(def) {hello}
800 set bindings(ghi) [expr {3.1415926*1.0}]
801 proc bind_callback {nm} {
802 global bindings
803 set n2 [string range $nm 1 end]
804 if {[info exists bindings($n2)]} {
805 return $bindings($n2)
806 }
807 if {[string match e* $n2]} {
808 error "no such variable: $nm"
809 }
810 return -code return {}
811 }
812 db bind_fallback bind_callback
813 db eval {SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi)}
814} {3 integer hello text 3.1415926 real}
815do_test 18.110 {
816 db eval {SELECT quote(@def), typeof(@def)}
817} {X'68656C6C6F' blob}
818do_execsql_test 18.120 {
819 SELECT typeof($mno);
820} {null}
821do_catchsql_test 18.130 {
822 SELECT $e01;
823} {1 {no such variable: $e01}}
824do_test 18.140 {
825 db bind_fallback
826} {bind_callback}
827do_test 18.200 {
828 db bind_fallback {}
829 db eval {SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi)}
830} {{} null {} null {} null}
831do_test 18.300 {
832 unset -nocomplain bindings
833 proc bind_callback {nm} {lappend ::bindings $nm}
834 db bind_fallback bind_callback
835 db eval {SELECT $abc, @def, $ghi(123), :mno}
836 set bindings
837} {{$abc} @def {$ghi(123)} :mno}
838do_test 18.900 {
839 set rc [catch {db bind_fallback a b} msg]
840 lappend rc $msg
841} {1 {wrong # args: should be "db bind_fallback ?CALLBACK?"}}
842do_test 18.910 {
843 db bind_fallback bind_fallback_does_not_exist
844} {}
845do_catchsql_test 19.911 {
846 SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi);
847} {1 {invalid command name "bind_fallback_does_not_exist"}}
848db bind_fallback {}
dan89d24932019-02-27 16:38:19 +0000849
drhc06ede12019-02-28 17:29:19 +0000850finish_test