savepoint.test 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. # 2008 December 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. #
  12. # $Id: savepoint.test,v 1.13 2009/07/18 08:30:45 danielk1977 Exp $
  13. set testdir [file dirname $argv0]
  14. source $testdir/tester.tcl
  15. source $testdir/lock_common.tcl
  16. source $testdir/malloc_common.tcl
  17. #----------------------------------------------------------------------
  18. # The following tests - savepoint-1.* - test that the SAVEPOINT, RELEASE
  19. # and ROLLBACK TO comands are correctly parsed, and that the auto-commit
  20. # flag is correctly set and unset as a result.
  21. #
  22. do_test savepoint-1.1 {
  23. wal_set_journal_mode
  24. execsql {
  25. SAVEPOINT sp1;
  26. RELEASE sp1;
  27. }
  28. } {}
  29. do_test savepoint-1.2 {
  30. execsql {
  31. SAVEPOINT sp1;
  32. ROLLBACK TO sp1;
  33. }
  34. } {}
  35. do_test savepoint-1.3 {
  36. execsql { SAVEPOINT sp1 }
  37. db close
  38. } {}
  39. sqlite3 db test.db
  40. do_test savepoint-1.4.1 {
  41. execsql {
  42. SAVEPOINT sp1;
  43. SAVEPOINT sp2;
  44. RELEASE sp1;
  45. }
  46. sqlite3_get_autocommit db
  47. } {1}
  48. do_test savepoint-1.4.2 {
  49. execsql {
  50. SAVEPOINT sp1;
  51. SAVEPOINT sp2;
  52. RELEASE sp2;
  53. }
  54. sqlite3_get_autocommit db
  55. } {0}
  56. do_test savepoint-1.4.3 {
  57. execsql { RELEASE sp1 }
  58. sqlite3_get_autocommit db
  59. } {1}
  60. do_test savepoint-1.4.4 {
  61. execsql {
  62. SAVEPOINT sp1;
  63. SAVEPOINT sp2;
  64. ROLLBACK TO sp1;
  65. }
  66. sqlite3_get_autocommit db
  67. } {0}
  68. do_test savepoint-1.4.5 {
  69. execsql { RELEASE SAVEPOINT sp1 }
  70. sqlite3_get_autocommit db
  71. } {1}
  72. do_test savepoint-1.4.6 {
  73. execsql {
  74. SAVEPOINT sp1;
  75. SAVEPOINT sp2;
  76. SAVEPOINT sp3;
  77. ROLLBACK TO SAVEPOINT sp3;
  78. ROLLBACK TRANSACTION TO sp2;
  79. ROLLBACK TRANSACTION TO SAVEPOINT sp1;
  80. }
  81. sqlite3_get_autocommit db
  82. } {0}
  83. do_test savepoint-1.4.7 {
  84. execsql { RELEASE SAVEPOINT SP1 }
  85. sqlite3_get_autocommit db
  86. } {1}
  87. do_test savepoint-1.5 {
  88. execsql {
  89. SAVEPOINT sp1;
  90. ROLLBACK TO sp1;
  91. }
  92. } {}
  93. do_test savepoint-1.6 {
  94. execsql COMMIT
  95. } {}
  96. wal_check_journal_mode savepoint-1.7
  97. #------------------------------------------------------------------------
  98. # These tests - savepoint-2.* - test rollbacks and releases of savepoints
  99. # with a very simple data set.
  100. #
  101. do_test savepoint-2.1 {
  102. execsql {
  103. CREATE TABLE t1(a, b, c);
  104. BEGIN;
  105. INSERT INTO t1 VALUES(1, 2, 3);
  106. SAVEPOINT one;
  107. UPDATE t1 SET a = 2, b = 3, c = 4;
  108. }
  109. execsql { SELECT * FROM t1 }
  110. } {2 3 4}
  111. do_test savepoint-2.2 {
  112. execsql {
  113. ROLLBACK TO one;
  114. }
  115. execsql { SELECT * FROM t1 }
  116. } {1 2 3}
  117. do_test savepoint-2.3 {
  118. execsql {
  119. INSERT INTO t1 VALUES(4, 5, 6);
  120. }
  121. execsql { SELECT * FROM t1 }
  122. } {1 2 3 4 5 6}
  123. do_test savepoint-2.4 {
  124. execsql {
  125. ROLLBACK TO one;
  126. }
  127. execsql { SELECT * FROM t1 }
  128. } {1 2 3}
  129. do_test savepoint-2.5 {
  130. execsql {
  131. INSERT INTO t1 VALUES(7, 8, 9);
  132. SAVEPOINT two;
  133. INSERT INTO t1 VALUES(10, 11, 12);
  134. }
  135. execsql { SELECT * FROM t1 }
  136. } {1 2 3 7 8 9 10 11 12}
  137. do_test savepoint-2.6 {
  138. execsql {
  139. ROLLBACK TO two;
  140. }
  141. execsql { SELECT * FROM t1 }
  142. } {1 2 3 7 8 9}
  143. do_test savepoint-2.7 {
  144. execsql {
  145. INSERT INTO t1 VALUES(10, 11, 12);
  146. }
  147. execsql { SELECT * FROM t1 }
  148. } {1 2 3 7 8 9 10 11 12}
  149. do_test savepoint-2.8 {
  150. execsql {
  151. ROLLBACK TO one;
  152. }
  153. execsql { SELECT * FROM t1 }
  154. } {1 2 3}
  155. do_test savepoint-2.9 {
  156. execsql {
  157. INSERT INTO t1 VALUES('a', 'b', 'c');
  158. SAVEPOINT two;
  159. INSERT INTO t1 VALUES('d', 'e', 'f');
  160. }
  161. execsql { SELECT * FROM t1 }
  162. } {1 2 3 a b c d e f}
  163. do_test savepoint-2.10 {
  164. execsql {
  165. RELEASE two;
  166. }
  167. execsql { SELECT * FROM t1 }
  168. } {1 2 3 a b c d e f}
  169. do_test savepoint-2.11 {
  170. execsql {
  171. ROLLBACK;
  172. }
  173. execsql { SELECT * FROM t1 }
  174. } {}
  175. wal_check_journal_mode savepoint-2.12
  176. #------------------------------------------------------------------------
  177. # This block of tests - savepoint-3.* - test that when a transaction
  178. # savepoint is rolled back, locks are not released from database files.
  179. # And that when a transaction savepoint is released, they are released.
  180. #
  181. # These tests do not work in WAL mode. WAL mode does not take RESERVED
  182. # locks on the database file.
  183. #
  184. if {[wal_is_wal_mode]==0} {
  185. do_test savepoint-3.1 {
  186. execsql { SAVEPOINT "transaction" }
  187. execsql { PRAGMA lock_status }
  188. } {main unlocked temp closed}
  189. do_test savepoint-3.2 {
  190. execsql { INSERT INTO t1 VALUES(1, 2, 3) }
  191. execsql { PRAGMA lock_status }
  192. } {main reserved temp closed}
  193. do_test savepoint-3.3 {
  194. execsql { ROLLBACK TO "transaction" }
  195. execsql { PRAGMA lock_status }
  196. } {main reserved temp closed}
  197. do_test savepoint-3.4 {
  198. execsql { INSERT INTO t1 VALUES(1, 2, 3) }
  199. execsql { PRAGMA lock_status }
  200. } {main reserved temp closed}
  201. do_test savepoint-3.5 {
  202. execsql { RELEASE "transaction" }
  203. execsql { PRAGMA lock_status }
  204. } {main unlocked temp closed}
  205. }
  206. #------------------------------------------------------------------------
  207. # Test that savepoints that include schema modifications are handled
  208. # correctly. Test cases savepoint-4.*.
  209. #
  210. do_test savepoint-4.1 {
  211. execsql {
  212. CREATE TABLE t2(d, e, f);
  213. SELECT sql FROM sqlite_master;
  214. }
  215. } {{CREATE TABLE t1(a, b, c)} {CREATE TABLE t2(d, e, f)}}
  216. do_test savepoint-4.2 {
  217. execsql {
  218. BEGIN;
  219. CREATE TABLE t3(g,h);
  220. INSERT INTO t3 VALUES('I', 'II');
  221. SAVEPOINT one;
  222. DROP TABLE t3;
  223. }
  224. } {}
  225. do_test savepoint-4.3 {
  226. execsql {
  227. CREATE TABLE t3(g, h, i);
  228. INSERT INTO t3 VALUES('III', 'IV', 'V');
  229. }
  230. execsql {SELECT * FROM t3}
  231. } {III IV V}
  232. do_test savepoint-4.4 {
  233. execsql { ROLLBACK TO one; }
  234. execsql {SELECT * FROM t3}
  235. } {I II}
  236. do_test savepoint-4.5 {
  237. execsql {
  238. ROLLBACK;
  239. SELECT sql FROM sqlite_master;
  240. }
  241. } {{CREATE TABLE t1(a, b, c)} {CREATE TABLE t2(d, e, f)}}
  242. do_test savepoint-4.6 {
  243. execsql {
  244. BEGIN;
  245. INSERT INTO t1 VALUES('o', 't', 't');
  246. SAVEPOINT sp1;
  247. CREATE TABLE t3(a, b, c);
  248. INSERT INTO t3 VALUES('z', 'y', 'x');
  249. }
  250. execsql {SELECT * FROM t3}
  251. } {z y x}
  252. do_test savepoint-4.7 {
  253. execsql {
  254. ROLLBACK TO sp1;
  255. CREATE TABLE t3(a);
  256. INSERT INTO t3 VALUES('value');
  257. }
  258. execsql {SELECT * FROM t3}
  259. } {value}
  260. do_test savepoint-4.8 {
  261. execsql COMMIT
  262. } {}
  263. wal_check_journal_mode savepoint-4.9
  264. #------------------------------------------------------------------------
  265. # Test some logic errors to do with the savepoint feature.
  266. #
  267. ifcapable incrblob {
  268. do_test savepoint-5.1.1 {
  269. execsql {
  270. CREATE TABLE blobs(x);
  271. INSERT INTO blobs VALUES('a twentyeight character blob');
  272. }
  273. set fd [db incrblob blobs x 1]
  274. puts -nonewline $fd "hello"
  275. catchsql {SAVEPOINT abc}
  276. } {1 {cannot open savepoint - SQL statements in progress}}
  277. do_test savepoint-5.1.2 {
  278. close $fd
  279. catchsql {SAVEPOINT abc}
  280. } {0 {}}
  281. do_test savepoint-5.2 {
  282. execsql {RELEASE abc}
  283. catchsql {RELEASE abc}
  284. } {1 {no such savepoint: abc}}
  285. do_test savepoint-5.3.1 {
  286. execsql {SAVEPOINT abc}
  287. catchsql {ROLLBACK TO def}
  288. } {1 {no such savepoint: def}}
  289. do_test savepoint-5.3.2.1 {
  290. execsql {SAVEPOINT def}
  291. set fd [db incrblob -readonly blobs x 1]
  292. set rc [catch {seek $fd 0;read $fd} res]
  293. lappend rc $res
  294. } {0 {hellontyeight character blob}}
  295. do_test savepoint-5.3.2.2 {
  296. catchsql {ROLLBACK TO def}
  297. } {0 {}}
  298. do_test savepoint-5.3.2.3 {
  299. set rc [catch {seek $fd 0; read $fd} res]
  300. set rc
  301. } {1}
  302. do_test savepoint-5.3.3 {
  303. catchsql {RELEASE def}
  304. } {0 {}}
  305. do_test savepoint-5.3.4 {
  306. close $fd
  307. execsql {savepoint def}
  308. set fd [db incrblob blobs x 1]
  309. catchsql {release def}
  310. } {1 {cannot release savepoint - SQL statements in progress}}
  311. do_test savepoint-5.3.5 {
  312. close $fd
  313. execsql {release abc}
  314. } {}
  315. # Rollback mode:
  316. #
  317. # Open a savepoint transaction and insert a row into the database. Then,
  318. # using a second database handle, open a read-only transaction on the
  319. # database file. Check that the savepoint transaction cannot be committed
  320. # until after the read-only transaction has been closed.
  321. #
  322. # WAL mode:
  323. #
  324. # As above, except that the savepoint transaction can be successfully
  325. # committed before the read-only transaction has been closed.
  326. #
  327. do_test savepoint-5.4.1 {
  328. execsql {
  329. SAVEPOINT main;
  330. INSERT INTO blobs VALUES('another blob');
  331. }
  332. } {}
  333. do_test savepoint-5.4.2 {
  334. sqlite3 db2 test.db
  335. execsql { BEGIN ; SELECT count(*) FROM blobs } db2
  336. } {1}
  337. if {[wal_is_wal_mode]} {
  338. do_test savepoint-5.4.3 { catchsql "RELEASE main" } {0 {}}
  339. do_test savepoint-5.4.4 { db2 close } {}
  340. } else {
  341. do_test savepoint-5.4.3 {
  342. catchsql { RELEASE main }
  343. } {1 {database is locked}}
  344. do_test savepoint-5.4.4 {
  345. db2 close
  346. catchsql { RELEASE main }
  347. } {0 {}}
  348. }
  349. do_test savepoint-5.4.5 {
  350. execsql { SELECT x FROM blobs WHERE rowid = 2 }
  351. } {{another blob}}
  352. do_test savepoint-5.4.6 {
  353. execsql { SELECT count(*) FROM blobs }
  354. } {2}
  355. }
  356. wal_check_journal_mode savepoint-5.5
  357. #-------------------------------------------------------------------------
  358. # The following tests, savepoint-6.*, test an incr-vacuum inside of a
  359. # couple of nested savepoints.
  360. #
  361. ifcapable {autovacuum && pragma} {
  362. db close
  363. forcedelete test.db
  364. sqlite3 db test.db
  365. do_test savepoint-6.1 {
  366. execsql { PRAGMA auto_vacuum = incremental }
  367. wal_set_journal_mode
  368. execsql {
  369. CREATE TABLE t1(a, b, c);
  370. CREATE INDEX i1 ON t1(a, b);
  371. BEGIN;
  372. INSERT INTO t1 VALUES(randstr(10,400),randstr(10,400),randstr(10,400));
  373. }
  374. set r "randstr(10,400)"
  375. for {set ii 0} {$ii < 10} {incr ii} {
  376. execsql "INSERT INTO t1 SELECT $r, $r, $r FROM t1"
  377. }
  378. execsql { COMMIT }
  379. } {}
  380. integrity_check savepoint-6.2
  381. do_test savepoint-6.3 {
  382. execsql {
  383. PRAGMA cache_size = 10;
  384. BEGIN;
  385. UPDATE t1 SET a = randstr(10,10) WHERE (rowid%4)==0;
  386. SAVEPOINT one;
  387. DELETE FROM t1 WHERE rowid%2;
  388. PRAGMA incr_vacuum;
  389. SAVEPOINT two;
  390. INSERT INTO t1 SELECT randstr(10,400), randstr(10,400), c FROM t1;
  391. DELETE FROM t1 WHERE rowid%2;
  392. PRAGMA incr_vacuum;
  393. ROLLBACK TO one;
  394. COMMIT;
  395. }
  396. } {}
  397. integrity_check savepoint-6.4
  398. wal_check_journal_mode savepoint-6.5
  399. }
  400. #-------------------------------------------------------------------------
  401. # The following tests, savepoint-7.*, attempt to break the logic
  402. # surrounding savepoints by growing and shrinking the database file.
  403. #
  404. db close
  405. forcedelete test.db
  406. sqlite3 db test.db
  407. do_test savepoint-7.1 {
  408. execsql { PRAGMA auto_vacuum = incremental }
  409. wal_set_journal_mode
  410. execsql {
  411. PRAGMA cache_size = 10;
  412. BEGIN;
  413. CREATE TABLE t1(a PRIMARY KEY, b);
  414. INSERT INTO t1(a) VALUES('alligator');
  415. INSERT INTO t1(a) VALUES('angelfish');
  416. INSERT INTO t1(a) VALUES('ant');
  417. INSERT INTO t1(a) VALUES('antelope');
  418. INSERT INTO t1(a) VALUES('ape');
  419. INSERT INTO t1(a) VALUES('baboon');
  420. INSERT INTO t1(a) VALUES('badger');
  421. INSERT INTO t1(a) VALUES('bear');
  422. INSERT INTO t1(a) VALUES('beetle');
  423. INSERT INTO t1(a) VALUES('bird');
  424. INSERT INTO t1(a) VALUES('bison');
  425. UPDATE t1 SET b = randstr(1000,1000);
  426. UPDATE t1 SET b = b||randstr(1000,1000);
  427. UPDATE t1 SET b = b||randstr(1000,1000);
  428. UPDATE t1 SET b = b||randstr(10,1000);
  429. COMMIT;
  430. }
  431. expr ([execsql { PRAGMA page_count }] > 20)
  432. } {1}
  433. do_test savepoint-7.2.1 {
  434. execsql {
  435. BEGIN;
  436. SAVEPOINT one;
  437. CREATE TABLE t2(a, b);
  438. INSERT INTO t2 SELECT a, b FROM t1;
  439. ROLLBACK TO one;
  440. }
  441. execsql {
  442. PRAGMA integrity_check;
  443. }
  444. } {ok}
  445. do_test savepoint-7.2.2 {
  446. execsql {
  447. COMMIT;
  448. PRAGMA integrity_check;
  449. }
  450. } {ok}
  451. do_test savepoint-7.3.1 {
  452. execsql {
  453. CREATE TABLE t2(a, b);
  454. INSERT INTO t2 SELECT a, b FROM t1;
  455. }
  456. } {}
  457. do_test savepoint-7.3.2 {
  458. execsql {
  459. BEGIN;
  460. SAVEPOINT one;
  461. DELETE FROM t2;
  462. PRAGMA incremental_vacuum;
  463. SAVEPOINT two;
  464. INSERT INTO t2 SELECT a, b FROM t1;
  465. ROLLBACK TO two;
  466. COMMIT;
  467. }
  468. execsql { PRAGMA integrity_check }
  469. } {ok}
  470. wal_check_journal_mode savepoint-7.3.3
  471. do_test savepoint-7.4.1 {
  472. db close
  473. forcedelete test.db
  474. sqlite3 db test.db
  475. execsql { PRAGMA auto_vacuum = incremental }
  476. wal_set_journal_mode
  477. execsql {
  478. CREATE TABLE t1(a, b, PRIMARY KEY(a, b));
  479. INSERT INTO t1 VALUES(randstr(1000,1000), randstr(1000,1000));
  480. BEGIN;
  481. DELETE FROM t1;
  482. SAVEPOINT one;
  483. PRAGMA incremental_vacuum;
  484. ROLLBACK TO one;
  485. COMMIT;
  486. }
  487. execsql { PRAGMA integrity_check }
  488. } {ok}
  489. do_test savepoint-7.5.1 {
  490. execsql {
  491. PRAGMA incremental_vacuum;
  492. CREATE TABLE t5(x, y);
  493. INSERT INTO t5 VALUES(1, randstr(1000,1000));
  494. INSERT INTO t5 VALUES(2, randstr(1000,1000));
  495. INSERT INTO t5 VALUES(3, randstr(1000,1000));
  496. BEGIN;
  497. INSERT INTO t5 VALUES(4, randstr(1000,1000));
  498. INSERT INTO t5 VALUES(5, randstr(1000,1000));
  499. DELETE FROM t5 WHERE x=1 OR x=2;
  500. SAVEPOINT one;
  501. PRAGMA incremental_vacuum;
  502. SAVEPOINT two;
  503. INSERT INTO t5 VALUES(1, randstr(1000,1000));
  504. INSERT INTO t5 VALUES(2, randstr(1000,1000));
  505. ROLLBACK TO two;
  506. ROLLBACK TO one;
  507. COMMIT;
  508. PRAGMA integrity_check;
  509. }
  510. } {ok}
  511. do_test savepoint-7.5.2 {
  512. execsql {
  513. DROP TABLE t5;
  514. }
  515. } {}
  516. wal_check_journal_mode savepoint-7.5.3
  517. # Test oddly named and quoted savepoints.
  518. #
  519. do_test savepoint-8-1 {
  520. execsql { SAVEPOINT "save1" }
  521. execsql { RELEASE save1 }
  522. } {}
  523. do_test savepoint-8-2 {
  524. execsql { SAVEPOINT "Including whitespace " }
  525. execsql { RELEASE "including Whitespace " }
  526. } {}
  527. # Test that the authorization callback works.
  528. #
  529. ifcapable auth {
  530. proc auth {args} {
  531. eval lappend ::authdata $args
  532. return SQLITE_OK
  533. }
  534. db auth auth
  535. do_test savepoint-9.1 {
  536. set ::authdata [list]
  537. execsql { SAVEPOINT sp1 }
  538. set ::authdata
  539. } {SQLITE_SAVEPOINT BEGIN sp1 {} {}}
  540. do_test savepoint-9.2 {
  541. set ::authdata [list]
  542. execsql { ROLLBACK TO sp1 }
  543. set ::authdata
  544. } {SQLITE_SAVEPOINT ROLLBACK sp1 {} {}}
  545. do_test savepoint-9.3 {
  546. set ::authdata [list]
  547. execsql { RELEASE sp1 }
  548. set ::authdata
  549. } {SQLITE_SAVEPOINT RELEASE sp1 {} {}}
  550. proc auth {args} {
  551. eval lappend ::authdata $args
  552. return SQLITE_DENY
  553. }
  554. db auth auth
  555. do_test savepoint-9.4 {
  556. set ::authdata [list]
  557. set res [catchsql { SAVEPOINT sp1 }]
  558. concat $::authdata $res
  559. } {SQLITE_SAVEPOINT BEGIN sp1 {} {} 1 {not authorized}}
  560. do_test savepoint-9.5 {
  561. set ::authdata [list]
  562. set res [catchsql { ROLLBACK TO sp1 }]
  563. concat $::authdata $res
  564. } {SQLITE_SAVEPOINT ROLLBACK sp1 {} {} 1 {not authorized}}
  565. do_test savepoint-9.6 {
  566. set ::authdata [list]
  567. set res [catchsql { RELEASE sp1 }]
  568. concat $::authdata $res
  569. } {SQLITE_SAVEPOINT RELEASE sp1 {} {} 1 {not authorized}}
  570. catch { db eval ROLLBACK }
  571. db auth ""
  572. }
  573. #-------------------------------------------------------------------------
  574. # The following tests - savepoint-10.* - test the interaction of
  575. # savepoints and ATTACH statements.
  576. #
  577. # First make sure it is not possible to attach or detach a database while
  578. # a savepoint is open (it is not possible if any transaction is open).
  579. #
  580. do_test savepoint-10.1.1 {
  581. catchsql {
  582. SAVEPOINT one;
  583. ATTACH 'test2.db' AS aux;
  584. }
  585. } {1 {cannot ATTACH database within transaction}}
  586. do_test savepoint-10.1.2 {
  587. execsql {
  588. RELEASE one;
  589. ATTACH 'test2.db' AS aux;
  590. }
  591. catchsql {
  592. SAVEPOINT one;
  593. DETACH aux;
  594. }
  595. } {1 {cannot DETACH database within transaction}}
  596. do_test savepoint-10.1.3 {
  597. execsql {
  598. RELEASE one;
  599. DETACH aux;
  600. }
  601. } {}
  602. # The lock state of the TEMP database can vary if SQLITE_TEMP_STORE=3
  603. # And the following set of tests is only really interested in the status
  604. # of the aux1 and aux2 locks. So record the current lock status of
  605. # TEMP for use in the answers.
  606. set templockstate [lindex [db eval {PRAGMA lock_status}] 3]
  607. if {[wal_is_wal_mode]==0} {
  608. do_test savepoint-10.2.1 {
  609. forcedelete test3.db
  610. forcedelete test2.db
  611. execsql {
  612. ATTACH 'test2.db' AS aux1;
  613. ATTACH 'test3.db' AS aux2;
  614. DROP TABLE t1;
  615. CREATE TABLE main.t1(x, y);
  616. CREATE TABLE aux1.t2(x, y);
  617. CREATE TABLE aux2.t3(x, y);
  618. SELECT name FROM sqlite_master;
  619. SELECT name FROM aux1.sqlite_master;
  620. SELECT name FROM aux2.sqlite_master;
  621. }
  622. } {t1 t2 t3}
  623. do_test savepoint-10.2.2 {
  624. execsql { PRAGMA lock_status }
  625. } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked]
  626. do_test savepoint-10.2.3 {
  627. execsql {
  628. SAVEPOINT one;
  629. INSERT INTO t1 VALUES(1, 2);
  630. PRAGMA lock_status;
  631. }
  632. } [list main reserved temp $templockstate aux1 unlocked aux2 unlocked]
  633. do_test savepoint-10.2.4 {
  634. execsql {
  635. INSERT INTO t3 VALUES(3, 4);
  636. PRAGMA lock_status;
  637. }
  638. } [list main reserved temp $templockstate aux1 unlocked aux2 reserved]
  639. do_test savepoint-10.2.5 {
  640. execsql {
  641. SAVEPOINT two;
  642. INSERT INTO t2 VALUES(5, 6);
  643. PRAGMA lock_status;
  644. }
  645. } [list main reserved temp $templockstate aux1 reserved aux2 reserved]
  646. do_test savepoint-10.2.6 {
  647. execsql { SELECT * FROM t2 }
  648. } {5 6}
  649. do_test savepoint-10.2.7 {
  650. execsql { ROLLBACK TO two }
  651. execsql { SELECT * FROM t2 }
  652. } {}
  653. do_test savepoint-10.2.8 {
  654. execsql { PRAGMA lock_status }
  655. } [list main reserved temp $templockstate aux1 reserved aux2 reserved]
  656. do_test savepoint-10.2.9 {
  657. execsql { SELECT 'a', * FROM t1 ; SELECT 'b', * FROM t3 }
  658. } {a 1 2 b 3 4}
  659. do_test savepoint-10.2.9 {
  660. execsql {
  661. INSERT INTO t2 VALUES(5, 6);
  662. RELEASE one;
  663. }
  664. execsql {
  665. SELECT * FROM t1;
  666. SELECT * FROM t2;
  667. SELECT * FROM t3;
  668. }
  669. } {1 2 5 6 3 4}
  670. do_test savepoint-10.2.9 {
  671. execsql { PRAGMA lock_status }
  672. } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked]
  673. do_test savepoint-10.2.10 {
  674. execsql {
  675. SAVEPOINT one;
  676. INSERT INTO t1 VALUES('a', 'b');
  677. SAVEPOINT two;
  678. INSERT INTO t2 VALUES('c', 'd');
  679. SAVEPOINT three;
  680. INSERT INTO t3 VALUES('e', 'f');
  681. }
  682. execsql {
  683. SELECT * FROM t1;
  684. SELECT * FROM t2;
  685. SELECT * FROM t3;
  686. }
  687. } {1 2 a b 5 6 c d 3 4 e f}
  688. do_test savepoint-10.2.11 {
  689. execsql { ROLLBACK TO two }
  690. execsql {
  691. SELECT * FROM t1;
  692. SELECT * FROM t2;
  693. SELECT * FROM t3;
  694. }
  695. } {1 2 a b 5 6 3 4}
  696. do_test savepoint-10.2.12 {
  697. execsql {
  698. INSERT INTO t3 VALUES('g', 'h');
  699. ROLLBACK TO two;
  700. }
  701. execsql {
  702. SELECT * FROM t1;
  703. SELECT * FROM t2;
  704. SELECT * FROM t3;
  705. }
  706. } {1 2 a b 5 6 3 4}
  707. do_test savepoint-10.2.13 {
  708. execsql { ROLLBACK }
  709. execsql {
  710. SELECT * FROM t1;
  711. SELECT * FROM t2;
  712. SELECT * FROM t3;
  713. }
  714. } {1 2 5 6 3 4}
  715. do_test savepoint-10.2.14 {
  716. execsql { PRAGMA lock_status }
  717. } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked]
  718. }
  719. #-------------------------------------------------------------------------
  720. # The following tests - savepoint-11.* - test the interaction of
  721. # savepoints and creating or dropping tables and indexes in
  722. # auto-vacuum mode.
  723. #
  724. do_test savepoint-11.1 {
  725. db close
  726. forcedelete test.db
  727. sqlite3 db test.db
  728. execsql { PRAGMA auto_vacuum = full; }
  729. wal_set_journal_mode
  730. execsql {
  731. CREATE TABLE t1(a, b, UNIQUE(a, b));
  732. INSERT INTO t1 VALUES(1, randstr(1000,1000));
  733. INSERT INTO t1 VALUES(2, randstr(1000,1000));
  734. }
  735. } {}
  736. do_test savepoint-11.2 {
  737. execsql {
  738. SAVEPOINT one;
  739. CREATE TABLE t2(a, b, UNIQUE(a, b));
  740. SAVEPOINT two;
  741. CREATE TABLE t3(a, b, UNIQUE(a, b));
  742. }
  743. } {}
  744. integrity_check savepoint-11.3
  745. do_test savepoint-11.4 {
  746. execsql { ROLLBACK TO two }
  747. } {}
  748. integrity_check savepoint-11.5
  749. do_test savepoint-11.6 {
  750. execsql {
  751. CREATE TABLE t3(a, b, UNIQUE(a, b));
  752. ROLLBACK TO one;
  753. }
  754. } {}
  755. integrity_check savepoint-11.7
  756. do_test savepoint-11.8 {
  757. execsql { ROLLBACK }
  758. execsql { PRAGMA wal_checkpoint }
  759. file size test.db
  760. } {8192}
  761. do_test savepoint-11.9 {
  762. execsql {
  763. DROP TABLE IF EXISTS t1;
  764. DROP TABLE IF EXISTS t2;
  765. DROP TABLE IF EXISTS t3;
  766. }
  767. } {}
  768. do_test savepoint-11.10 {
  769. execsql {
  770. BEGIN;
  771. CREATE TABLE t1(a, b);
  772. CREATE TABLE t2(x, y);
  773. INSERT INTO t2 VALUES(1, 2);
  774. SAVEPOINT one;
  775. INSERT INTO t2 VALUES(3, 4);
  776. SAVEPOINT two;
  777. DROP TABLE t1;
  778. ROLLBACK TO two;
  779. }
  780. execsql {SELECT * FROM t2}
  781. } {1 2 3 4}
  782. do_test savepoint-11.11 {
  783. execsql COMMIT
  784. } {}
  785. do_test savepoint-11.12 {
  786. execsql {SELECT * FROM t2}
  787. } {1 2 3 4}
  788. wal_check_journal_mode savepoint-11.13
  789. #-------------------------------------------------------------------------
  790. # The following tests - savepoint-12.* - test the interaction of
  791. # savepoints and "ON CONFLICT ROLLBACK" clauses.
  792. #
  793. do_test savepoint-12.1 {
  794. execsql {
  795. CREATE TABLE t4(a PRIMARY KEY, b);
  796. INSERT INTO t4 VALUES(1, 'one');
  797. }
  798. } {}
  799. do_test savepoint-12.2 {
  800. # The final statement of the following SQL hits a constraint when the
  801. # conflict handling mode is "OR ROLLBACK" and there are a couple of
  802. # open savepoints. At one point this would fail to clear the internal
  803. # record of the open savepoints, resulting in an assert() failure
  804. # later on.
  805. #
  806. catchsql {
  807. BEGIN;
  808. INSERT INTO t4 VALUES(2, 'two');
  809. SAVEPOINT sp1;
  810. INSERT INTO t4 VALUES(3, 'three');
  811. SAVEPOINT sp2;
  812. INSERT OR ROLLBACK INTO t4 VALUES(1, 'one');
  813. }
  814. } {1 {column a is not unique}}
  815. do_test savepoint-12.3 {
  816. sqlite3_get_autocommit db
  817. } {1}
  818. do_test savepoint-12.4 {
  819. execsql { SAVEPOINT one }
  820. } {}
  821. wal_check_journal_mode savepoint-12.5
  822. #-------------------------------------------------------------------------
  823. # The following tests - savepoint-13.* - test the interaction of
  824. # savepoints and "journal_mode = off".
  825. #
  826. if {[wal_is_wal_mode]==0} {
  827. do_test savepoint-13.1 {
  828. db close
  829. catch {forcedelete test.db}
  830. sqlite3 db test.db
  831. execsql {
  832. BEGIN;
  833. CREATE TABLE t1(a PRIMARY KEY, b);
  834. INSERT INTO t1 VALUES(1, 2);
  835. COMMIT;
  836. PRAGMA journal_mode = off;
  837. }
  838. } {off}
  839. do_test savepoint-13.2 {
  840. execsql {
  841. BEGIN;
  842. INSERT INTO t1 VALUES(3, 4);
  843. INSERT INTO t1 SELECT a+4,b+4 FROM t1;
  844. COMMIT;
  845. }
  846. } {}
  847. do_test savepoint-13.3 {
  848. execsql {
  849. BEGIN;
  850. INSERT INTO t1 VALUES(9, 10);
  851. SAVEPOINT s1;
  852. INSERT INTO t1 VALUES(11, 12);
  853. COMMIT;
  854. }
  855. } {}
  856. do_test savepoint-13.4 {
  857. execsql {
  858. BEGIN;
  859. INSERT INTO t1 VALUES(13, 14);
  860. SAVEPOINT s1;
  861. INSERT INTO t1 VALUES(15, 16);
  862. ROLLBACK TO s1;
  863. ROLLBACK;
  864. SELECT * FROM t1;
  865. }
  866. } {1 2 3 4 5 6 7 8 9 10 11 12}
  867. }
  868. db close
  869. delete_file test.db
  870. do_multiclient_test tn {
  871. do_test savepoint-14.$tn.1 {
  872. sql1 {
  873. CREATE TABLE foo(x);
  874. INSERT INTO foo VALUES(1);
  875. INSERT INTO foo VALUES(2);
  876. }
  877. sql2 {
  878. BEGIN;
  879. SELECT * FROM foo;
  880. }
  881. } {1 2}
  882. do_test savepoint-14.$tn.2 {
  883. sql1 {
  884. SAVEPOINT one;
  885. INSERT INTO foo VALUES(1);
  886. }
  887. csql1 { RELEASE one }
  888. } {1 {database is locked}}
  889. do_test savepoint-14.$tn.3 {
  890. sql1 { ROLLBACK TO one }
  891. sql2 { COMMIT }
  892. sql1 { RELEASE one }
  893. } {}
  894. do_test savepoint-14.$tn.4 {
  895. sql2 {
  896. BEGIN;
  897. SELECT * FROM foo;
  898. }
  899. } {1 2}
  900. do_test savepoint-14.$tn.5 {
  901. sql1 {
  902. SAVEPOINT one;
  903. INSERT INTO foo VALUES(1);
  904. }
  905. csql1 { RELEASE one }
  906. } {1 {database is locked}}
  907. do_test savepoint-14.$tn.6 {
  908. sql2 { COMMIT }
  909. sql1 {
  910. ROLLBACK TO one;
  911. INSERT INTO foo VALUES(3);
  912. INSERT INTO foo VALUES(4);
  913. INSERT INTO foo VALUES(5);
  914. RELEASE one;
  915. }
  916. } {}
  917. do_test savepoint-14.$tn.7 {
  918. sql2 { CREATE INDEX fooidx ON foo(x); }
  919. sql3 { PRAGMA integrity_check }
  920. } {ok}
  921. }
  922. do_multiclient_test tn {
  923. do_test savepoint-15.$tn.1 {
  924. sql1 {
  925. CREATE TABLE foo(x);
  926. INSERT INTO foo VALUES(1);
  927. INSERT INTO foo VALUES(2);
  928. }
  929. sql2 { BEGIN; SELECT * FROM foo; }
  930. } {1 2}
  931. do_test savepoint-15.$tn.2 {
  932. sql1 {
  933. PRAGMA locking_mode = EXCLUSIVE;
  934. BEGIN;
  935. INSERT INTO foo VALUES(3);
  936. }
  937. csql1 { COMMIT }
  938. } {1 {database is locked}}
  939. do_test savepoint-15.$tn.3 {
  940. sql1 { ROLLBACK }
  941. sql2 { COMMIT }
  942. sql1 {
  943. INSERT INTO foo VALUES(3);
  944. PRAGMA locking_mode = NORMAL;
  945. INSERT INTO foo VALUES(4);
  946. }
  947. sql2 { CREATE INDEX fooidx ON foo(x); }
  948. sql3 { PRAGMA integrity_check }
  949. } {ok}
  950. }
  951. do_multiclient_test tn {
  952. do_test savepoint-16.$tn.1 {
  953. sql1 {
  954. CREATE TABLE foo(x);
  955. INSERT INTO foo VALUES(1);
  956. INSERT INTO foo VALUES(2);
  957. }
  958. } {}
  959. do_test savepoint-16.$tn.2 {
  960. db eval {SELECT * FROM foo} {
  961. sql1 { INSERT INTO foo VALUES(3) }
  962. sql2 { SELECT * FROM foo }
  963. sql1 { INSERT INTO foo VALUES(4) }
  964. break
  965. }
  966. sql2 { CREATE INDEX fooidx ON foo(x); }
  967. sql3 { PRAGMA integrity_check }
  968. } {ok}
  969. do_test savepoint-16.$tn.3 {
  970. sql1 { SELECT * FROM foo }
  971. } {1 2 3 4}
  972. }
  973. #-------------------------------------------------------------------------
  974. # This next block of tests verifies that a problem reported on the mailing
  975. # list has been resolved. At one point the second "CREATE TABLE t6" would
  976. # fail as table t6 still existed in the internal cache of the db schema
  977. # (even though it had been removed from the database by the ROLLBACK
  978. # command).
  979. #
  980. sqlite3 db test.db
  981. do_execsql_test savepoint-17.1 {
  982. BEGIN;
  983. CREATE TABLE t6(a, b);
  984. INSERT INTO t6 VALUES(1, 2);
  985. SAVEPOINT one;
  986. INSERT INTO t6 VALUES(3, 4);
  987. ROLLBACK TO one;
  988. SELECT * FROM t6;
  989. ROLLBACK;
  990. } {1 2}
  991. do_execsql_test savepoint-17.2 {
  992. CREATE TABLE t6(a, b);
  993. } {}
  994. finish_test