xref: /sqlite-3.40.0/test/tclsqlite.test (revision be4e3c88)
1b19a2bc6Sdrh# 2001 September 15
2960e8c63Sdrh#
3b19a2bc6Sdrh# The author disclaims copyright to this source code.  In place of
4b19a2bc6Sdrh# a legal notice, here is a blessing:
5960e8c63Sdrh#
6b19a2bc6Sdrh#    May you do good and not evil.
7b19a2bc6Sdrh#    May you find forgiveness for yourself and forgive others.
8b19a2bc6Sdrh#    May you share freely, never taking more than you give.
9960e8c63Sdrh#
10960e8c63Sdrh#***********************************************************************
11960e8c63Sdrh# This file implements regression tests for TCL interface to the
12960e8c63Sdrh# SQLite library.
13960e8c63Sdrh#
14960e8c63Sdrh# Actually, all tests are based on the TCL interface, so the main
15960e8c63Sdrh# interface is pretty well tested.  This file contains some addition
16960e8c63Sdrh# tests for fringe issues that the main test suite does not cover.
17960e8c63Sdrh#
18404ca075Sdanielk1977# $Id: tclsqlite.test,v 1.73 2009/03/16 13:19:36 danielk1977 Exp $
19960e8c63Sdrh
20c6727c83Sdrhcatch {sqlite3}
21c6727c83Sdrh
22960e8c63Sdrhset testdir [file dirname $argv0]
23960e8c63Sdrhsource $testdir/tester.tcl
2489d24936Sdanset testprefix tcl
25960e8c63Sdrh
26960e8c63Sdrh# Check the error messages generated by tclsqlite
27960e8c63Sdrh#
280933aad7Sdrhset r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nofollow BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
297da56b4fSdrhif {[sqlite3 -has-codec]} {
307da56b4fSdrh  append r " ?-key CODECKEY?"
3122fbcb8dSdrh}
32960e8c63Sdrhdo_test tcl-1.1 {
334dcac40eSdrh  set v [catch {sqlite3 -bogus} msg]
34df81a25aSdrh  regsub {really_sqlite3} $msg {sqlite3} msg
35960e8c63Sdrh  lappend v $msg
3622fbcb8dSdrh} [list 1 "wrong # args: should be \"$r\""]
37c6727c83Sdrhdo_test tcl-1.1.1 {
38c6727c83Sdrh  set v [catch {sqlite3} msg]
39c6727c83Sdrh  regsub {really_sqlite3} $msg {sqlite3} msg
40c6727c83Sdrh  lappend v $msg
41c6727c83Sdrh} [list 1 "wrong # args: should be \"$r\""]
42960e8c63Sdrhdo_test tcl-1.2 {
43960e8c63Sdrh  set v [catch {db bogus} msg]
44960e8c63Sdrh  lappend v $msg
45*be4e3c88Sdrh} {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, erroroffset, 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}}
46191fadcfSdanielk1977do_test tcl-1.2.1 {
47191fadcfSdanielk1977  set v [catch {db cache bogus} msg]
48191fadcfSdanielk1977  lappend v $msg
49191fadcfSdanielk1977} {1 {bad option "bogus": must be flush or size}}
50191fadcfSdanielk1977do_test tcl-1.2.2 {
51191fadcfSdanielk1977  set v [catch {db cache} msg]
52191fadcfSdanielk1977  lappend v $msg
53191fadcfSdanielk1977} {1 {wrong # args: should be "db cache option ?arg?"}}
54960e8c63Sdrhdo_test tcl-1.3 {
55960e8c63Sdrh  execsql {CREATE TABLE t1(a int, b int)}
56960e8c63Sdrh  execsql {INSERT INTO t1 VALUES(10,20)}
57960e8c63Sdrh  set v [catch {
58960e8c63Sdrh    db eval {SELECT * FROM t1} data {
59960e8c63Sdrh      error "The error message"
60960e8c63Sdrh    }
61960e8c63Sdrh  } msg]
62960e8c63Sdrh  lappend v $msg
63960e8c63Sdrh} {1 {The error message}}
64960e8c63Sdrhdo_test tcl-1.4 {
65960e8c63Sdrh  set v [catch {
66960e8c63Sdrh    db eval {SELECT * FROM t2} data {
67960e8c63Sdrh      error "The error message"
68960e8c63Sdrh    }
69960e8c63Sdrh  } msg]
70960e8c63Sdrh  lappend v $msg
71960e8c63Sdrh} {1 {no such table: t2}}
72960e8c63Sdrhdo_test tcl-1.5 {
73960e8c63Sdrh  set v [catch {
74960e8c63Sdrh    db eval {SELECT * FROM t1} data {
75960e8c63Sdrh      break
76960e8c63Sdrh    }
77960e8c63Sdrh  } msg]
78960e8c63Sdrh  lappend v $msg
79960e8c63Sdrh} {0 {}}
80d65e530bSdrhcatch {expr x*} msg
81960e8c63Sdrhdo_test tcl-1.6 {
82960e8c63Sdrh  set v [catch {
83960e8c63Sdrh    db eval {SELECT * FROM t1} data {
84960e8c63Sdrh      expr x*
85960e8c63Sdrh    }
86960e8c63Sdrh  } msg]
87960e8c63Sdrh  lappend v $msg
88d65e530bSdrh} [list 1 $msg]
890f14e2ebSdrhdo_test tcl-1.7 {
900f14e2ebSdrh  set v [catch {db} msg]
910f14e2ebSdrh  lappend v $msg
920f14e2ebSdrh} {1 {wrong # args: should be "db SUBCOMMAND ..."}}
931211de37Sdrhif {[catch {db auth {}}]==0} {
940f14e2ebSdrh  do_test tcl-1.8 {
950f14e2ebSdrh    set v [catch {db authorizer 1 2 3} msg]
960f14e2ebSdrh    lappend v $msg
970f14e2ebSdrh  } {1 {wrong # args: should be "db authorizer ?CALLBACK?"}}
981211de37Sdrh}
990f14e2ebSdrhdo_test tcl-1.9 {
1000f14e2ebSdrh  set v [catch {db busy 1 2 3} msg]
1010f14e2ebSdrh  lappend v $msg
1020f14e2ebSdrh} {1 {wrong # args: should be "db busy CALLBACK"}}
1030f14e2ebSdrhdo_test tcl-1.10 {
1040f14e2ebSdrh  set v [catch {db progress 1} msg]
1050f14e2ebSdrh  lappend v $msg
1060f14e2ebSdrh} {1 {wrong # args: should be "db progress N CALLBACK"}}
1070f14e2ebSdrhdo_test tcl-1.11 {
1080f14e2ebSdrh  set v [catch {db changes xyz} msg]
1090f14e2ebSdrh  lappend v $msg
1100f14e2ebSdrh} {1 {wrong # args: should be "db changes "}}
1110f14e2ebSdrhdo_test tcl-1.12 {
1120f14e2ebSdrh  set v [catch {db commit_hook a b c} msg]
1130f14e2ebSdrh  lappend v $msg
1140f14e2ebSdrh} {1 {wrong # args: should be "db commit_hook ?CALLBACK?"}}
115ccae6026Sdrhifcapable {complete} {
1160f14e2ebSdrh  do_test tcl-1.13 {
1170f14e2ebSdrh    set v [catch {db complete} msg]
1180f14e2ebSdrh    lappend v $msg
1190f14e2ebSdrh  } {1 {wrong # args: should be "db complete SQL"}}
120ccae6026Sdrh}
1210f14e2ebSdrhdo_test tcl-1.14 {
1220f14e2ebSdrh  set v [catch {db eval} msg]
1230f14e2ebSdrh  lappend v $msg
124af38cdbcSdrh} {1 {wrong # args: should be "db eval ?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?"}}
1250f14e2ebSdrhdo_test tcl-1.15 {
1260f14e2ebSdrh  set v [catch {db function} msg]
1270f14e2ebSdrh  lappend v $msg
1283df30592Sdan} {1 {wrong # args: should be "db function NAME ?SWITCHES? SCRIPT"}}
1297ddad969Sdanielk1977do_test tcl-1.16 {
1300f14e2ebSdrh  set v [catch {db last_insert_rowid xyz} msg]
1310f14e2ebSdrh  lappend v $msg
1320f14e2ebSdrh} {1 {wrong # args: should be "db last_insert_rowid "}}
1337ddad969Sdanielk1977do_test tcl-1.17 {
1340f14e2ebSdrh  set v [catch {db rekey} msg]
1350f14e2ebSdrh  lappend v $msg
1360f14e2ebSdrh} {1 {wrong # args: should be "db rekey KEY"}}
1377ddad969Sdanielk1977do_test tcl-1.18 {
1380f14e2ebSdrh  set v [catch {db timeout} msg]
1390f14e2ebSdrh  lappend v $msg
1400f14e2ebSdrh} {1 {wrong # args: should be "db timeout MILLISECONDS"}}
1417ddad969Sdanielk1977do_test tcl-1.19 {
1420f14e2ebSdrh  set v [catch {db collate} msg]
1430f14e2ebSdrh  lappend v $msg
1440f14e2ebSdrh} {1 {wrong # args: should be "db collate NAME SCRIPT"}}
1457ddad969Sdanielk1977do_test tcl-1.20 {
1460f14e2ebSdrh  set v [catch {db collation_needed} msg]
1470f14e2ebSdrh  lappend v $msg
1480f14e2ebSdrh} {1 {wrong # args: should be "db collation_needed SCRIPT"}}
1497ddad969Sdanielk1977do_test tcl-1.21 {
1500f14e2ebSdrh  set v [catch {db total_changes xyz} msg]
1510f14e2ebSdrh  lappend v $msg
1520f14e2ebSdrh} {1 {wrong # args: should be "db total_changes "}}
1531c9ee268Smistachkindo_test tcl-1.22 {
1541067fe11Stpoindex  set v [catch {db copy} msg]
1551067fe11Stpoindex  lappend v $msg
1561067fe11Stpoindex} {1 {wrong # args: should be "db copy CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?"}}
1571c9ee268Smistachkindo_test tcl-1.23 {
15895c8a54cSdanielk1977  set v [catch {sqlite3 db2 test.db -vfs nosuchvfs} msg]
15995c8a54cSdanielk1977  lappend v $msg
16095c8a54cSdanielk1977} {1 {no such vfs: nosuchvfs}}
161960e8c63Sdrh
162c275b4eaSdrhcatch {unset ::result}
1636d4abfbeSdrhdo_test tcl-2.1 {
1646d4abfbeSdrh  execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)"
16527188fb5Sdanielk1977} {}
16627188fb5Sdanielk1977ifcapable schema_pragmas {
16727188fb5Sdanielk1977  do_test tcl-2.2 {
1686d4abfbeSdrh    execsql "PRAGMA table_info(t\u0123x)"
169c2df4d6aSdrh  } "0 a INT 0 {} 0 1 b\u1235 float 0 {} 0"
17027188fb5Sdanielk1977}
17127188fb5Sdanielk1977do_test tcl-2.3 {
1726d4abfbeSdrh  execsql "INSERT INTO t\u0123x VALUES(1,2.3)"
1736d4abfbeSdrh  db eval "SELECT * FROM t\u0123x" result break
1746d4abfbeSdrh  set result(*)
1756d4abfbeSdrh} "a b\u1235"
1766d4abfbeSdrh
1776d4abfbeSdrh
1785d9d7576Sdrh# Test the onecolumn method
1795d9d7576Sdrh#
1805d9d7576Sdrhdo_test tcl-3.1 {
1815d9d7576Sdrh  execsql {
1825d9d7576Sdrh    INSERT INTO t1 SELECT a*2, b*2 FROM t1;
1835d9d7576Sdrh    INSERT INTO t1 SELECT a*2+1, b*2+1 FROM t1;
1845d9d7576Sdrh    INSERT INTO t1 SELECT a*2+3, b*2+3 FROM t1;
1855d9d7576Sdrh  }
18622fbcb8dSdrh  set rc [catch {db onecolumn {SELECT * FROM t1 ORDER BY a}} msg]
18722fbcb8dSdrh  lappend rc $msg
18822fbcb8dSdrh} {0 10}
1895d9d7576Sdrhdo_test tcl-3.2 {
1905d9d7576Sdrh  db onecolumn {SELECT * FROM t1 WHERE a<0}
1915d9d7576Sdrh} {}
1925d9d7576Sdrhdo_test tcl-3.3 {
1935d9d7576Sdrh  set rc [catch {db onecolumn} errmsg]
1945d9d7576Sdrh  lappend rc $errmsg
1955d9d7576Sdrh} {1 {wrong # args: should be "db onecolumn SQL"}}
1960f14e2ebSdrhdo_test tcl-3.4 {
1970f14e2ebSdrh  set rc [catch {db onecolumn {SELECT bogus}} errmsg]
1980f14e2ebSdrh  lappend rc $errmsg
1990f14e2ebSdrh} {1 {no such column: bogus}}
2006bf89570Sdrhifcapable {tclvar} {
2011807ce37Sdrh  do_test tcl-3.5 {
2021807ce37Sdrh    set b 50
2031807ce37Sdrh    set rc [catch {db one {SELECT * FROM t1 WHERE b>$b}} msg]
2041807ce37Sdrh    lappend rc $msg
2051807ce37Sdrh  } {0 41}
2061807ce37Sdrh  do_test tcl-3.6 {
2071807ce37Sdrh    set b 500
2081807ce37Sdrh    set rc [catch {db one {SELECT * FROM t1 WHERE b>$b}} msg]
2091807ce37Sdrh    lappend rc $msg
2101807ce37Sdrh  } {0 {}}
2111807ce37Sdrh  do_test tcl-3.7 {
2121807ce37Sdrh    set b 500
2131807ce37Sdrh    set rc [catch {db one {
2141807ce37Sdrh      INSERT INTO t1 VALUES(99,510);
2151807ce37Sdrh      SELECT * FROM t1 WHERE b>$b
2161807ce37Sdrh    }} msg]
2171807ce37Sdrh    lappend rc $msg
2181807ce37Sdrh  } {0 99}
2196bf89570Sdrh}
2206bf89570Sdrhifcapable {!tclvar} {
2216bf89570Sdrh   execsql {INSERT INTO t1 VALUES(99,510)}
2226bf89570Sdrh}
2235d9d7576Sdrh
2240f14e2ebSdrh# Turn the busy handler on and off
2250f14e2ebSdrh#
2260f14e2ebSdrhdo_test tcl-4.1 {
2270f14e2ebSdrh  proc busy_callback {cnt} {
2280f14e2ebSdrh    break
2290f14e2ebSdrh  }
2300f14e2ebSdrh  db busy busy_callback
2310f14e2ebSdrh  db busy
2320f14e2ebSdrh} {busy_callback}
2330f14e2ebSdrhdo_test tcl-4.2 {
2340f14e2ebSdrh  db busy {}
2350f14e2ebSdrh  db busy
2360f14e2ebSdrh} {}
2376d4abfbeSdrh
2386bf89570Sdrhifcapable {tclvar} {
23992febd92Sdrh  # Parsing of TCL variable names within SQL into bound parameters.
24092febd92Sdrh  #
24192febd92Sdrh  do_test tcl-5.1 {
24292febd92Sdrh    execsql {CREATE TABLE t3(a,b,c)}
24392febd92Sdrh    catch {unset x}
2447a1d17f1Sdanielk1977    set x(1) A
2457a1d17f1Sdanielk1977    set x(2) B
24692febd92Sdrh    execsql {
24792febd92Sdrh      INSERT INTO t3 VALUES($::x(1),$::x(2),$::x(3));
24892febd92Sdrh      SELECT * FROM t3
24992febd92Sdrh    }
2507a1d17f1Sdanielk1977  } {A B {}}
25192febd92Sdrh  do_test tcl-5.2 {
25292febd92Sdrh    execsql {
25392febd92Sdrh      SELECT typeof(a), typeof(b), typeof(c) FROM t3
25492febd92Sdrh    }
25592febd92Sdrh  } {text text null}
25692febd92Sdrh  do_test tcl-5.3 {
25792febd92Sdrh    catch {unset x}
25892febd92Sdrh    set x [binary format h12 686900686f00]
25992febd92Sdrh    execsql {
26092febd92Sdrh      UPDATE t3 SET a=$::x;
26192febd92Sdrh    }
26292febd92Sdrh    db eval {
26392febd92Sdrh      SELECT a FROM t3
26492febd92Sdrh    } break
26592febd92Sdrh    binary scan $a h12 adata
26692febd92Sdrh    set adata
26792febd92Sdrh  } {686900686f00}
26892febd92Sdrh  do_test tcl-5.4 {
26992febd92Sdrh    execsql {
27092febd92Sdrh      SELECT typeof(a), typeof(b), typeof(c) FROM t3
27192febd92Sdrh    }
27292febd92Sdrh  } {blob text null}
2736bf89570Sdrh}
27492febd92Sdrh
275fd241b0eSdrh# Operation of "break" and "continue" within row scripts
276fd241b0eSdrh#
277fd241b0eSdrhdo_test tcl-6.1 {
278fd241b0eSdrh  db eval {SELECT * FROM t1} {
279fd241b0eSdrh    break
280fd241b0eSdrh  }
281fd241b0eSdrh  lappend a $b
282fd241b0eSdrh} {10 20}
283fd241b0eSdrhdo_test tcl-6.2 {
284fd241b0eSdrh  set cnt 0
285fd241b0eSdrh  db eval {SELECT * FROM t1} {
286fd241b0eSdrh    if {$a>40} continue
287fd241b0eSdrh    incr cnt
288fd241b0eSdrh  }
289fd241b0eSdrh  set cnt
290fd241b0eSdrh} {4}
291fd241b0eSdrhdo_test tcl-6.3 {
292fd241b0eSdrh  set cnt 0
293fd241b0eSdrh  db eval {SELECT * FROM t1} {
294fd241b0eSdrh    if {$a<40} continue
295fd241b0eSdrh    incr cnt
296fd241b0eSdrh  }
297fd241b0eSdrh  set cnt
298fd241b0eSdrh} {5}
299fd241b0eSdrhdo_test tcl-6.4 {
300fd241b0eSdrh  proc return_test {x} {
301fd241b0eSdrh    db eval {SELECT * FROM t1} {
302fd241b0eSdrh      if {$a==$x} {return $b}
303fd241b0eSdrh    }
304fd241b0eSdrh  }
305fd241b0eSdrh  return_test 10
306fd241b0eSdrh} 20
307fd241b0eSdrhdo_test tcl-6.5 {
308fd241b0eSdrh  return_test 20
309fd241b0eSdrh} 40
310fd241b0eSdrhdo_test tcl-6.6 {
311fd241b0eSdrh  return_test 99
312fd241b0eSdrh} 510
313fd241b0eSdrhdo_test tcl-6.7 {
314fd241b0eSdrh  return_test 0
315fd241b0eSdrh} {}
316fd241b0eSdrh
3174397de57Sdanielk1977do_test tcl-7.1 {
3184397de57Sdanielk1977  db version
3194397de57Sdanielk1977  expr 0
3204397de57Sdanielk1977} {0}
3214397de57Sdanielk1977
32255c45f2eSdanielk1977# modify and reset the NULL representation
32355c45f2eSdanielk1977#
32455c45f2eSdanielk1977do_test tcl-8.1 {
32555c45f2eSdanielk1977  db nullvalue NaN
32655c45f2eSdanielk1977  execsql {INSERT INTO t1 VALUES(30,NULL)}
32755c45f2eSdanielk1977  db eval {SELECT * FROM t1 WHERE b IS NULL}
32855c45f2eSdanielk1977} {30 NaN}
329c45e6716Sdrhproc concatFunc args {return [join $args {}]}
33055c45f2eSdanielk1977do_test tcl-8.2 {
331c45e6716Sdrh  db function concat concatFunc
332c45e6716Sdrh  db eval {SELECT concat('a', b, 'z') FROM t1 WHERE b is NULL}
333c45e6716Sdrh} {aNaNz}
334c45e6716Sdrhdo_test tcl-8.3 {
33555c45f2eSdanielk1977  db nullvalue NULL
33655c45f2eSdanielk1977  db nullvalue
33755c45f2eSdanielk1977} {NULL}
338c45e6716Sdrhdo_test tcl-8.4 {
33955c45f2eSdanielk1977  db nullvalue {}
34055c45f2eSdanielk1977  db eval {SELECT * FROM t1 WHERE b IS NULL}
34155c45f2eSdanielk1977} {30 {}}
342c45e6716Sdrhdo_test tcl-8.5 {
343c45e6716Sdrh  db function concat concatFunc
344c45e6716Sdrh  db eval {SELECT concat('a', b, 'z') FROM t1 WHERE b is NULL}
345c45e6716Sdrh} {az}
34655c45f2eSdanielk1977
347c7f269d5Sdrh# Test the return type of user-defined functions
348c7f269d5Sdrh#
349c7f269d5Sdrhdo_test tcl-9.1 {
350c7f269d5Sdrh  db function ret_str {return "hi"}
351c7f269d5Sdrh  execsql {SELECT typeof(ret_str())}
352c7f269d5Sdrh} {text}
353c7f269d5Sdrhdo_test tcl-9.2 {
3549645d8d4Sdrh  db function ret_dbl {return [expr {rand()*0.5}]}
355c7f269d5Sdrh  execsql {SELECT typeof(ret_dbl())}
356c7f269d5Sdrh} {real}
357c7f269d5Sdrhdo_test tcl-9.3 {
3589645d8d4Sdrh  db function ret_int {return [expr {int(rand()*200)}]}
359c7f269d5Sdrh  execsql {SELECT typeof(ret_int())}
360c7f269d5Sdrh} {integer}
361c7f269d5Sdrh
362d1e4733dSdrh# Recursive calls to the same user-defined function
363d1e4733dSdrh#
3643bdca9c9Sdanielk1977ifcapable tclvar {
365d1e4733dSdrh  do_test tcl-9.10 {
366d1e4733dSdrh    proc userfunc_r1 {n} {
367d1e4733dSdrh      if {$n<=0} {return 0}
368d1e4733dSdrh      set nm1 [expr {$n-1}]
369d1e4733dSdrh      return [expr {[db eval {SELECT r1($nm1)}]+$n}]
370d1e4733dSdrh    }
371d1e4733dSdrh    db function r1 userfunc_r1
372d1e4733dSdrh    execsql {SELECT r1(10)}
373d1e4733dSdrh  } {55}
374a01fda71Sdrh  # Fails under -fsanitize=address,undefined due to stack overflow
375a01fda71Sdrh  # do_test tcl-9.11 {
376a01fda71Sdrh  #   execsql {SELECT r1(100)}
377a01fda71Sdrh  # } {5050}
3783bdca9c9Sdanielk1977}
379d1e4733dSdrh
380b5555e7eSdrh# Tests for the new transaction method
381b5555e7eSdrh#
382b5555e7eSdrhdo_test tcl-10.1 {
383b5555e7eSdrh  db transaction {}
384b5555e7eSdrh} {}
385b5555e7eSdrhdo_test tcl-10.2 {
386b5555e7eSdrh  db transaction deferred {}
387b5555e7eSdrh} {}
388b5555e7eSdrhdo_test tcl-10.3 {
389b5555e7eSdrh  db transaction immediate {}
390b5555e7eSdrh} {}
391b5555e7eSdrhdo_test tcl-10.4 {
392b5555e7eSdrh  db transaction exclusive {}
393b5555e7eSdrh} {}
394b5555e7eSdrhdo_test tcl-10.5 {
395b5555e7eSdrh  set rc [catch {db transaction xyzzy {}} msg]
396b5555e7eSdrh  lappend rc $msg
397b5555e7eSdrh} {1 {bad transaction type "xyzzy": must be deferred, exclusive, or immediate}}
398b5555e7eSdrhdo_test tcl-10.6 {
399b5555e7eSdrh  set rc [catch {db transaction {error test-error}} msg]
400b5555e7eSdrh  lappend rc $msg
401b5555e7eSdrh} {1 test-error}
402b5555e7eSdrhdo_test tcl-10.7 {
403b5555e7eSdrh  db transaction {
404b5555e7eSdrh    db eval {CREATE TABLE t4(x)}
405b5555e7eSdrh    db transaction {
406b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(1)}
407b5555e7eSdrh    }
408b5555e7eSdrh  }
409b5555e7eSdrh  db eval {SELECT * FROM t4}
410b5555e7eSdrh} 1
411b5555e7eSdrhdo_test tcl-10.8 {
412b5555e7eSdrh  catch {
413b5555e7eSdrh    db transaction {
414b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(2)}
415b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(3)}
416b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(4)}
417b5555e7eSdrh      error test-error
418b5555e7eSdrh    }
419b5555e7eSdrh  }
420b5555e7eSdrh  db eval {SELECT * FROM t4}
421b5555e7eSdrh} 1
422b5555e7eSdrhdo_test tcl-10.9 {
423b5555e7eSdrh  db transaction {
424b5555e7eSdrh    db eval {INSERT INTO t4 VALUES(2)}
425b5555e7eSdrh    catch {
426b5555e7eSdrh      db transaction {
427b5555e7eSdrh        db eval {INSERT INTO t4 VALUES(3)}
428b5555e7eSdrh        db eval {INSERT INTO t4 VALUES(4)}
429b5555e7eSdrh        error test-error
430b5555e7eSdrh      }
431b5555e7eSdrh    }
432b5555e7eSdrh  }
433b5555e7eSdrh  db eval {SELECT * FROM t4}
434cd38d520Sdanielk1977} {1 2}
435b5555e7eSdrhdo_test tcl-10.10 {
436b5555e7eSdrh  for {set i 0} {$i<1} {incr i} {
437b5555e7eSdrh    db transaction {
438b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(5)}
439b5555e7eSdrh      continue
440b5555e7eSdrh    }
441cd38d520Sdanielk1977    error "This line should not be run"
442b5555e7eSdrh  }
443b5555e7eSdrh  db eval {SELECT * FROM t4}
444cd38d520Sdanielk1977} {1 2 5}
445b5555e7eSdrhdo_test tcl-10.11 {
446b5555e7eSdrh  for {set i 0} {$i<10} {incr i} {
447b5555e7eSdrh    db transaction {
448b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(6)}
449b5555e7eSdrh      break
450b5555e7eSdrh    }
451b5555e7eSdrh  }
452b5555e7eSdrh  db eval {SELECT * FROM t4}
453cd38d520Sdanielk1977} {1 2 5 6}
454b5555e7eSdrhdo_test tcl-10.12 {
455b5555e7eSdrh  set rc [catch {
456b5555e7eSdrh    for {set i 0} {$i<10} {incr i} {
457b5555e7eSdrh      db transaction {
458b5555e7eSdrh        db eval {INSERT INTO t4 VALUES(7)}
459b5555e7eSdrh        return
460b5555e7eSdrh      }
461b5555e7eSdrh    }
462b5555e7eSdrh  }]
463b5555e7eSdrh} {2}
464b5555e7eSdrhdo_test tcl-10.13 {
465b5555e7eSdrh  db eval {SELECT * FROM t4}
466cd38d520Sdanielk1977} {1 2 5 6 7}
467cd38d520Sdanielk1977
468cd38d520Sdanielk1977# Now test that [db transaction] commands may be nested with
469cd38d520Sdanielk1977# the expected results.
470cd38d520Sdanielk1977#
471cd38d520Sdanielk1977do_test tcl-10.14 {
472cd38d520Sdanielk1977  db transaction {
473cd38d520Sdanielk1977    db eval {
474cd38d520Sdanielk1977      DELETE FROM t4;
475cd38d520Sdanielk1977      INSERT INTO t4 VALUES('one');
476cd38d520Sdanielk1977    }
477cd38d520Sdanielk1977
478cd38d520Sdanielk1977    catch {
479cd38d520Sdanielk1977      db transaction {
480cd38d520Sdanielk1977        db eval { INSERT INTO t4 VALUES('two') }
481cd38d520Sdanielk1977        db transaction {
482cd38d520Sdanielk1977          db eval { INSERT INTO t4 VALUES('three') }
483cd38d520Sdanielk1977          error "throw an error!"
484cd38d520Sdanielk1977        }
485cd38d520Sdanielk1977      }
486cd38d520Sdanielk1977    }
487cd38d520Sdanielk1977  }
488cd38d520Sdanielk1977
489cd38d520Sdanielk1977  db eval {SELECT * FROM t4}
490cd38d520Sdanielk1977} {one}
491cd38d520Sdanielk1977do_test tcl-10.15 {
492cd38d520Sdanielk1977  # Make sure a transaction has not been left open.
493cd38d520Sdanielk1977  db eval {BEGIN ; COMMIT}
494cd38d520Sdanielk1977} {}
495cd38d520Sdanielk1977do_test tcl-10.16 {
496cd38d520Sdanielk1977  db transaction {
497cd38d520Sdanielk1977    db eval { INSERT INTO t4 VALUES('two'); }
498cd38d520Sdanielk1977    db transaction {
499cd38d520Sdanielk1977      db eval { INSERT INTO t4 VALUES('three') }
500cd38d520Sdanielk1977      db transaction {
501cd38d520Sdanielk1977        db eval { INSERT INTO t4 VALUES('four') }
502cd38d520Sdanielk1977      }
503cd38d520Sdanielk1977    }
504cd38d520Sdanielk1977  }
505cd38d520Sdanielk1977  db eval {SELECT * FROM t4}
506cd38d520Sdanielk1977} {one two three four}
507cd38d520Sdanielk1977do_test tcl-10.17 {
508cd38d520Sdanielk1977  catch {
509cd38d520Sdanielk1977    db transaction {
510cd38d520Sdanielk1977      db eval { INSERT INTO t4 VALUES('A'); }
511cd38d520Sdanielk1977      db transaction {
512cd38d520Sdanielk1977        db eval { INSERT INTO t4 VALUES('B') }
513cd38d520Sdanielk1977        db transaction {
514cd38d520Sdanielk1977          db eval { INSERT INTO t4 VALUES('C') }
515cd38d520Sdanielk1977          error "throw an error!"
516cd38d520Sdanielk1977        }
517cd38d520Sdanielk1977      }
518cd38d520Sdanielk1977    }
519cd38d520Sdanielk1977  }
520cd38d520Sdanielk1977  db eval {SELECT * FROM t4}
521cd38d520Sdanielk1977} {one two three four}
522cd38d520Sdanielk1977do_test tcl-10.18 {
523cd38d520Sdanielk1977  # Make sure a transaction has not been left open.
524cd38d520Sdanielk1977  db eval {BEGIN ; COMMIT}
525cd38d520Sdanielk1977} {}
526cd38d520Sdanielk1977
527cd38d520Sdanielk1977# Mess up a [db transaction] command by locking the database using a
528cd38d520Sdanielk1977# second connection when it tries to commit. Make sure the transaction
529cd38d520Sdanielk1977# is not still open after the "database is locked" exception is thrown.
530cd38d520Sdanielk1977#
531cd38d520Sdanielk1977do_test tcl-10.18 {
532cd38d520Sdanielk1977  sqlite3 db2 test.db
533cd38d520Sdanielk1977  db2 eval {
534cd38d520Sdanielk1977    BEGIN;
535cd38d520Sdanielk1977    SELECT * FROM sqlite_master;
536cd38d520Sdanielk1977  }
537cd38d520Sdanielk1977
538cd38d520Sdanielk1977  set rc [catch {
539cd38d520Sdanielk1977    db transaction {
540cd38d520Sdanielk1977      db eval {INSERT INTO t4 VALUES('five')}
541cd38d520Sdanielk1977    }
542cd38d520Sdanielk1977  } msg]
543cd38d520Sdanielk1977  list $rc $msg
544cd38d520Sdanielk1977} {1 {database is locked}}
545cd38d520Sdanielk1977do_test tcl-10.19 {
546cd38d520Sdanielk1977  db eval {BEGIN ; COMMIT}
547cd38d520Sdanielk1977} {}
548cd38d520Sdanielk1977
549cd38d520Sdanielk1977# Thwart a [db transaction] command by locking the database using a
550cd38d520Sdanielk1977# second connection with "BEGIN EXCLUSIVE". Make sure no transaction is
551cd38d520Sdanielk1977# open after the "database is locked" exception is thrown.
552cd38d520Sdanielk1977#
553cd38d520Sdanielk1977do_test tcl-10.20 {
554cd38d520Sdanielk1977  db2 eval {
555cd38d520Sdanielk1977    COMMIT;
556cd38d520Sdanielk1977    BEGIN EXCLUSIVE;
557cd38d520Sdanielk1977  }
558cd38d520Sdanielk1977  set rc [catch {
559cd38d520Sdanielk1977    db transaction {
560cd38d520Sdanielk1977      db eval {INSERT INTO t4 VALUES('five')}
561cd38d520Sdanielk1977    }
562cd38d520Sdanielk1977  } msg]
563cd38d520Sdanielk1977  list $rc $msg
564cd38d520Sdanielk1977} {1 {database is locked}}
565cd38d520Sdanielk1977do_test tcl-10.21 {
566cd38d520Sdanielk1977  db2 close
567cd38d520Sdanielk1977  db eval {BEGIN ; COMMIT}
568cd38d520Sdanielk1977} {}
569cd38d520Sdanielk1977do_test tcl-10.22 {
570cd38d520Sdanielk1977  sqlite3 db2 test.db
571cd38d520Sdanielk1977  db transaction exclusive {
572cd38d520Sdanielk1977    catch { db2 eval {SELECT * FROM sqlite_master} } msg
573cd38d520Sdanielk1977    set msg "db2: $msg"
574cd38d520Sdanielk1977  }
575cd38d520Sdanielk1977  set msg
576cd38d520Sdanielk1977} {db2: database is locked}
577cd38d520Sdanielk1977db2 close
578c7f269d5Sdrh
57997f2ebc1Sdrhdo_test tcl-11.1 {
580cd38d520Sdanielk1977  db eval {INSERT INTO t4 VALUES(6)}
581cd38d520Sdanielk1977  db exists {SELECT x,x*2,x+x FROM t4 WHERE x==6}
58297f2ebc1Sdrh} {1}
58397f2ebc1Sdrhdo_test tcl-11.2 {
584cd38d520Sdanielk1977  db exists {SELECT 0 FROM t4 WHERE x==6}
58597f2ebc1Sdrh} {1}
58697f2ebc1Sdrhdo_test tcl-11.3 {
58797f2ebc1Sdrh  db exists {SELECT 1 FROM t4 WHERE x==8}
58897f2ebc1Sdrh} {0}
589a2c8a95bSdrhdo_test tcl-11.3.1 {
590a2c8a95bSdrh  tcl_objproc db exists {SELECT 1 FROM t4 WHERE x==8}
591a2c8a95bSdrh} {0}
59297f2ebc1Sdrh
593161fb796Sdanielk1977do_test tcl-12.1 {
594161fb796Sdanielk1977  unset -nocomplain a b c version
595161fb796Sdanielk1977  set version [db version]
596161fb796Sdanielk1977  scan $version "%d.%d.%d" a b c
597161fb796Sdanielk1977  expr $a*1000000 + $b*1000 + $c
598161fb796Sdanielk1977} [sqlite3_libversion_number]
599161fb796Sdanielk1977
6004f5e80f9Sdrh
6014f5e80f9Sdrh# Check to see that when bindings of the form @aaa are used instead
6021c747819Sdrh# of $aaa, that objects are treated as bytearray and are inserted
6031c747819Sdrh# as BLOBs.
6044f5e80f9Sdrh#
6054152e677Sdanielk1977ifcapable tclvar {
6064f5e80f9Sdrh  do_test tcl-13.1 {
6074f5e80f9Sdrh    db eval {CREATE TABLE t5(x BLOB)}
6084f5e80f9Sdrh    set x abc123
6094f5e80f9Sdrh    db eval {INSERT INTO t5 VALUES($x)}
6104f5e80f9Sdrh    db eval {SELECT typeof(x) FROM t5}
6114f5e80f9Sdrh  } {text}
6124f5e80f9Sdrh  do_test tcl-13.2 {
6134f5e80f9Sdrh    binary scan $x H notUsed
6144f5e80f9Sdrh    db eval {
6154f5e80f9Sdrh      DELETE FROM t5;
6164f5e80f9Sdrh      INSERT INTO t5 VALUES($x);
6174f5e80f9Sdrh      SELECT typeof(x) FROM t5;
6184f5e80f9Sdrh    }
6194f5e80f9Sdrh  } {text}
6204f5e80f9Sdrh  do_test tcl-13.3 {
6214f5e80f9Sdrh    db eval {
6224f5e80f9Sdrh      DELETE FROM t5;
6234f5e80f9Sdrh      INSERT INTO t5 VALUES(@x);
6244f5e80f9Sdrh      SELECT typeof(x) FROM t5;
6254f5e80f9Sdrh    }
6264f5e80f9Sdrh  } {blob}
6271c747819Sdrh  do_test tcl-13.4 {
6281c747819Sdrh    set y 1234
6291c747819Sdrh    db eval {
6301c747819Sdrh      DELETE FROM t5;
6311c747819Sdrh      INSERT INTO t5 VALUES(@y);
6321c747819Sdrh      SELECT hex(x), typeof(x) FROM t5
6331c747819Sdrh    }
6341c747819Sdrh  } {31323334 blob}
6354152e677Sdanielk1977}
6361c747819Sdrh
637d5f12cd5Sdandb func xCall xCall
638d5f12cd5Sdanproc xCall {} { return "value" }
639d5f12cd5Sdando_execsql_test tcl-14.1 {
640d5f12cd5Sdan  CREATE TABLE t6(x);
641d5f12cd5Sdan  INSERT INTO t6 VALUES(1);
642d5f12cd5Sdan}
643d5f12cd5Sdando_test tcl-14.2 {
644d5f12cd5Sdan  db one {SELECT x FROM t6 WHERE xCall()!='value'}
645d5f12cd5Sdan} {}
646d5f12cd5Sdan
647edc4024bSdrh# Verify that the "exists" and "onecolumn" methods work when
648edc4024bSdrh# a "profile" is registered.
649edc4024bSdrh#
650edc4024bSdrhcatch {db close}
651edc4024bSdrhsqlite3 db :memory:
652edc4024bSdrhproc noop-profile {args} {
653edc4024bSdrh  return
654edc4024bSdrh}
655edc4024bSdrhdo_test tcl-15.0 {
656edc4024bSdrh  db eval {CREATE TABLE t1(a); INSERT INTO t1 VALUES(1),(2),(3);}
657edc4024bSdrh  db onecolumn {SELECT a FROM t1 WHERE a>2}
658edc4024bSdrh} {3}
659edc4024bSdrhdo_test tcl-15.1 {
660edc4024bSdrh  db exists {SELECT a FROM t1 WHERE a>2}
661edc4024bSdrh} {1}
662edc4024bSdrhdo_test tcl-15.2 {
663edc4024bSdrh  db exists {SELECT a FROM t1 WHERE a>3}
664edc4024bSdrh} {0}
665edc4024bSdrhdb profile noop-profile
666edc4024bSdrhdo_test tcl-15.3 {
667edc4024bSdrh  db onecolumn {SELECT a FROM t1 WHERE a>2}
668edc4024bSdrh} {3}
669edc4024bSdrhdo_test tcl-15.4 {
670edc4024bSdrh  db exists {SELECT a FROM t1 WHERE a>2}
671edc4024bSdrh} {1}
672edc4024bSdrhdo_test tcl-15.5 {
673edc4024bSdrh  db exists {SELECT a FROM t1 WHERE a>3}
674edc4024bSdrh} {0}
675edc4024bSdrh
676edc4024bSdrh
677af38cdbcSdrh# 2017-06-26: The --withoutnulls flag to "db eval".
678af38cdbcSdrh#
679af38cdbcSdrh# In the "db eval --withoutnulls SQL ARRAY" form, NULL results cause the
680af38cdbcSdrh# corresponding array entry to be unset.  The default behavior (without
681af38cdbcSdrh# the -withoutnulls flags) is for the corresponding array value to get
682af38cdbcSdrh# the [db nullvalue] string.
683af38cdbcSdrh#
684af38cdbcSdrhcatch {db close}
685af38cdbcSdrhforcedelete test.db
686af38cdbcSdrhsqlite3 db test.db
687af38cdbcSdrhdo_execsql_test tcl-16.100 {
688af38cdbcSdrh  CREATE TABLE t1(a,b);
689af38cdbcSdrh  INSERT INTO t1 VALUES(1,2),(2,NULL),(3,'xyz');
690af38cdbcSdrh}
691af38cdbcSdrhdo_test tcl-16.101 {
692af38cdbcSdrh  set res {}
693af38cdbcSdrh  unset -nocomplain x
694af38cdbcSdrh  db eval {SELECT * FROM t1} x {
695af38cdbcSdrh    lappend res $x(a) [array names x]
696af38cdbcSdrh  }
697af38cdbcSdrh  set res
698af38cdbcSdrh} {1 {a b *} 2 {a b *} 3 {a b *}}
699af38cdbcSdrhdo_test tcl-16.102 {
700af38cdbcSdrh  set res [catch {
701af38cdbcSdrh    db eval -unknown {SELECT * FROM t1} x {
702af38cdbcSdrh      lappend res $x(a) [array names x]
703af38cdbcSdrh    }
704af38cdbcSdrh  } rc]
705af38cdbcSdrh  lappend res $rc
706af38cdbcSdrh} {1 {unknown option: "-unknown"}}
707af38cdbcSdrhdo_test tcl-16.103 {
708af38cdbcSdrh  set res {}
709af38cdbcSdrh  unset -nocomplain x
710af38cdbcSdrh  db eval -withoutnulls {SELECT * FROM t1} x {
711af38cdbcSdrh    lappend res $x(a) [array names x]
712af38cdbcSdrh  }
713af38cdbcSdrh  set res
714af38cdbcSdrh} {1 {a b *} 2 {a *} 3 {a b *}}
715edc4024bSdrh
71689d24936Sdan#-------------------------------------------------------------------------
71789d24936Sdan# Test the -type option to [db function].
71889d24936Sdan#
71989d24936Sdanreset_db
72089d24936Sdanproc add {a b} { return [expr $a + $b] }
72189d24936Sdanproc ret {a} { return $a }
722edc4024bSdrh
72389d24936Sdandb function add_i -returntype integer add
72489d24936Sdandb function add_r -ret        real    add
72589d24936Sdandb function add_t -return     text    add
72689d24936Sdandb function add_b -returntype blob    add
72789d24936Sdandb function add_a -returntype any     add
728edc4024bSdrh
72989d24936Sdandb function ret_i -returntype int     ret
73089d24936Sdandb function ret_r -returntype real    ret
73189d24936Sdandb function ret_t -returntype text    ret
73289d24936Sdandb function ret_b -returntype blob    ret
73389d24936Sdandb function ret_a -r          any     ret
734d5f12cd5Sdan
73589d24936Sdando_execsql_test 17.0 {
73689d24936Sdan  SELECT quote( add_i(2, 3) );
73789d24936Sdan  SELECT quote( add_r(2, 3) );
73889d24936Sdan  SELECT quote( add_t(2, 3) );
73989d24936Sdan  SELECT quote( add_b(2, 3) );
74089d24936Sdan  SELECT quote( add_a(2, 3) );
74189d24936Sdan} {5 5.0 '5' X'35' 5}
74289d24936Sdan
74389d24936Sdando_execsql_test 17.1 {
74489d24936Sdan  SELECT quote( add_i(2.2, 3.3) );
74589d24936Sdan  SELECT quote( add_r(2.2, 3.3) );
74689d24936Sdan  SELECT quote( add_t(2.2, 3.3) );
74789d24936Sdan  SELECT quote( add_b(2.2, 3.3) );
74889d24936Sdan  SELECT quote( add_a(2.2, 3.3) );
74989d24936Sdan} {5.5 5.5 '5.5' X'352E35' 5.5}
75089d24936Sdan
75189d24936Sdando_execsql_test 17.2 {
75289d24936Sdan  SELECT quote( ret_i(2.5) );
75389d24936Sdan  SELECT quote( ret_r(2.5) );
75489d24936Sdan  SELECT quote( ret_t(2.5) );
75589d24936Sdan  SELECT quote( ret_b(2.5) );
75689d24936Sdan  SELECT quote( ret_a(2.5) );
75789d24936Sdan} {2.5 2.5 '2.5' X'322E35' 2.5}
75889d24936Sdan
75989d24936Sdando_execsql_test 17.3 {
76089d24936Sdan  SELECT quote( ret_i('2.5') );
76189d24936Sdan  SELECT quote( ret_r('2.5') );
76289d24936Sdan  SELECT quote( ret_t('2.5') );
76389d24936Sdan  SELECT quote( ret_b('2.5') );
76489d24936Sdan  SELECT quote( ret_a('2.5') );
76589d24936Sdan} {2.5 2.5 '2.5' X'322E35' '2.5'}
76689d24936Sdan
76789d24936Sdando_execsql_test 17.4 {
76889d24936Sdan  SELECT quote( ret_i('abc') );
76989d24936Sdan  SELECT quote( ret_r('abc') );
77089d24936Sdan  SELECT quote( ret_t('abc') );
77189d24936Sdan  SELECT quote( ret_b('abc') );
77289d24936Sdan  SELECT quote( ret_a('abc') );
77389d24936Sdan} {'abc' 'abc' 'abc' X'616263' 'abc'}
77489d24936Sdan
77589d24936Sdando_execsql_test 17.5 {
77689d24936Sdan  SELECT quote( ret_i(X'616263') );
77789d24936Sdan  SELECT quote( ret_r(X'616263') );
77889d24936Sdan  SELECT quote( ret_t(X'616263') );
77989d24936Sdan  SELECT quote( ret_b(X'616263') );
78089d24936Sdan  SELECT quote( ret_a(X'616263') );
78189d24936Sdan} {'abc' 'abc' 'abc' X'616263' X'616263'}
78289d24936Sdan
78389d24936Sdando_test 17.6.1 {
78489d24936Sdan  list [catch { db function xyz -return object ret } msg] $msg
78589d24936Sdan} {1 {bad type "object": must be integer, real, text, blob, or any}}
78689d24936Sdan
78789d24936Sdando_test 17.6.2 {
78889d24936Sdan  list [catch { db function xyz -return ret } msg] $msg
78989d24936Sdan} {1 {option requires an argument: -return}}
79089d24936Sdan
79189d24936Sdando_test 17.6.3 {
79289d24936Sdan  list [catch { db function xyz -n object ret } msg] $msg
7932eeca204Sdrh} {1 {bad option "-n": must be -argcount, -deterministic, -directonly, -innocuous, or -returntype}}
7944f5e80f9Sdrh
795c06ede10Sdrh# 2019-02-28: The "bind_fallback" command.
796c06ede10Sdrh#
797c06ede10Sdrhdo_test 18.100 {
798c06ede10Sdrh  unset -nocomplain bindings abc def ghi jkl mno e01 e02
799c06ede10Sdrh  set bindings(abc) [expr {1+2}]
800c06ede10Sdrh  set bindings(def) {hello}
801c06ede10Sdrh  set bindings(ghi) [expr {3.1415926*1.0}]
802c06ede10Sdrh  proc bind_callback {nm} {
803c06ede10Sdrh    global bindings
804c06ede10Sdrh    set n2 [string range $nm 1 end]
805c06ede10Sdrh    if {[info exists bindings($n2)]} {
806c06ede10Sdrh      return $bindings($n2)
807c06ede10Sdrh    }
808c06ede10Sdrh    if {[string match e* $n2]} {
809c06ede10Sdrh      error "no such variable: $nm"
810c06ede10Sdrh    }
811c06ede10Sdrh    return -code return {}
812c06ede10Sdrh  }
813c06ede10Sdrh  db bind_fallback bind_callback
814c06ede10Sdrh  db eval {SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi)}
815c06ede10Sdrh} {3 integer hello text 3.1415926 real}
816c06ede10Sdrhdo_test 18.110 {
817c06ede10Sdrh  db eval {SELECT quote(@def), typeof(@def)}
818c06ede10Sdrh} {X'68656C6C6F' blob}
819c06ede10Sdrhdo_execsql_test 18.120 {
820c06ede10Sdrh  SELECT typeof($mno);
821c06ede10Sdrh} {null}
822c06ede10Sdrhdo_catchsql_test 18.130 {
823c06ede10Sdrh  SELECT $e01;
824c06ede10Sdrh} {1 {no such variable: $e01}}
825c06ede10Sdrhdo_test 18.140 {
826c06ede10Sdrh  db bind_fallback
827c06ede10Sdrh} {bind_callback}
828c06ede10Sdrhdo_test 18.200 {
829c06ede10Sdrh  db bind_fallback {}
830c06ede10Sdrh  db eval {SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi)}
831c06ede10Sdrh} {{} null {} null {} null}
832c06ede10Sdrhdo_test 18.300 {
833c06ede10Sdrh  unset -nocomplain bindings
834c06ede10Sdrh  proc bind_callback {nm} {lappend ::bindings $nm}
835c06ede10Sdrh  db bind_fallback bind_callback
836c06ede10Sdrh  db eval {SELECT $abc, @def, $ghi(123), :mno}
837c06ede10Sdrh  set bindings
838c06ede10Sdrh} {{$abc} @def {$ghi(123)} :mno}
839c06ede10Sdrhdo_test 18.900 {
840c06ede10Sdrh  set rc [catch {db bind_fallback a b} msg]
841c06ede10Sdrh  lappend rc $msg
842c06ede10Sdrh} {1 {wrong # args: should be "db bind_fallback ?CALLBACK?"}}
843c06ede10Sdrhdo_test 18.910 {
844c06ede10Sdrh  db bind_fallback bind_fallback_does_not_exist
845c06ede10Sdrh} {}
846c06ede10Sdrhdo_catchsql_test 19.911 {
847c06ede10Sdrh  SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi);
848c06ede10Sdrh} {1 {invalid command name "bind_fallback_does_not_exist"}}
849c06ede10Sdrhdb bind_fallback {}
85089d24936Sdan
851bea28c73Sdan#-------------------------------------------------------------------------
852bea28c73Sdando_test 20.0 {
853bea28c73Sdan  db transaction {
854bea28c73Sdan    db close
855bea28c73Sdan  }
856bea28c73Sdan} {}
857bea28c73Sdan
858bea28c73Sdando_test 20.1 {
859bea28c73Sdan  sqlite3 db test.db
860bea28c73Sdan  set rc [catch {
861bea28c73Sdan    db eval {SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3} { db close }
862bea28c73Sdan  } msg]
863bea28c73Sdan  list $rc $msg
864bea28c73Sdan} {1 {invalid command name "db"}}
865bea28c73Sdan
866bea28c73Sdan
867bea28c73Sdanproc closedb {} {
868bea28c73Sdan  db close
869bea28c73Sdan  return 10
870bea28c73Sdan}
871bea28c73Sdanproc func1 {} { return 1 }
872bea28c73Sdan
873bea28c73Sdansqlite3 db test.db
874bea28c73Sdandb func closedb closedb
875bea28c73Sdandb func func1 func1
876bea28c73Sdan
877bea28c73Sdando_test 20.2 {
878bea28c73Sdan  set rc [catch {
879bea28c73Sdan    db eval {
880bea28c73Sdan      SELECT closedb(),func1() UNION ALL SELECT 20,30 UNION ALL SELECT 30,40
881bea28c73Sdan    }
882bea28c73Sdan  } msg]
883bea28c73Sdan  list $rc $msg
884bea28c73Sdan} {0 {10 1 20 30 30 40}}
885bea28c73Sdan
886*be4e3c88Sdrhsqlite3 db :memory:
887*be4e3c88Sdrhdo_test 21.1 {
888*be4e3c88Sdrh  catch {db eval {SELECT 1 2 3;}} msg
889*be4e3c88Sdrh  db erroroffset
890*be4e3c88Sdrh} {9}
891bea28c73Sdan
892*be4e3c88Sdrhfinish_test
893