PageRenderTime 67ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/test/tclsqlite.test

https://bitbucket.org/aware/sqlite
Unknown | 641 lines | 614 code | 27 blank | 0 comment | 0 complexity | 2cbfb00afd319c2e6871fe286f936b94 MD5 | raw file
  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 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. #
  18. # $Id:$
  19. set testdir [file dirname $argv0]
  20. source $testdir/tester.tcl
  21. # Check the error messages generated by tclsqlite
  22. #
  23. if {[sqlite3 -has-codec]} {
  24. set r "sqlite_orig HANDLE FILENAME ?-key CODEC-KEY?"
  25. } else {
  26. set r "sqlite_orig HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
  27. }
  28. do_test tcl-1.1 {
  29. set v [catch {sqlite3 bogus} msg]
  30. regsub {really_sqlite3} $msg {sqlite3} msg
  31. lappend v $msg
  32. } [list 1 "wrong # args: should be \"$r\""]
  33. do_test tcl-1.2 {
  34. set v [catch {db bogus} msg]
  35. lappend v $msg
  36. } {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, version, or wal_hook}}
  37. do_test tcl-1.2.1 {
  38. set v [catch {db cache bogus} msg]
  39. lappend v $msg
  40. } {1 {bad option "bogus": must be flush or size}}
  41. do_test tcl-1.2.2 {
  42. set v [catch {db cache} msg]
  43. lappend v $msg
  44. } {1 {wrong # args: should be "db cache option ?arg?"}}
  45. do_test tcl-1.3 {
  46. execsql {CREATE TABLE t1(a int, b int)}
  47. execsql {INSERT INTO t1 VALUES(10,20)}
  48. set v [catch {
  49. db eval {SELECT * FROM t1} data {
  50. error "The error message"
  51. }
  52. } msg]
  53. lappend v $msg
  54. } {1 {The error message}}
  55. do_test tcl-1.4 {
  56. set v [catch {
  57. db eval {SELECT * FROM t2} data {
  58. error "The error message"
  59. }
  60. } msg]
  61. lappend v $msg
  62. } {1 {no such table: t2}}
  63. do_test tcl-1.5 {
  64. set v [catch {
  65. db eval {SELECT * FROM t1} data {
  66. break
  67. }
  68. } msg]
  69. lappend v $msg
  70. } {0 {}}
  71. catch {expr x*} msg
  72. do_test tcl-1.6 {
  73. set v [catch {
  74. db eval {SELECT * FROM t1} data {
  75. expr x*
  76. }
  77. } msg]
  78. lappend v $msg
  79. } [list 1 $msg]
  80. do_test tcl-1.7 {
  81. set v [catch {db} msg]
  82. lappend v $msg
  83. } {1 {wrong # args: should be "db SUBCOMMAND ..."}}
  84. if {[catch {db auth {}}]==0} {
  85. do_test tcl-1.8 {
  86. set v [catch {db authorizer 1 2 3} msg]
  87. lappend v $msg
  88. } {1 {wrong # args: should be "db authorizer ?CALLBACK?"}}
  89. }
  90. do_test tcl-1.9 {
  91. set v [catch {db busy 1 2 3} msg]
  92. lappend v $msg
  93. } {1 {wrong # args: should be "db busy CALLBACK"}}
  94. do_test tcl-1.10 {
  95. set v [catch {db progress 1} msg]
  96. lappend v $msg
  97. } {1 {wrong # args: should be "db progress N CALLBACK"}}
  98. do_test tcl-1.11 {
  99. set v [catch {db changes xyz} msg]
  100. lappend v $msg
  101. } {1 {wrong # args: should be "db changes "}}
  102. do_test tcl-1.12 {
  103. set v [catch {db commit_hook a b c} msg]
  104. lappend v $msg
  105. } {1 {wrong # args: should be "db commit_hook ?CALLBACK?"}}
  106. ifcapable {complete} {
  107. do_test tcl-1.13 {
  108. set v [catch {db complete} msg]
  109. lappend v $msg
  110. } {1 {wrong # args: should be "db complete SQL"}}
  111. }
  112. do_test tcl-1.14 {
  113. set v [catch {db eval} msg]
  114. lappend v $msg
  115. } {1 {wrong # args: should be "db eval SQL ?ARRAY-NAME? ?SCRIPT?"}}
  116. do_test tcl-1.15 {
  117. set v [catch {db function} msg]
  118. lappend v $msg
  119. } {1 {wrong # args: should be "db function NAME [-argcount N] SCRIPT"}}
  120. do_test tcl-1.16 {
  121. set v [catch {db last_insert_rowid xyz} msg]
  122. lappend v $msg
  123. } {1 {wrong # args: should be "db last_insert_rowid "}}
  124. do_test tcl-1.17 {
  125. set v [catch {db rekey} msg]
  126. lappend v $msg
  127. } {1 {wrong # args: should be "db rekey KEY"}}
  128. do_test tcl-1.18 {
  129. set v [catch {db timeout} msg]
  130. lappend v $msg
  131. } {1 {wrong # args: should be "db timeout MILLISECONDS"}}
  132. do_test tcl-1.19 {
  133. set v [catch {db collate} msg]
  134. lappend v $msg
  135. } {1 {wrong # args: should be "db collate NAME SCRIPT"}}
  136. do_test tcl-1.20 {
  137. set v [catch {db collation_needed} msg]
  138. lappend v $msg
  139. } {1 {wrong # args: should be "db collation_needed SCRIPT"}}
  140. do_test tcl-1.21 {
  141. set v [catch {db total_changes xyz} msg]
  142. lappend v $msg
  143. } {1 {wrong # args: should be "db total_changes "}}
  144. do_test tcl-1.20 {
  145. set v [catch {db copy} msg]
  146. lappend v $msg
  147. } {1 {wrong # args: should be "db copy CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?"}}
  148. do_test tcl-1.21 {
  149. set v [catch {sqlite3 db2 test.db -vfs nosuchvfs} msg]
  150. lappend v $msg
  151. } {1 {no such vfs: nosuchvfs}}
  152. catch {unset ::result}
  153. do_test tcl-2.1 {
  154. execsql "CREATE TABLE t\u0123x(a int, b\u1235 float)"
  155. } {}
  156. ifcapable schema_pragmas {
  157. do_test tcl-2.2 {
  158. execsql "PRAGMA table_info(t\u0123x)"
  159. } "0 a int 0 {} 0 1 b\u1235 float 0 {} 0"
  160. }
  161. do_test tcl-2.3 {
  162. execsql "INSERT INTO t\u0123x VALUES(1,2.3)"
  163. db eval "SELECT * FROM t\u0123x" result break
  164. set result(*)
  165. } "a b\u1235"
  166. # Test the onecolumn method
  167. #
  168. do_test tcl-3.1 {
  169. execsql {
  170. INSERT INTO t1 SELECT a*2, b*2 FROM t1;
  171. INSERT INTO t1 SELECT a*2+1, b*2+1 FROM t1;
  172. INSERT INTO t1 SELECT a*2+3, b*2+3 FROM t1;
  173. }
  174. set rc [catch {db onecolumn {SELECT * FROM t1 ORDER BY a}} msg]
  175. lappend rc $msg
  176. } {0 10}
  177. do_test tcl-3.2 {
  178. db onecolumn {SELECT * FROM t1 WHERE a<0}
  179. } {}
  180. do_test tcl-3.3 {
  181. set rc [catch {db onecolumn} errmsg]
  182. lappend rc $errmsg
  183. } {1 {wrong # args: should be "db onecolumn SQL"}}
  184. do_test tcl-3.4 {
  185. set rc [catch {db onecolumn {SELECT bogus}} errmsg]
  186. lappend rc $errmsg
  187. } {1 {no such column: bogus}}
  188. ifcapable {tclvar} {
  189. do_test tcl-3.5 {
  190. set b 50
  191. set rc [catch {db one {SELECT * FROM t1 WHERE b>$b}} msg]
  192. lappend rc $msg
  193. } {0 41}
  194. do_test tcl-3.6 {
  195. set b 500
  196. set rc [catch {db one {SELECT * FROM t1 WHERE b>$b}} msg]
  197. lappend rc $msg
  198. } {0 {}}
  199. do_test tcl-3.7 {
  200. set b 500
  201. set rc [catch {db one {
  202. INSERT INTO t1 VALUES(99,510);
  203. SELECT * FROM t1 WHERE b>$b
  204. }} msg]
  205. lappend rc $msg
  206. } {0 99}
  207. }
  208. ifcapable {!tclvar} {
  209. execsql {INSERT INTO t1 VALUES(99,510)}
  210. }
  211. # Turn the busy handler on and off
  212. #
  213. do_test tcl-4.1 {
  214. proc busy_callback {cnt} {
  215. break
  216. }
  217. db busy busy_callback
  218. db busy
  219. } {busy_callback}
  220. do_test tcl-4.2 {
  221. db busy {}
  222. db busy
  223. } {}
  224. ifcapable {tclvar} {
  225. # Parsing of TCL variable names within SQL into bound parameters.
  226. #
  227. do_test tcl-5.1 {
  228. execsql {CREATE TABLE t3(a,b,c)}
  229. catch {unset x}
  230. set x(1) A
  231. set x(2) B
  232. execsql {
  233. INSERT INTO t3 VALUES($::x(1),$::x(2),$::x(3));
  234. SELECT * FROM t3
  235. }
  236. } {A B {}}
  237. do_test tcl-5.2 {
  238. execsql {
  239. SELECT typeof(a), typeof(b), typeof(c) FROM t3
  240. }
  241. } {text text null}
  242. do_test tcl-5.3 {
  243. catch {unset x}
  244. set x [binary format h12 686900686f00]
  245. execsql {
  246. UPDATE t3 SET a=$::x;
  247. }
  248. db eval {
  249. SELECT a FROM t3
  250. } break
  251. binary scan $a h12 adata
  252. set adata
  253. } {686900686f00}
  254. do_test tcl-5.4 {
  255. execsql {
  256. SELECT typeof(a), typeof(b), typeof(c) FROM t3
  257. }
  258. } {blob text null}
  259. }
  260. # Operation of "break" and "continue" within row scripts
  261. #
  262. do_test tcl-6.1 {
  263. db eval {SELECT * FROM t1} {
  264. break
  265. }
  266. lappend a $b
  267. } {10 20}
  268. do_test tcl-6.2 {
  269. set cnt 0
  270. db eval {SELECT * FROM t1} {
  271. if {$a>40} continue
  272. incr cnt
  273. }
  274. set cnt
  275. } {4}
  276. do_test tcl-6.3 {
  277. set cnt 0
  278. db eval {SELECT * FROM t1} {
  279. if {$a<40} continue
  280. incr cnt
  281. }
  282. set cnt
  283. } {5}
  284. do_test tcl-6.4 {
  285. proc return_test {x} {
  286. db eval {SELECT * FROM t1} {
  287. if {$a==$x} {return $b}
  288. }
  289. }
  290. return_test 10
  291. } 20
  292. do_test tcl-6.5 {
  293. return_test 20
  294. } 40
  295. do_test tcl-6.6 {
  296. return_test 99
  297. } 510
  298. do_test tcl-6.7 {
  299. return_test 0
  300. } {}
  301. do_test tcl-7.1 {
  302. db version
  303. expr 0
  304. } {0}
  305. # modify and reset the NULL representation
  306. #
  307. do_test tcl-8.1 {
  308. db nullvalue NaN
  309. execsql {INSERT INTO t1 VALUES(30,NULL)}
  310. db eval {SELECT * FROM t1 WHERE b IS NULL}
  311. } {30 NaN}
  312. proc concatFunc args {return [join $args {}]}
  313. do_test tcl-8.2 {
  314. db function concat concatFunc
  315. db eval {SELECT concat('a', b, 'z') FROM t1 WHERE b is NULL}
  316. } {aNaNz}
  317. do_test tcl-8.3 {
  318. db nullvalue NULL
  319. db nullvalue
  320. } {NULL}
  321. do_test tcl-8.4 {
  322. db nullvalue {}
  323. db eval {SELECT * FROM t1 WHERE b IS NULL}
  324. } {30 {}}
  325. do_test tcl-8.5 {
  326. db function concat concatFunc
  327. db eval {SELECT concat('a', b, 'z') FROM t1 WHERE b is NULL}
  328. } {az}
  329. # Test the return type of user-defined functions
  330. #
  331. do_test tcl-9.1 {
  332. db function ret_str {return "hi"}
  333. execsql {SELECT typeof(ret_str())}
  334. } {text}
  335. do_test tcl-9.2 {
  336. db function ret_dbl {return [expr {rand()*0.5}]}
  337. execsql {SELECT typeof(ret_dbl())}
  338. } {real}
  339. do_test tcl-9.3 {
  340. db function ret_int {return [expr {int(rand()*200)}]}
  341. execsql {SELECT typeof(ret_int())}
  342. } {integer}
  343. # Recursive calls to the same user-defined function
  344. #
  345. ifcapable tclvar {
  346. do_test tcl-9.10 {
  347. proc userfunc_r1 {n} {
  348. if {$n<=0} {return 0}
  349. set nm1 [expr {$n-1}]
  350. return [expr {[db eval {SELECT r1($nm1)}]+$n}]
  351. }
  352. db function r1 userfunc_r1
  353. execsql {SELECT r1(10)}
  354. } {55}
  355. do_test tcl-9.11 {
  356. execsql {SELECT r1(100)}
  357. } {5050}
  358. }
  359. # Tests for the new transaction method
  360. #
  361. do_test tcl-10.1 {
  362. db transaction {}
  363. } {}
  364. do_test tcl-10.2 {
  365. db transaction deferred {}
  366. } {}
  367. do_test tcl-10.3 {
  368. db transaction immediate {}
  369. } {}
  370. do_test tcl-10.4 {
  371. db transaction exclusive {}
  372. } {}
  373. do_test tcl-10.5 {
  374. set rc [catch {db transaction xyzzy {}} msg]
  375. lappend rc $msg
  376. } {1 {bad transaction type "xyzzy": must be deferred, exclusive, or immediate}}
  377. do_test tcl-10.6 {
  378. set rc [catch {db transaction {error test-error}} msg]
  379. lappend rc $msg
  380. } {1 test-error}
  381. do_test tcl-10.7 {
  382. db transaction {
  383. db eval {CREATE TABLE t4(x)}
  384. db transaction {
  385. db eval {INSERT INTO t4 VALUES(1)}
  386. }
  387. }
  388. db eval {SELECT * FROM t4}
  389. } 1
  390. do_test tcl-10.8 {
  391. catch {
  392. db transaction {
  393. db eval {INSERT INTO t4 VALUES(2)}
  394. db eval {INSERT INTO t4 VALUES(3)}
  395. db eval {INSERT INTO t4 VALUES(4)}
  396. error test-error
  397. }
  398. }
  399. db eval {SELECT * FROM t4}
  400. } 1
  401. do_test tcl-10.9 {
  402. db transaction {
  403. db eval {INSERT INTO t4 VALUES(2)}
  404. catch {
  405. db transaction {
  406. db eval {INSERT INTO t4 VALUES(3)}
  407. db eval {INSERT INTO t4 VALUES(4)}
  408. error test-error
  409. }
  410. }
  411. }
  412. db eval {SELECT * FROM t4}
  413. } {1 2}
  414. do_test tcl-10.10 {
  415. for {set i 0} {$i<1} {incr i} {
  416. db transaction {
  417. db eval {INSERT INTO t4 VALUES(5)}
  418. continue
  419. }
  420. error "This line should not be run"
  421. }
  422. db eval {SELECT * FROM t4}
  423. } {1 2 5}
  424. do_test tcl-10.11 {
  425. for {set i 0} {$i<10} {incr i} {
  426. db transaction {
  427. db eval {INSERT INTO t4 VALUES(6)}
  428. break
  429. }
  430. }
  431. db eval {SELECT * FROM t4}
  432. } {1 2 5 6}
  433. do_test tcl-10.12 {
  434. set rc [catch {
  435. for {set i 0} {$i<10} {incr i} {
  436. db transaction {
  437. db eval {INSERT INTO t4 VALUES(7)}
  438. return
  439. }
  440. }
  441. }]
  442. } {2}
  443. do_test tcl-10.13 {
  444. db eval {SELECT * FROM t4}
  445. } {1 2 5 6 7}
  446. # Now test that [db transaction] commands may be nested with
  447. # the expected results.
  448. #
  449. do_test tcl-10.14 {
  450. db transaction {
  451. db eval {
  452. DELETE FROM t4;
  453. INSERT INTO t4 VALUES('one');
  454. }
  455. catch {
  456. db transaction {
  457. db eval { INSERT INTO t4 VALUES('two') }
  458. db transaction {
  459. db eval { INSERT INTO t4 VALUES('three') }
  460. error "throw an error!"
  461. }
  462. }
  463. }
  464. }
  465. db eval {SELECT * FROM t4}
  466. } {one}
  467. do_test tcl-10.15 {
  468. # Make sure a transaction has not been left open.
  469. db eval {BEGIN ; COMMIT}
  470. } {}
  471. do_test tcl-10.16 {
  472. db transaction {
  473. db eval { INSERT INTO t4 VALUES('two'); }
  474. db transaction {
  475. db eval { INSERT INTO t4 VALUES('three') }
  476. db transaction {
  477. db eval { INSERT INTO t4 VALUES('four') }
  478. }
  479. }
  480. }
  481. db eval {SELECT * FROM t4}
  482. } {one two three four}
  483. do_test tcl-10.17 {
  484. catch {
  485. db transaction {
  486. db eval { INSERT INTO t4 VALUES('A'); }
  487. db transaction {
  488. db eval { INSERT INTO t4 VALUES('B') }
  489. db transaction {
  490. db eval { INSERT INTO t4 VALUES('C') }
  491. error "throw an error!"
  492. }
  493. }
  494. }
  495. }
  496. db eval {SELECT * FROM t4}
  497. } {one two three four}
  498. do_test tcl-10.18 {
  499. # Make sure a transaction has not been left open.
  500. db eval {BEGIN ; COMMIT}
  501. } {}
  502. # Mess up a [db transaction] command by locking the database using a
  503. # second connection when it tries to commit. Make sure the transaction
  504. # is not still open after the "database is locked" exception is thrown.
  505. #
  506. do_test tcl-10.18 {
  507. sqlite3 db2 test.db
  508. db2 eval {
  509. BEGIN;
  510. SELECT * FROM sqlite_master;
  511. }
  512. set rc [catch {
  513. db transaction {
  514. db eval {INSERT INTO t4 VALUES('five')}
  515. }
  516. } msg]
  517. list $rc $msg
  518. } {1 {database is locked}}
  519. do_test tcl-10.19 {
  520. db eval {BEGIN ; COMMIT}
  521. } {}
  522. # Thwart a [db transaction] command by locking the database using a
  523. # second connection with "BEGIN EXCLUSIVE". Make sure no transaction is
  524. # open after the "database is locked" exception is thrown.
  525. #
  526. do_test tcl-10.20 {
  527. db2 eval {
  528. COMMIT;
  529. BEGIN EXCLUSIVE;
  530. }
  531. set rc [catch {
  532. db transaction {
  533. db eval {INSERT INTO t4 VALUES('five')}
  534. }
  535. } msg]
  536. list $rc $msg
  537. } {1 {database is locked}}
  538. do_test tcl-10.21 {
  539. db2 close
  540. db eval {BEGIN ; COMMIT}
  541. } {}
  542. do_test tcl-10.22 {
  543. sqlite3 db2 test.db
  544. db transaction exclusive {
  545. catch { db2 eval {SELECT * FROM sqlite_master} } msg
  546. set msg "db2: $msg"
  547. }
  548. set msg
  549. } {db2: database is locked}
  550. db2 close
  551. do_test tcl-11.1 {
  552. db eval {INSERT INTO t4 VALUES(6)}
  553. db exists {SELECT x,x*2,x+x FROM t4 WHERE x==6}
  554. } {1}
  555. do_test tcl-11.2 {
  556. db exists {SELECT 0 FROM t4 WHERE x==6}
  557. } {1}
  558. do_test tcl-11.3 {
  559. db exists {SELECT 1 FROM t4 WHERE x==8}
  560. } {0}
  561. do_test tcl-11.3.1 {
  562. tcl_objproc db exists {SELECT 1 FROM t4 WHERE x==8}
  563. } {0}
  564. do_test tcl-12.1 {
  565. unset -nocomplain a b c version
  566. set version [db version]
  567. scan $version "%d.%d.%d" a b c
  568. expr $a*1000000 + $b*1000 + $c
  569. } [sqlite3_libversion_number]
  570. # Check to see that when bindings of the form @aaa are used instead
  571. # of $aaa, that objects are treated as bytearray and are inserted
  572. # as BLOBs.
  573. #
  574. ifcapable tclvar {
  575. do_test tcl-13.1 {
  576. db eval {CREATE TABLE t5(x BLOB)}
  577. set x abc123
  578. db eval {INSERT INTO t5 VALUES($x)}
  579. db eval {SELECT typeof(x) FROM t5}
  580. } {text}
  581. do_test tcl-13.2 {
  582. binary scan $x H notUsed
  583. db eval {
  584. DELETE FROM t5;
  585. INSERT INTO t5 VALUES($x);
  586. SELECT typeof(x) FROM t5;
  587. }
  588. } {text}
  589. do_test tcl-13.3 {
  590. db eval {
  591. DELETE FROM t5;
  592. INSERT INTO t5 VALUES(@x);
  593. SELECT typeof(x) FROM t5;
  594. }
  595. } {blob}
  596. do_test tcl-13.4 {
  597. set y 1234
  598. db eval {
  599. DELETE FROM t5;
  600. INSERT INTO t5 VALUES(@y);
  601. SELECT hex(x), typeof(x) FROM t5
  602. }
  603. } {31323334 blob}
  604. }
  605. db func xCall xCall
  606. proc xCall {} { return "value" }
  607. do_execsql_test tcl-14.1 {
  608. CREATE TABLE t6(x);
  609. INSERT INTO t6 VALUES(1);
  610. }
  611. do_test tcl-14.2 {
  612. db one {SELECT x FROM t6 WHERE xCall()!='value'}
  613. } {}
  614. finish_test