incrblob.test 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. # 2007 May 1
  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. #
  12. # $Id: incrblob.test,v 1.24 2009/06/19 22:23:42 drh Exp $
  13. #
  14. set testdir [file dirname $argv0]
  15. source $testdir/tester.tcl
  16. ifcapable {!autovacuum || !pragma || !incrblob} {
  17. finish_test
  18. return
  19. }
  20. do_test incrblob-1.1 {
  21. execsql {
  22. CREATE TABLE blobs(k PRIMARY KEY, v BLOB);
  23. INSERT INTO blobs VALUES('one', X'0102030405060708090A');
  24. INSERT INTO blobs VALUES('two', X'0A090807060504030201');
  25. }
  26. } {}
  27. do_test incrblob-1.2.1 {
  28. set ::blob [db incrblob blobs v 1]
  29. string match incrblob_* $::blob
  30. } {1}
  31. unset -nocomplain data
  32. do_test incrblob-1.2.2 {
  33. binary scan [read $::blob] c* data
  34. set data
  35. } {1 2 3 4 5 6 7 8 9 10}
  36. do_test incrblob-1.2.3 {
  37. seek $::blob 0
  38. puts -nonewline $::blob "1234567890"
  39. flush $::blob
  40. } {}
  41. do_test incrblob-1.2.4 {
  42. seek $::blob 0
  43. binary scan [read $::blob] c* data
  44. set data
  45. } {49 50 51 52 53 54 55 56 57 48}
  46. do_test incrblob-1.2.5 {
  47. close $::blob
  48. } {}
  49. do_test incrblob-1.2.6 {
  50. execsql {
  51. SELECT v FROM blobs WHERE rowid = 1;
  52. }
  53. } {1234567890}
  54. #--------------------------------------------------------------------
  55. # Test cases incrblob-1.3.X check that it is possible to read and write
  56. # regions of a blob that lie on overflow pages.
  57. #
  58. do_test incrblob-1.3.1 {
  59. set ::str "[string repeat . 10000]"
  60. execsql {
  61. INSERT INTO blobs(rowid, k, v) VALUES(3, 'three', $::str);
  62. }
  63. } {}
  64. do_test incrblob-1.3.2 {
  65. set ::blob [db incrblob blobs v 3]
  66. seek $::blob 8500
  67. read $::blob 10
  68. } {..........}
  69. do_test incrblob-1.3.3 {
  70. seek $::blob 8500
  71. puts -nonewline $::blob 1234567890
  72. } {}
  73. do_test incrblob-1.3.4 {
  74. seek $::blob 8496
  75. read $::blob 10
  76. } {....123456}
  77. do_test incrblob-1.3.10 {
  78. close $::blob
  79. } {}
  80. #------------------------------------------------------------------------
  81. # incrblob-2.*:
  82. #
  83. # Test that the following operations use ptrmap pages to reduce
  84. # unnecessary reads:
  85. #
  86. # * Reading near the end of a blob,
  87. # * Writing near the end of a blob, and
  88. # * SELECT a column value that is located on an overflow page.
  89. #
  90. proc nRead {db} {
  91. set bt [btree_from_db $db]
  92. db_enter $db
  93. array set stats [btree_pager_stats $bt]
  94. db_leave $db
  95. return $stats(read)
  96. }
  97. proc nWrite {db} {
  98. set bt [btree_from_db $db]
  99. db_enter $db
  100. array set stats [btree_pager_stats $bt]
  101. db_leave $db
  102. return $stats(write)
  103. }
  104. sqlite3_soft_heap_limit 0
  105. foreach AutoVacuumMode [list 0 1] {
  106. if {$AutoVacuumMode>0} {
  107. ifcapable !autovacuum {
  108. break
  109. }
  110. }
  111. db close
  112. forcedelete test.db test.db-journal
  113. sqlite3 db test.db
  114. execsql "PRAGMA mmap_size = 0"
  115. execsql "PRAGMA auto_vacuum = $AutoVacuumMode"
  116. do_test incrblob-2.$AutoVacuumMode.1 {
  117. set ::str [string repeat abcdefghij 2900]
  118. execsql {
  119. BEGIN;
  120. CREATE TABLE blobs(k PRIMARY KEY, v BLOB, i INTEGER);
  121. DELETE FROM blobs;
  122. INSERT INTO blobs VALUES('one', $::str || randstr(500,500), 45);
  123. COMMIT;
  124. }
  125. expr [file size test.db]/1024
  126. } [expr 31 + $AutoVacuumMode]
  127. ifcapable autovacuum {
  128. do_test incrblob-2.$AutoVacuumMode.2 {
  129. execsql {
  130. PRAGMA auto_vacuum;
  131. }
  132. } $AutoVacuumMode
  133. }
  134. do_test incrblob-2.$AutoVacuumMode.3 {
  135. # Open and close the db to make sure the page cache is empty.
  136. db close
  137. sqlite3 db test.db
  138. execsql "PRAGMA mmap_size = 0"
  139. # Read the last 20 bytes of the blob via a blob handle.
  140. set ::blob [db incrblob blobs v 1]
  141. seek $::blob -20 end
  142. set ::fragment [read $::blob]
  143. close $::blob
  144. # If the database is not in auto-vacuum mode, the whole of
  145. # the overflow-chain must be scanned. In auto-vacuum mode,
  146. # sqlite uses the ptrmap pages to avoid reading the other pages.
  147. #
  148. nRead db
  149. } [expr $AutoVacuumMode ? 4 : 30]
  150. do_test incrblob-2.$AutoVacuumMode.4 {
  151. string range [db one {SELECT v FROM blobs}] end-19 end
  152. } $::fragment
  153. do_test incrblob-2.$AutoVacuumMode.5 {
  154. # Open and close the db to make sure the page cache is empty.
  155. db close
  156. sqlite3 db test.db
  157. execsql "PRAGMA mmap_size = 0"
  158. # Write the second-to-last 20 bytes of the blob via a blob handle.
  159. #
  160. set ::blob [db incrblob blobs v 1]
  161. seek $::blob -40 end
  162. puts -nonewline $::blob "1234567890abcdefghij"
  163. flush $::blob
  164. # If the database is not in auto-vacuum mode, the whole of
  165. # the overflow-chain must be scanned. In auto-vacuum mode,
  166. # sqlite uses the ptrmap pages to avoid reading the other pages.
  167. #
  168. nRead db
  169. } [expr $AutoVacuumMode ? 4 : 30]
  170. # Pages 1 (the write-counter) and 32 (the blob data) were written.
  171. do_test incrblob-2.$AutoVacuumMode.6 {
  172. close $::blob
  173. nWrite db
  174. } 2
  175. do_test incrblob-2.$AutoVacuumMode.7 {
  176. string range [db one {SELECT v FROM blobs}] end-39 end-20
  177. } "1234567890abcdefghij"
  178. do_test incrblob-2.$AutoVacuumMode.8 {
  179. # Open and close the db to make sure the page cache is empty.
  180. db close
  181. sqlite3 db test.db
  182. execsql { PRAGMA mmap_size = 0 }
  183. execsql { SELECT i FROM blobs }
  184. } {45}
  185. do_test incrblob-2.$AutoVacuumMode.9 {
  186. nRead db
  187. } [expr $AutoVacuumMode ? 4 : 30]
  188. }
  189. sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
  190. #------------------------------------------------------------------------
  191. # incrblob-3.*:
  192. #
  193. # Test the outcome of trying to write to a read-only blob handle.
  194. #
  195. do_test incrblob-3.1 {
  196. set ::blob [db incrblob -readonly blobs v 1]
  197. seek $::blob -40 end
  198. read $::blob 20
  199. } "1234567890abcdefghij"
  200. do_test incrblob-3.2 {
  201. seek $::blob 0
  202. set rc [catch {
  203. puts -nonewline $::blob "helloworld"
  204. } msg]
  205. close $::blob
  206. list $rc $msg
  207. } "1 {channel \"$::blob\" wasn't opened for writing}"
  208. do_test incrblob-3.3 {
  209. set ::blob [db incrblob -readonly blobs v 1]
  210. seek $::blob -40 end
  211. read $::blob 20
  212. } "1234567890abcdefghij"
  213. do_test incrblob-3.4 {
  214. set rc [catch {
  215. sqlite3_blob_write $::blob 20 "qwertyuioplkjhgfds"
  216. } msg]
  217. list $rc $msg
  218. } {1 SQLITE_READONLY}
  219. catch {close $::blob}
  220. #------------------------------------------------------------------------
  221. # incrblob-4.*:
  222. #
  223. # Try a couple of error conditions:
  224. #
  225. # 4.1 - Attempt to open a row that does not exist.
  226. # 4.2 - Attempt to open a column that does not exist.
  227. # 4.3 - Attempt to open a table that does not exist.
  228. # 4.4 - Attempt to open a database that does not exist.
  229. #
  230. # 4.5 - Attempt to open an integer
  231. # 4.6 - Attempt to open a real value
  232. # 4.7 - Attempt to open an SQL null
  233. #
  234. # 4.8 - Attempt to open an indexed column for writing
  235. # 4.9 - Attempt to open an indexed column for reading (this works)
  236. #
  237. # 4.11 - Attempt to open a column of a view.
  238. # 4.12 - Attempt to open a column of a virtual table.
  239. #
  240. do_test incrblob-4.1 {
  241. set rc [catch {
  242. set ::blob [db incrblob blobs v 2]
  243. } msg ]
  244. list $rc $msg
  245. } {1 {no such rowid: 2}}
  246. do_test incrblob-4.2 {
  247. set rc [catch {
  248. set ::blob [db incrblob blobs blue 1]
  249. } msg ]
  250. list $rc $msg
  251. } {1 {no such column: "blue"}}
  252. do_test incrblob-4.3 {
  253. set rc [catch {
  254. set ::blob [db incrblob nosuchtable blue 1]
  255. } msg ]
  256. list $rc $msg
  257. } {1 {no such table: main.nosuchtable}}
  258. do_test incrblob-4.4 {
  259. set rc [catch {
  260. set ::blob [db incrblob nosuchdb blobs v 1]
  261. } msg ]
  262. list $rc $msg
  263. } {1 {no such table: nosuchdb.blobs}}
  264. do_test incrblob-4.5 {
  265. set rc [catch {
  266. set ::blob [db incrblob blobs i 1]
  267. } msg ]
  268. list $rc $msg
  269. } {1 {cannot open value of type integer}}
  270. do_test incrblob-4.6 {
  271. execsql {
  272. INSERT INTO blobs(k, v, i) VALUES(123, 567.765, NULL);
  273. }
  274. set rc [catch {
  275. set ::blob [db incrblob blobs v 2]
  276. } msg ]
  277. list $rc $msg
  278. } {1 {cannot open value of type real}}
  279. do_test incrblob-4.7 {
  280. set rc [catch {
  281. set ::blob [db incrblob blobs i 2]
  282. } msg ]
  283. list $rc $msg
  284. } {1 {cannot open value of type null}}
  285. do_test incrblob-4.8.1 {
  286. execsql {
  287. INSERT INTO blobs(k, v, i) VALUES(X'010203040506070809', 'hello', 'world');
  288. }
  289. set rc [catch {
  290. set ::blob [db incrblob blobs k 3]
  291. } msg ]
  292. list $rc $msg
  293. } {1 {cannot open indexed column for writing}}
  294. do_test incrblob-4.8.2 {
  295. execsql {
  296. CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
  297. INSERT INTO t3 VALUES(1, 2);
  298. }
  299. set rc [catch {
  300. set ::blob [db incrblob -readonly t3 a 1]
  301. } msg ]
  302. list $rc $msg
  303. } {1 {cannot open value of type null}}
  304. do_test incrblob-4.8.3 {
  305. set rc [catch {
  306. set ::blob [db incrblob -readonly t3 rowid 1]
  307. } msg ]
  308. list $rc $msg
  309. } {1 {no such column: "rowid"}}
  310. do_test incrblob-4.9.1 {
  311. set rc [catch {
  312. set ::blob [db incrblob -readonly blobs k 3]
  313. } msg]
  314. } {0}
  315. do_test incrblob-4.9.2 {
  316. binary scan [read $::blob] c* c
  317. close $::blob
  318. set c
  319. } {1 2 3 4 5 6 7 8 9}
  320. do_test incrblob-4.10 {
  321. set ::blob [db incrblob -readonly blobs k 3]
  322. set rc [catch { sqlite3_blob_read $::blob 10 100 } msg]
  323. list $rc $msg
  324. } {1 SQLITE_ERROR}
  325. do_test incrblob-4.10.2 {
  326. close $::blob
  327. } {}
  328. ifcapable view {
  329. do_test incrblob-4.11 {
  330. execsql { CREATE VIEW blobs_view AS SELECT k, v, i FROM blobs }
  331. set rc [catch { db incrblob blobs_view v 3 } msg]
  332. list $rc $msg
  333. } {1 {cannot open view: blobs_view}}
  334. }
  335. ifcapable vtab {
  336. register_echo_module [sqlite3_connection_pointer db]
  337. do_test incrblob-4.12 {
  338. execsql { CREATE VIRTUAL TABLE blobs_echo USING echo(blobs) }
  339. set rc [catch { db incrblob blobs_echo v 3 } msg]
  340. list $rc $msg
  341. } {1 {cannot open virtual table: blobs_echo}}
  342. }
  343. #------------------------------------------------------------------------
  344. # incrblob-5.*:
  345. #
  346. # Test that opening a blob in an attached database works.
  347. #
  348. ifcapable attach {
  349. do_test incrblob-5.1 {
  350. forcedelete test2.db test2.db-journal
  351. set ::size [expr [file size [info script]]]
  352. execsql {
  353. ATTACH 'test2.db' AS aux;
  354. CREATE TABLE aux.files(name, text);
  355. INSERT INTO aux.files VALUES('this one', zeroblob($::size));
  356. }
  357. set fd [db incrblob aux files text 1]
  358. fconfigure $fd -translation binary
  359. set fd2 [open [info script]]
  360. fconfigure $fd2 -translation binary
  361. puts -nonewline $fd [read $fd2]
  362. close $fd
  363. close $fd2
  364. set ::text [db one {select text from aux.files}]
  365. string length $::text
  366. } [file size [info script]]
  367. do_test incrblob-5.2 {
  368. set fd2 [open [info script]]
  369. fconfigure $fd2 -translation binary
  370. set ::data [read $fd2]
  371. close $fd2
  372. set ::data
  373. } $::text
  374. }
  375. # free memory
  376. unset -nocomplain ::data
  377. unset -nocomplain ::text
  378. #------------------------------------------------------------------------
  379. # incrblob-6.*:
  380. #
  381. # Test that opening a blob for write-access is impossible if
  382. # another connection has the database RESERVED lock.
  383. #
  384. # Then test that blob writes that take place inside of a
  385. # transaction are not visible to external connections until
  386. # after the transaction is commited and the blob channel
  387. # closed.
  388. #
  389. # This test does not work with the "memsubsys1" configuration.
  390. # Permutation memsubsys1 configures a very small static allocation
  391. # for use as page-cache memory. This causes SQLite to upgrade
  392. # to an exclusive lock when writing earlier than usual, which
  393. # makes some of these tests fail.
  394. #
  395. sqlite3_soft_heap_limit 0
  396. if {[permutation] != "memsubsys1"} {
  397. do_test incrblob-6.1 {
  398. sqlite3 db2 test.db
  399. execsql {
  400. BEGIN;
  401. INSERT INTO blobs(k, v, i) VALUES('a', 'different', 'connection');
  402. } db2
  403. } {}
  404. do_test incrblob-6.2 {
  405. execsql {
  406. SELECT rowid FROM blobs ORDER BY rowid
  407. }
  408. } {1 2 3}
  409. do_test incrblob-6.3 {
  410. set rc [catch {
  411. db incrblob blobs v 1
  412. } msg]
  413. list $rc $msg
  414. } {1 {database is locked}}
  415. do_test incrblob-6.4 {
  416. set rc [catch {
  417. db incrblob blobs v 3
  418. } msg]
  419. list $rc $msg
  420. } {1 {database is locked}}
  421. do_test incrblob-6.5 {
  422. set ::blob [db incrblob -readonly blobs v 3]
  423. read $::blob
  424. } {hello}
  425. do_test incrblob-6.6 {
  426. close $::blob
  427. } {}
  428. do_test incrblob-6.7 {
  429. set ::blob [db2 incrblob blobs i 4]
  430. gets $::blob
  431. } {connection}
  432. do_test incrblob-6.8 {
  433. tell $::blob
  434. } {10}
  435. do_test incrblob-6.9 {
  436. seek $::blob 0
  437. puts -nonewline $::blob "invocation"
  438. flush $::blob
  439. } {}
  440. # At this point commit should be illegal (because
  441. # there is an open blob channel).
  442. #
  443. do_test incrblob-6.11 {
  444. catchsql {
  445. COMMIT;
  446. } db2
  447. } {1 {cannot commit transaction - SQL statements in progress}}
  448. do_test incrblob-6.12 {
  449. execsql {
  450. SELECT * FROM blobs WHERE rowid = 4;
  451. }
  452. } {}
  453. do_test incrblob-6.13 {
  454. close $::blob
  455. } {}
  456. do_test incrblob-6.14 {
  457. catchsql {
  458. COMMIT;
  459. } db2
  460. } {0 {}}
  461. do_test incrblob-6.15 {
  462. execsql {
  463. SELECT * FROM blobs WHERE rowid = 4;
  464. }
  465. } {a different invocation}
  466. db2 close
  467. }
  468. sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
  469. #-----------------------------------------------------------------------
  470. # The following tests verify the behavior of the incremental IO
  471. # APIs in the following cases:
  472. #
  473. # 7.1 A row that containing an open blob is modified.
  474. #
  475. # 7.2 A CREATE TABLE requires that an overflow page that is part
  476. # of an open blob is moved.
  477. #
  478. # 7.3 An INCREMENTAL VACUUM moves an overflow page that is part
  479. # of an open blob.
  480. #
  481. # In the first case above, correct behavior is for all subsequent
  482. # read/write operations on the blob-handle to return SQLITE_ABORT.
  483. # More accurately, blob-handles are invalidated whenever the table
  484. # they belong to is written to.
  485. #
  486. # The second two cases have no external effect. They are testing
  487. # that the internal cache of overflow page numbers is correctly
  488. # invalidated.
  489. #
  490. do_test incrblob-7.1.0 {
  491. execsql {
  492. BEGIN;
  493. DROP TABLE blobs;
  494. CREATE TABLE t1 (a, b, c, d BLOB);
  495. INSERT INTO t1(a, b, c, d) VALUES(1, 2, 3, 4);
  496. COMMIT;
  497. }
  498. } {}
  499. foreach {tn arg} {1 "" 2 -readonly} {
  500. execsql {
  501. UPDATE t1 SET d = zeroblob(10000);
  502. }
  503. do_test incrblob-7.1.$tn.1 {
  504. set ::b [eval db incrblob $arg t1 d 1]
  505. binary scan [sqlite3_blob_read $::b 5000 5] c* c
  506. set c
  507. } {0 0 0 0 0}
  508. do_test incrblob-7.1.$tn.2 {
  509. execsql {
  510. UPDATE t1 SET d = 15;
  511. }
  512. } {}
  513. do_test incrblob-7.1.$tn.3 {
  514. set rc [catch { sqlite3_blob_read $::b 5000 5 } msg]
  515. list $rc $msg
  516. } {1 SQLITE_ABORT}
  517. do_test incrblob-7.1.$tn.4 {
  518. execsql {
  519. SELECT d FROM t1;
  520. }
  521. } {15}
  522. do_test incrblob-7.1.$tn.5 {
  523. set rc [catch { close $::b } msg]
  524. list $rc $msg
  525. } {0 {}}
  526. do_test incrblob-7.1.$tn.6 {
  527. execsql {
  528. SELECT d FROM t1;
  529. }
  530. } {15}
  531. }
  532. set fd [open [info script]]
  533. fconfigure $fd -translation binary
  534. set ::data [read $fd 14000]
  535. close $fd
  536. db close
  537. forcedelete test.db test.db-journal
  538. sqlite3 db test.db
  539. do_test incrblob-7.2.1 {
  540. execsql {
  541. PRAGMA auto_vacuum = "incremental";
  542. CREATE TABLE t1(a INTEGER PRIMARY KEY, b); -- root@page3
  543. INSERT INTO t1 VALUES(123, $::data);
  544. }
  545. set ::b [db incrblob -readonly t1 b 123]
  546. fconfigure $::b -translation binary
  547. read $::b
  548. } $::data
  549. do_test incrblob-7.2.2 {
  550. execsql {
  551. CREATE TABLE t2(a INTEGER PRIMARY KEY, b); -- root@page4
  552. }
  553. seek $::b 0
  554. read $::b
  555. } $::data
  556. do_test incrblob-7.2.3 {
  557. close $::b
  558. execsql {
  559. SELECT rootpage FROM sqlite_master;
  560. }
  561. } {3 4}
  562. set ::otherdata "[string range $::data 0 1000][string range $::data 1001 end]"
  563. do_test incrblob-7.3.1 {
  564. execsql {
  565. INSERT INTO t2 VALUES(456, $::otherdata);
  566. }
  567. set ::b [db incrblob -readonly t2 b 456]
  568. fconfigure $::b -translation binary
  569. read $::b
  570. } $::otherdata
  571. do_test incrblob-7.3.2 {
  572. expr [file size test.db]/1024
  573. } 30
  574. do_test incrblob-7.3.3 {
  575. execsql {
  576. DELETE FROM t1 WHERE a = 123;
  577. PRAGMA INCREMENTAL_VACUUM(0);
  578. }
  579. seek $::b 0
  580. read $::b
  581. } $::otherdata
  582. # Attempt to write on a read-only blob. Make sure the error code
  583. # gets set. Ticket #2464.
  584. #
  585. do_test incrblob-7.4 {
  586. set rc [catch {sqlite3_blob_write $::b 10 HELLO} msg]
  587. lappend rc $msg
  588. } {1 SQLITE_READONLY}
  589. do_test incrblob-7.5 {
  590. sqlite3_errcode db
  591. } {SQLITE_READONLY}
  592. do_test incrblob-7.6 {
  593. sqlite3_errmsg db
  594. } {attempt to write a readonly database}
  595. # Test that if either the "offset" or "amount" arguments to
  596. # sqlite3_blob_write() are less than zero, SQLITE_ERROR is returned.
  597. #
  598. do_test incrblob-8.1 {
  599. execsql { INSERT INTO t1 VALUES(314159, 'sqlite') }
  600. set ::b [db incrblob t1 b 314159]
  601. fconfigure $::b -translation binary
  602. set rc [catch {sqlite3_blob_write $::b 10 HELLO -1} msg]
  603. lappend rc $msg
  604. } {1 SQLITE_ERROR}
  605. do_test incrblob-8.2 {
  606. sqlite3_errcode db
  607. } {SQLITE_ERROR}
  608. do_test incrblob-8.3 {
  609. set rc [catch {sqlite3_blob_write $::b -1 HELLO 5} msg]
  610. lappend rc $msg
  611. } {1 SQLITE_ERROR}
  612. do_test incrblob-8.4 {
  613. sqlite3_errcode db
  614. } {SQLITE_ERROR}
  615. do_test incrblob-8.5 {
  616. execsql {SELECT b FROM t1 WHERE a = 314159}
  617. } {sqlite}
  618. do_test incrblob-8.6 {
  619. set rc [catch {sqlite3_blob_write $::b 0 etilqs 6} msg]
  620. lappend rc $msg
  621. } {0 {}}
  622. do_test incrblob-8.7 {
  623. execsql {SELECT b FROM t1 WHERE a = 314159}
  624. } {etilqs}
  625. # The following test case exposes an instance in the blob code where
  626. # an error message was set using a call similar to sqlite3_mprintf(zErr),
  627. # where zErr is an arbitrary string. This is no good if the string contains
  628. # characters that can be mistaken for printf() formatting directives.
  629. #
  630. do_test incrblob-9.1 {
  631. list [catch { db incrblob t1 "A tricky column name %s%s" 1 } msg] $msg
  632. } {1 {no such column: "A tricky column name %s%s"}}
  633. finish_test