xref: /sqlite-3.40.0/test/tclsqlite.test (revision a2c8a95b)
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
20960e8c63Sdrhset testdir [file dirname $argv0]
21960e8c63Sdrhsource $testdir/tester.tcl
22960e8c63Sdrh
23960e8c63Sdrh# Check the error messages generated by tclsqlite
24960e8c63Sdrh#
25ef4ac8f9Sdrhif {[sqlite3 -has-codec]} {
269eb9e26bSdrh  set r "sqlite_orig HANDLE FILENAME ?-key CODEC-KEY?"
2722fbcb8dSdrh} else {
28039963adSdrh  set r "sqlite3 HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN?"
2922fbcb8dSdrh}
30960e8c63Sdrhdo_test tcl-1.1 {
31ef4ac8f9Sdrh  set v [catch {sqlite3 bogus} msg]
32df81a25aSdrh  regsub {really_sqlite3} $msg {sqlite3} msg
33960e8c63Sdrh  lappend v $msg
3422fbcb8dSdrh} [list 1 "wrong # args: should be \"$r\""]
35960e8c63Sdrhdo_test tcl-1.2 {
36960e8c63Sdrh  set v [catch {db bogus} msg]
37960e8c63Sdrh  lappend v $msg
38404ca075Sdanielk1977} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, unlock_notify, update_hook, or version}}
39191fadcfSdanielk1977do_test tcl-1.2.1 {
40191fadcfSdanielk1977  set v [catch {db cache bogus} msg]
41191fadcfSdanielk1977  lappend v $msg
42191fadcfSdanielk1977} {1 {bad option "bogus": must be flush or size}}
43191fadcfSdanielk1977do_test tcl-1.2.2 {
44191fadcfSdanielk1977  set v [catch {db cache} msg]
45191fadcfSdanielk1977  lappend v $msg
46191fadcfSdanielk1977} {1 {wrong # args: should be "db cache option ?arg?"}}
47960e8c63Sdrhdo_test tcl-1.3 {
48960e8c63Sdrh  execsql {CREATE TABLE t1(a int, b int)}
49960e8c63Sdrh  execsql {INSERT INTO t1 VALUES(10,20)}
50960e8c63Sdrh  set v [catch {
51960e8c63Sdrh    db eval {SELECT * FROM t1} data {
52960e8c63Sdrh      error "The error message"
53960e8c63Sdrh    }
54960e8c63Sdrh  } msg]
55960e8c63Sdrh  lappend v $msg
56960e8c63Sdrh} {1 {The error message}}
57960e8c63Sdrhdo_test tcl-1.4 {
58960e8c63Sdrh  set v [catch {
59960e8c63Sdrh    db eval {SELECT * FROM t2} data {
60960e8c63Sdrh      error "The error message"
61960e8c63Sdrh    }
62960e8c63Sdrh  } msg]
63960e8c63Sdrh  lappend v $msg
64960e8c63Sdrh} {1 {no such table: t2}}
65960e8c63Sdrhdo_test tcl-1.5 {
66960e8c63Sdrh  set v [catch {
67960e8c63Sdrh    db eval {SELECT * FROM t1} data {
68960e8c63Sdrh      break
69960e8c63Sdrh    }
70960e8c63Sdrh  } msg]
71960e8c63Sdrh  lappend v $msg
72960e8c63Sdrh} {0 {}}
73d65e530bSdrhcatch {expr x*} msg
74960e8c63Sdrhdo_test tcl-1.6 {
75960e8c63Sdrh  set v [catch {
76960e8c63Sdrh    db eval {SELECT * FROM t1} data {
77960e8c63Sdrh      expr x*
78960e8c63Sdrh    }
79960e8c63Sdrh  } msg]
80960e8c63Sdrh  lappend v $msg
81d65e530bSdrh} [list 1 $msg]
820f14e2ebSdrhdo_test tcl-1.7 {
830f14e2ebSdrh  set v [catch {db} msg]
840f14e2ebSdrh  lappend v $msg
850f14e2ebSdrh} {1 {wrong # args: should be "db SUBCOMMAND ..."}}
861211de37Sdrhif {[catch {db auth {}}]==0} {
870f14e2ebSdrh  do_test tcl-1.8 {
880f14e2ebSdrh    set v [catch {db authorizer 1 2 3} msg]
890f14e2ebSdrh    lappend v $msg
900f14e2ebSdrh  } {1 {wrong # args: should be "db authorizer ?CALLBACK?"}}
911211de37Sdrh}
920f14e2ebSdrhdo_test tcl-1.9 {
930f14e2ebSdrh  set v [catch {db busy 1 2 3} msg]
940f14e2ebSdrh  lappend v $msg
950f14e2ebSdrh} {1 {wrong # args: should be "db busy CALLBACK"}}
960f14e2ebSdrhdo_test tcl-1.10 {
970f14e2ebSdrh  set v [catch {db progress 1} msg]
980f14e2ebSdrh  lappend v $msg
990f14e2ebSdrh} {1 {wrong # args: should be "db progress N CALLBACK"}}
1000f14e2ebSdrhdo_test tcl-1.11 {
1010f14e2ebSdrh  set v [catch {db changes xyz} msg]
1020f14e2ebSdrh  lappend v $msg
1030f14e2ebSdrh} {1 {wrong # args: should be "db changes "}}
1040f14e2ebSdrhdo_test tcl-1.12 {
1050f14e2ebSdrh  set v [catch {db commit_hook a b c} msg]
1060f14e2ebSdrh  lappend v $msg
1070f14e2ebSdrh} {1 {wrong # args: should be "db commit_hook ?CALLBACK?"}}
108ccae6026Sdrhifcapable {complete} {
1090f14e2ebSdrh  do_test tcl-1.13 {
1100f14e2ebSdrh    set v [catch {db complete} msg]
1110f14e2ebSdrh    lappend v $msg
1120f14e2ebSdrh  } {1 {wrong # args: should be "db complete SQL"}}
113ccae6026Sdrh}
1140f14e2ebSdrhdo_test tcl-1.14 {
1150f14e2ebSdrh  set v [catch {db eval} msg]
1160f14e2ebSdrh  lappend v $msg
117895d7472Sdrh} {1 {wrong # args: should be "db eval SQL ?ARRAY-NAME? ?SCRIPT?"}}
1180f14e2ebSdrhdo_test tcl-1.15 {
1190f14e2ebSdrh  set v [catch {db function} msg]
1200f14e2ebSdrh  lappend v $msg
121e3602be8Sdrh} {1 {wrong # args: should be "db function NAME [-argcount N] SCRIPT"}}
1227ddad969Sdanielk1977do_test tcl-1.16 {
1230f14e2ebSdrh  set v [catch {db last_insert_rowid xyz} msg]
1240f14e2ebSdrh  lappend v $msg
1250f14e2ebSdrh} {1 {wrong # args: should be "db last_insert_rowid "}}
1267ddad969Sdanielk1977do_test tcl-1.17 {
1270f14e2ebSdrh  set v [catch {db rekey} msg]
1280f14e2ebSdrh  lappend v $msg
1290f14e2ebSdrh} {1 {wrong # args: should be "db rekey KEY"}}
1307ddad969Sdanielk1977do_test tcl-1.18 {
1310f14e2ebSdrh  set v [catch {db timeout} msg]
1320f14e2ebSdrh  lappend v $msg
1330f14e2ebSdrh} {1 {wrong # args: should be "db timeout MILLISECONDS"}}
1347ddad969Sdanielk1977do_test tcl-1.19 {
1350f14e2ebSdrh  set v [catch {db collate} msg]
1360f14e2ebSdrh  lappend v $msg
1370f14e2ebSdrh} {1 {wrong # args: should be "db collate NAME SCRIPT"}}
1387ddad969Sdanielk1977do_test tcl-1.20 {
1390f14e2ebSdrh  set v [catch {db collation_needed} msg]
1400f14e2ebSdrh  lappend v $msg
1410f14e2ebSdrh} {1 {wrong # args: should be "db collation_needed SCRIPT"}}
1427ddad969Sdanielk1977do_test tcl-1.21 {
1430f14e2ebSdrh  set v [catch {db total_changes xyz} msg]
1440f14e2ebSdrh  lappend v $msg
1450f14e2ebSdrh} {1 {wrong # args: should be "db total_changes "}}
1461067fe11Stpoindexdo_test tcl-1.20 {
1471067fe11Stpoindex  set v [catch {db copy} msg]
1481067fe11Stpoindex  lappend v $msg
1491067fe11Stpoindex} {1 {wrong # args: should be "db copy CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?"}}
15095c8a54cSdanielk1977do_test tcl-1.21 {
15195c8a54cSdanielk1977  set v [catch {sqlite3 db2 test.db -vfs nosuchvfs} msg]
15295c8a54cSdanielk1977  lappend v $msg
15395c8a54cSdanielk1977} {1 {no such vfs: nosuchvfs}}
154960e8c63Sdrh
155c275b4eaSdrhcatch {unset ::result}
1566d4abfbeSdrhdo_test tcl-2.1 {
1576d4abfbeSdrh  execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)"
15827188fb5Sdanielk1977} {}
15927188fb5Sdanielk1977ifcapable schema_pragmas {
16027188fb5Sdanielk1977  do_test tcl-2.2 {
1616d4abfbeSdrh    execsql "PRAGMA table_info(t\u0123x)"
1629f6696acSdrh  } "0 a int 0 {} 0 1 b\u1235 float 0 {} 0"
16327188fb5Sdanielk1977}
16427188fb5Sdanielk1977do_test tcl-2.3 {
1656d4abfbeSdrh  execsql "INSERT INTO t\u0123x VALUES(1,2.3)"
1666d4abfbeSdrh  db eval "SELECT * FROM t\u0123x" result break
1676d4abfbeSdrh  set result(*)
1686d4abfbeSdrh} "a b\u1235"
1696d4abfbeSdrh
1706d4abfbeSdrh
1715d9d7576Sdrh# Test the onecolumn method
1725d9d7576Sdrh#
1735d9d7576Sdrhdo_test tcl-3.1 {
1745d9d7576Sdrh  execsql {
1755d9d7576Sdrh    INSERT INTO t1 SELECT a*2, b*2 FROM t1;
1765d9d7576Sdrh    INSERT INTO t1 SELECT a*2+1, b*2+1 FROM t1;
1775d9d7576Sdrh    INSERT INTO t1 SELECT a*2+3, b*2+3 FROM t1;
1785d9d7576Sdrh  }
17922fbcb8dSdrh  set rc [catch {db onecolumn {SELECT * FROM t1 ORDER BY a}} msg]
18022fbcb8dSdrh  lappend rc $msg
18122fbcb8dSdrh} {0 10}
1825d9d7576Sdrhdo_test tcl-3.2 {
1835d9d7576Sdrh  db onecolumn {SELECT * FROM t1 WHERE a<0}
1845d9d7576Sdrh} {}
1855d9d7576Sdrhdo_test tcl-3.3 {
1865d9d7576Sdrh  set rc [catch {db onecolumn} errmsg]
1875d9d7576Sdrh  lappend rc $errmsg
1885d9d7576Sdrh} {1 {wrong # args: should be "db onecolumn SQL"}}
1890f14e2ebSdrhdo_test tcl-3.4 {
1900f14e2ebSdrh  set rc [catch {db onecolumn {SELECT bogus}} errmsg]
1910f14e2ebSdrh  lappend rc $errmsg
1920f14e2ebSdrh} {1 {no such column: bogus}}
1936bf89570Sdrhifcapable {tclvar} {
1941807ce37Sdrh  do_test tcl-3.5 {
1951807ce37Sdrh    set b 50
1961807ce37Sdrh    set rc [catch {db one {SELECT * FROM t1 WHERE b>$b}} msg]
1971807ce37Sdrh    lappend rc $msg
1981807ce37Sdrh  } {0 41}
1991807ce37Sdrh  do_test tcl-3.6 {
2001807ce37Sdrh    set b 500
2011807ce37Sdrh    set rc [catch {db one {SELECT * FROM t1 WHERE b>$b}} msg]
2021807ce37Sdrh    lappend rc $msg
2031807ce37Sdrh  } {0 {}}
2041807ce37Sdrh  do_test tcl-3.7 {
2051807ce37Sdrh    set b 500
2061807ce37Sdrh    set rc [catch {db one {
2071807ce37Sdrh      INSERT INTO t1 VALUES(99,510);
2081807ce37Sdrh      SELECT * FROM t1 WHERE b>$b
2091807ce37Sdrh    }} msg]
2101807ce37Sdrh    lappend rc $msg
2111807ce37Sdrh  } {0 99}
2126bf89570Sdrh}
2136bf89570Sdrhifcapable {!tclvar} {
2146bf89570Sdrh   execsql {INSERT INTO t1 VALUES(99,510)}
2156bf89570Sdrh}
2165d9d7576Sdrh
2170f14e2ebSdrh# Turn the busy handler on and off
2180f14e2ebSdrh#
2190f14e2ebSdrhdo_test tcl-4.1 {
2200f14e2ebSdrh  proc busy_callback {cnt} {
2210f14e2ebSdrh    break
2220f14e2ebSdrh  }
2230f14e2ebSdrh  db busy busy_callback
2240f14e2ebSdrh  db busy
2250f14e2ebSdrh} {busy_callback}
2260f14e2ebSdrhdo_test tcl-4.2 {
2270f14e2ebSdrh  db busy {}
2280f14e2ebSdrh  db busy
2290f14e2ebSdrh} {}
2306d4abfbeSdrh
2316bf89570Sdrhifcapable {tclvar} {
23292febd92Sdrh  # Parsing of TCL variable names within SQL into bound parameters.
23392febd92Sdrh  #
23492febd92Sdrh  do_test tcl-5.1 {
23592febd92Sdrh    execsql {CREATE TABLE t3(a,b,c)}
23692febd92Sdrh    catch {unset x}
2377a1d17f1Sdanielk1977    set x(1) A
2387a1d17f1Sdanielk1977    set x(2) B
23992febd92Sdrh    execsql {
24092febd92Sdrh      INSERT INTO t3 VALUES($::x(1),$::x(2),$::x(3));
24192febd92Sdrh      SELECT * FROM t3
24292febd92Sdrh    }
2437a1d17f1Sdanielk1977  } {A B {}}
24492febd92Sdrh  do_test tcl-5.2 {
24592febd92Sdrh    execsql {
24692febd92Sdrh      SELECT typeof(a), typeof(b), typeof(c) FROM t3
24792febd92Sdrh    }
24892febd92Sdrh  } {text text null}
24992febd92Sdrh  do_test tcl-5.3 {
25092febd92Sdrh    catch {unset x}
25192febd92Sdrh    set x [binary format h12 686900686f00]
25292febd92Sdrh    execsql {
25392febd92Sdrh      UPDATE t3 SET a=$::x;
25492febd92Sdrh    }
25592febd92Sdrh    db eval {
25692febd92Sdrh      SELECT a FROM t3
25792febd92Sdrh    } break
25892febd92Sdrh    binary scan $a h12 adata
25992febd92Sdrh    set adata
26092febd92Sdrh  } {686900686f00}
26192febd92Sdrh  do_test tcl-5.4 {
26292febd92Sdrh    execsql {
26392febd92Sdrh      SELECT typeof(a), typeof(b), typeof(c) FROM t3
26492febd92Sdrh    }
26592febd92Sdrh  } {blob text null}
2666bf89570Sdrh}
26792febd92Sdrh
268fd241b0eSdrh# Operation of "break" and "continue" within row scripts
269fd241b0eSdrh#
270fd241b0eSdrhdo_test tcl-6.1 {
271fd241b0eSdrh  db eval {SELECT * FROM t1} {
272fd241b0eSdrh    break
273fd241b0eSdrh  }
274fd241b0eSdrh  lappend a $b
275fd241b0eSdrh} {10 20}
276fd241b0eSdrhdo_test tcl-6.2 {
277fd241b0eSdrh  set cnt 0
278fd241b0eSdrh  db eval {SELECT * FROM t1} {
279fd241b0eSdrh    if {$a>40} continue
280fd241b0eSdrh    incr cnt
281fd241b0eSdrh  }
282fd241b0eSdrh  set cnt
283fd241b0eSdrh} {4}
284fd241b0eSdrhdo_test tcl-6.3 {
285fd241b0eSdrh  set cnt 0
286fd241b0eSdrh  db eval {SELECT * FROM t1} {
287fd241b0eSdrh    if {$a<40} continue
288fd241b0eSdrh    incr cnt
289fd241b0eSdrh  }
290fd241b0eSdrh  set cnt
291fd241b0eSdrh} {5}
292fd241b0eSdrhdo_test tcl-6.4 {
293fd241b0eSdrh  proc return_test {x} {
294fd241b0eSdrh    db eval {SELECT * FROM t1} {
295fd241b0eSdrh      if {$a==$x} {return $b}
296fd241b0eSdrh    }
297fd241b0eSdrh  }
298fd241b0eSdrh  return_test 10
299fd241b0eSdrh} 20
300fd241b0eSdrhdo_test tcl-6.5 {
301fd241b0eSdrh  return_test 20
302fd241b0eSdrh} 40
303fd241b0eSdrhdo_test tcl-6.6 {
304fd241b0eSdrh  return_test 99
305fd241b0eSdrh} 510
306fd241b0eSdrhdo_test tcl-6.7 {
307fd241b0eSdrh  return_test 0
308fd241b0eSdrh} {}
309fd241b0eSdrh
3104397de57Sdanielk1977do_test tcl-7.1 {
3114397de57Sdanielk1977  db version
3124397de57Sdanielk1977  expr 0
3134397de57Sdanielk1977} {0}
3144397de57Sdanielk1977
31555c45f2eSdanielk1977# modify and reset the NULL representation
31655c45f2eSdanielk1977#
31755c45f2eSdanielk1977do_test tcl-8.1 {
31855c45f2eSdanielk1977  db nullvalue NaN
31955c45f2eSdanielk1977  execsql {INSERT INTO t1 VALUES(30,NULL)}
32055c45f2eSdanielk1977  db eval {SELECT * FROM t1 WHERE b IS NULL}
32155c45f2eSdanielk1977} {30 NaN}
32255c45f2eSdanielk1977do_test tcl-8.2 {
32355c45f2eSdanielk1977  db nullvalue NULL
32455c45f2eSdanielk1977  db nullvalue
32555c45f2eSdanielk1977} {NULL}
32655c45f2eSdanielk1977do_test tcl-8.3 {
32755c45f2eSdanielk1977  db nullvalue {}
32855c45f2eSdanielk1977  db eval {SELECT * FROM t1 WHERE b IS NULL}
32955c45f2eSdanielk1977} {30 {}}
33055c45f2eSdanielk1977
331c7f269d5Sdrh# Test the return type of user-defined functions
332c7f269d5Sdrh#
333c7f269d5Sdrhdo_test tcl-9.1 {
334c7f269d5Sdrh  db function ret_str {return "hi"}
335c7f269d5Sdrh  execsql {SELECT typeof(ret_str())}
336c7f269d5Sdrh} {text}
337c7f269d5Sdrhdo_test tcl-9.2 {
3389645d8d4Sdrh  db function ret_dbl {return [expr {rand()*0.5}]}
339c7f269d5Sdrh  execsql {SELECT typeof(ret_dbl())}
340c7f269d5Sdrh} {real}
341c7f269d5Sdrhdo_test tcl-9.3 {
3429645d8d4Sdrh  db function ret_int {return [expr {int(rand()*200)}]}
343c7f269d5Sdrh  execsql {SELECT typeof(ret_int())}
344c7f269d5Sdrh} {integer}
345c7f269d5Sdrh
346d1e4733dSdrh# Recursive calls to the same user-defined function
347d1e4733dSdrh#
3483bdca9c9Sdanielk1977ifcapable tclvar {
349d1e4733dSdrh  do_test tcl-9.10 {
350d1e4733dSdrh    proc userfunc_r1 {n} {
351d1e4733dSdrh      if {$n<=0} {return 0}
352d1e4733dSdrh      set nm1 [expr {$n-1}]
353d1e4733dSdrh      return [expr {[db eval {SELECT r1($nm1)}]+$n}]
354d1e4733dSdrh    }
355d1e4733dSdrh    db function r1 userfunc_r1
356d1e4733dSdrh    execsql {SELECT r1(10)}
357d1e4733dSdrh  } {55}
358d1e4733dSdrh  do_test tcl-9.11 {
359d1e4733dSdrh    execsql {SELECT r1(100)}
360d1e4733dSdrh  } {5050}
3613bdca9c9Sdanielk1977}
362d1e4733dSdrh
363b5555e7eSdrh# Tests for the new transaction method
364b5555e7eSdrh#
365b5555e7eSdrhdo_test tcl-10.1 {
366b5555e7eSdrh  db transaction {}
367b5555e7eSdrh} {}
368b5555e7eSdrhdo_test tcl-10.2 {
369b5555e7eSdrh  db transaction deferred {}
370b5555e7eSdrh} {}
371b5555e7eSdrhdo_test tcl-10.3 {
372b5555e7eSdrh  db transaction immediate {}
373b5555e7eSdrh} {}
374b5555e7eSdrhdo_test tcl-10.4 {
375b5555e7eSdrh  db transaction exclusive {}
376b5555e7eSdrh} {}
377b5555e7eSdrhdo_test tcl-10.5 {
378b5555e7eSdrh  set rc [catch {db transaction xyzzy {}} msg]
379b5555e7eSdrh  lappend rc $msg
380b5555e7eSdrh} {1 {bad transaction type "xyzzy": must be deferred, exclusive, or immediate}}
381b5555e7eSdrhdo_test tcl-10.6 {
382b5555e7eSdrh  set rc [catch {db transaction {error test-error}} msg]
383b5555e7eSdrh  lappend rc $msg
384b5555e7eSdrh} {1 test-error}
385b5555e7eSdrhdo_test tcl-10.7 {
386b5555e7eSdrh  db transaction {
387b5555e7eSdrh    db eval {CREATE TABLE t4(x)}
388b5555e7eSdrh    db transaction {
389b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(1)}
390b5555e7eSdrh    }
391b5555e7eSdrh  }
392b5555e7eSdrh  db eval {SELECT * FROM t4}
393b5555e7eSdrh} 1
394b5555e7eSdrhdo_test tcl-10.8 {
395b5555e7eSdrh  catch {
396b5555e7eSdrh    db transaction {
397b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(2)}
398b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(3)}
399b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(4)}
400b5555e7eSdrh      error test-error
401b5555e7eSdrh    }
402b5555e7eSdrh  }
403b5555e7eSdrh  db eval {SELECT * FROM t4}
404b5555e7eSdrh} 1
405b5555e7eSdrhdo_test tcl-10.9 {
406b5555e7eSdrh  db transaction {
407b5555e7eSdrh    db eval {INSERT INTO t4 VALUES(2)}
408b5555e7eSdrh    catch {
409b5555e7eSdrh      db transaction {
410b5555e7eSdrh        db eval {INSERT INTO t4 VALUES(3)}
411b5555e7eSdrh        db eval {INSERT INTO t4 VALUES(4)}
412b5555e7eSdrh        error test-error
413b5555e7eSdrh      }
414b5555e7eSdrh    }
415b5555e7eSdrh  }
416b5555e7eSdrh  db eval {SELECT * FROM t4}
417cd38d520Sdanielk1977} {1 2}
418b5555e7eSdrhdo_test tcl-10.10 {
419b5555e7eSdrh  for {set i 0} {$i<1} {incr i} {
420b5555e7eSdrh    db transaction {
421b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(5)}
422b5555e7eSdrh      continue
423b5555e7eSdrh    }
424cd38d520Sdanielk1977    error "This line should not be run"
425b5555e7eSdrh  }
426b5555e7eSdrh  db eval {SELECT * FROM t4}
427cd38d520Sdanielk1977} {1 2 5}
428b5555e7eSdrhdo_test tcl-10.11 {
429b5555e7eSdrh  for {set i 0} {$i<10} {incr i} {
430b5555e7eSdrh    db transaction {
431b5555e7eSdrh      db eval {INSERT INTO t4 VALUES(6)}
432b5555e7eSdrh      break
433b5555e7eSdrh    }
434b5555e7eSdrh  }
435b5555e7eSdrh  db eval {SELECT * FROM t4}
436cd38d520Sdanielk1977} {1 2 5 6}
437b5555e7eSdrhdo_test tcl-10.12 {
438b5555e7eSdrh  set rc [catch {
439b5555e7eSdrh    for {set i 0} {$i<10} {incr i} {
440b5555e7eSdrh      db transaction {
441b5555e7eSdrh        db eval {INSERT INTO t4 VALUES(7)}
442b5555e7eSdrh        return
443b5555e7eSdrh      }
444b5555e7eSdrh    }
445b5555e7eSdrh  }]
446b5555e7eSdrh} {2}
447b5555e7eSdrhdo_test tcl-10.13 {
448b5555e7eSdrh  db eval {SELECT * FROM t4}
449cd38d520Sdanielk1977} {1 2 5 6 7}
450cd38d520Sdanielk1977
451cd38d520Sdanielk1977# Now test that [db transaction] commands may be nested with
452cd38d520Sdanielk1977# the expected results.
453cd38d520Sdanielk1977#
454cd38d520Sdanielk1977do_test tcl-10.14 {
455cd38d520Sdanielk1977  db transaction {
456cd38d520Sdanielk1977    db eval {
457cd38d520Sdanielk1977      DELETE FROM t4;
458cd38d520Sdanielk1977      INSERT INTO t4 VALUES('one');
459cd38d520Sdanielk1977    }
460cd38d520Sdanielk1977
461cd38d520Sdanielk1977    catch {
462cd38d520Sdanielk1977      db transaction {
463cd38d520Sdanielk1977        db eval { INSERT INTO t4 VALUES('two') }
464cd38d520Sdanielk1977        db transaction {
465cd38d520Sdanielk1977          db eval { INSERT INTO t4 VALUES('three') }
466cd38d520Sdanielk1977          error "throw an error!"
467cd38d520Sdanielk1977        }
468cd38d520Sdanielk1977      }
469cd38d520Sdanielk1977    }
470cd38d520Sdanielk1977  }
471cd38d520Sdanielk1977
472cd38d520Sdanielk1977  db eval {SELECT * FROM t4}
473cd38d520Sdanielk1977} {one}
474cd38d520Sdanielk1977do_test tcl-10.15 {
475cd38d520Sdanielk1977  # Make sure a transaction has not been left open.
476cd38d520Sdanielk1977  db eval {BEGIN ; COMMIT}
477cd38d520Sdanielk1977} {}
478cd38d520Sdanielk1977do_test tcl-10.16 {
479cd38d520Sdanielk1977  db transaction {
480cd38d520Sdanielk1977    db eval { INSERT INTO t4 VALUES('two'); }
481cd38d520Sdanielk1977    db transaction {
482cd38d520Sdanielk1977      db eval { INSERT INTO t4 VALUES('three') }
483cd38d520Sdanielk1977      db transaction {
484cd38d520Sdanielk1977        db eval { INSERT INTO t4 VALUES('four') }
485cd38d520Sdanielk1977      }
486cd38d520Sdanielk1977    }
487cd38d520Sdanielk1977  }
488cd38d520Sdanielk1977  db eval {SELECT * FROM t4}
489cd38d520Sdanielk1977} {one two three four}
490cd38d520Sdanielk1977do_test tcl-10.17 {
491cd38d520Sdanielk1977  catch {
492cd38d520Sdanielk1977    db transaction {
493cd38d520Sdanielk1977      db eval { INSERT INTO t4 VALUES('A'); }
494cd38d520Sdanielk1977      db transaction {
495cd38d520Sdanielk1977        db eval { INSERT INTO t4 VALUES('B') }
496cd38d520Sdanielk1977        db transaction {
497cd38d520Sdanielk1977          db eval { INSERT INTO t4 VALUES('C') }
498cd38d520Sdanielk1977          error "throw an error!"
499cd38d520Sdanielk1977        }
500cd38d520Sdanielk1977      }
501cd38d520Sdanielk1977    }
502cd38d520Sdanielk1977  }
503cd38d520Sdanielk1977  db eval {SELECT * FROM t4}
504cd38d520Sdanielk1977} {one two three four}
505cd38d520Sdanielk1977do_test tcl-10.18 {
506cd38d520Sdanielk1977  # Make sure a transaction has not been left open.
507cd38d520Sdanielk1977  db eval {BEGIN ; COMMIT}
508cd38d520Sdanielk1977} {}
509cd38d520Sdanielk1977
510cd38d520Sdanielk1977# Mess up a [db transaction] command by locking the database using a
511cd38d520Sdanielk1977# second connection when it tries to commit. Make sure the transaction
512cd38d520Sdanielk1977# is not still open after the "database is locked" exception is thrown.
513cd38d520Sdanielk1977#
514cd38d520Sdanielk1977do_test tcl-10.18 {
515cd38d520Sdanielk1977  sqlite3 db2 test.db
516cd38d520Sdanielk1977  db2 eval {
517cd38d520Sdanielk1977    BEGIN;
518cd38d520Sdanielk1977    SELECT * FROM sqlite_master;
519cd38d520Sdanielk1977  }
520cd38d520Sdanielk1977
521cd38d520Sdanielk1977  set rc [catch {
522cd38d520Sdanielk1977    db transaction {
523cd38d520Sdanielk1977      db eval {INSERT INTO t4 VALUES('five')}
524cd38d520Sdanielk1977    }
525cd38d520Sdanielk1977  } msg]
526cd38d520Sdanielk1977  list $rc $msg
527cd38d520Sdanielk1977} {1 {database is locked}}
528cd38d520Sdanielk1977do_test tcl-10.19 {
529cd38d520Sdanielk1977  db eval {BEGIN ; COMMIT}
530cd38d520Sdanielk1977} {}
531cd38d520Sdanielk1977
532cd38d520Sdanielk1977# Thwart a [db transaction] command by locking the database using a
533cd38d520Sdanielk1977# second connection with "BEGIN EXCLUSIVE". Make sure no transaction is
534cd38d520Sdanielk1977# open after the "database is locked" exception is thrown.
535cd38d520Sdanielk1977#
536cd38d520Sdanielk1977do_test tcl-10.20 {
537cd38d520Sdanielk1977  db2 eval {
538cd38d520Sdanielk1977    COMMIT;
539cd38d520Sdanielk1977    BEGIN EXCLUSIVE;
540cd38d520Sdanielk1977  }
541cd38d520Sdanielk1977  set rc [catch {
542cd38d520Sdanielk1977    db transaction {
543cd38d520Sdanielk1977      db eval {INSERT INTO t4 VALUES('five')}
544cd38d520Sdanielk1977    }
545cd38d520Sdanielk1977  } msg]
546cd38d520Sdanielk1977  list $rc $msg
547cd38d520Sdanielk1977} {1 {database is locked}}
548cd38d520Sdanielk1977do_test tcl-10.21 {
549cd38d520Sdanielk1977  db2 close
550cd38d520Sdanielk1977  db eval {BEGIN ; COMMIT}
551cd38d520Sdanielk1977} {}
552cd38d520Sdanielk1977do_test tcl-10.22 {
553cd38d520Sdanielk1977  sqlite3 db2 test.db
554cd38d520Sdanielk1977  db transaction exclusive {
555cd38d520Sdanielk1977    catch { db2 eval {SELECT * FROM sqlite_master} } msg
556cd38d520Sdanielk1977    set msg "db2: $msg"
557cd38d520Sdanielk1977  }
558cd38d520Sdanielk1977  set msg
559cd38d520Sdanielk1977} {db2: database is locked}
560cd38d520Sdanielk1977db2 close
561c7f269d5Sdrh
56297f2ebc1Sdrhdo_test tcl-11.1 {
563cd38d520Sdanielk1977  db eval {INSERT INTO t4 VALUES(6)}
564cd38d520Sdanielk1977  db exists {SELECT x,x*2,x+x FROM t4 WHERE x==6}
56597f2ebc1Sdrh} {1}
56697f2ebc1Sdrhdo_test tcl-11.2 {
567cd38d520Sdanielk1977  db exists {SELECT 0 FROM t4 WHERE x==6}
56897f2ebc1Sdrh} {1}
56997f2ebc1Sdrhdo_test tcl-11.3 {
57097f2ebc1Sdrh  db exists {SELECT 1 FROM t4 WHERE x==8}
57197f2ebc1Sdrh} {0}
572*a2c8a95bSdrhdo_test tcl-11.3.1 {
573*a2c8a95bSdrh  tcl_objproc db exists {SELECT 1 FROM t4 WHERE x==8}
574*a2c8a95bSdrh} {0}
57597f2ebc1Sdrh
576161fb796Sdanielk1977do_test tcl-12.1 {
577161fb796Sdanielk1977  unset -nocomplain a b c version
578161fb796Sdanielk1977  set version [db version]
579161fb796Sdanielk1977  scan $version "%d.%d.%d" a b c
580161fb796Sdanielk1977  expr $a*1000000 + $b*1000 + $c
581161fb796Sdanielk1977} [sqlite3_libversion_number]
582161fb796Sdanielk1977
5834f5e80f9Sdrh
5844f5e80f9Sdrh# Check to see that when bindings of the form @aaa are used instead
5851c747819Sdrh# of $aaa, that objects are treated as bytearray and are inserted
5861c747819Sdrh# as BLOBs.
5874f5e80f9Sdrh#
5884152e677Sdanielk1977ifcapable tclvar {
5894f5e80f9Sdrh  do_test tcl-13.1 {
5904f5e80f9Sdrh    db eval {CREATE TABLE t5(x BLOB)}
5914f5e80f9Sdrh    set x abc123
5924f5e80f9Sdrh    db eval {INSERT INTO t5 VALUES($x)}
5934f5e80f9Sdrh    db eval {SELECT typeof(x) FROM t5}
5944f5e80f9Sdrh  } {text}
5954f5e80f9Sdrh  do_test tcl-13.2 {
5964f5e80f9Sdrh    binary scan $x H notUsed
5974f5e80f9Sdrh    db eval {
5984f5e80f9Sdrh      DELETE FROM t5;
5994f5e80f9Sdrh      INSERT INTO t5 VALUES($x);
6004f5e80f9Sdrh      SELECT typeof(x) FROM t5;
6014f5e80f9Sdrh    }
6024f5e80f9Sdrh  } {text}
6034f5e80f9Sdrh  do_test tcl-13.3 {
6044f5e80f9Sdrh    db eval {
6054f5e80f9Sdrh      DELETE FROM t5;
6064f5e80f9Sdrh      INSERT INTO t5 VALUES(@x);
6074f5e80f9Sdrh      SELECT typeof(x) FROM t5;
6084f5e80f9Sdrh    }
6094f5e80f9Sdrh  } {blob}
6101c747819Sdrh  do_test tcl-13.4 {
6111c747819Sdrh    set y 1234
6121c747819Sdrh    db eval {
6131c747819Sdrh      DELETE FROM t5;
6141c747819Sdrh      INSERT INTO t5 VALUES(@y);
6151c747819Sdrh      SELECT hex(x), typeof(x) FROM t5
6161c747819Sdrh    }
6171c747819Sdrh  } {31323334 blob}
6184152e677Sdanielk1977}
6191c747819Sdrh
6204f5e80f9Sdrh
621960e8c63Sdrhfinish_test
622