incrvacuum.test 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. # 2007 April 26
  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 SQLite library. The
  12. # focus of this file is testing the incremental vacuum feature.
  13. #
  14. # Note: There are also some tests for incremental vacuum and IO
  15. # errors in incrvacuum_ioerr.test.
  16. #
  17. # $Id: incrvacuum.test,v 1.23 2009/02/18 20:31:18 drh Exp $
  18. set testdir [file dirname $argv0]
  19. source $testdir/tester.tcl
  20. # If this build of the library does not support auto-vacuum, omit this
  21. # whole file.
  22. ifcapable {!autovacuum || !pragma} {
  23. finish_test
  24. return
  25. }
  26. #---------------------------------------------------------------------
  27. # Test the pragma on an empty database.
  28. #
  29. do_test incrvacuum-1.1 {
  30. execsql {
  31. pragma auto_vacuum;
  32. }
  33. } $sqlite_options(default_autovacuum)
  34. do_test incrvacuum-1.2.0 {
  35. # File size is sometimes 1 instead of 0 due to the hack we put in
  36. # to work around ticket #3260. Search for comments on #3260 in
  37. # os_unix.c.
  38. expr {[file size test.db] > 1}
  39. } {0}
  40. do_test incrvacuum-1.2 {
  41. # This command will create the database.
  42. execsql {
  43. pragma auto_vacuum = 'full';
  44. pragma auto_vacuum;
  45. }
  46. } {1}
  47. do_test incrvacuum-1.2.1 {
  48. expr {[file size test.db] > 0}
  49. } {1}
  50. do_test incrvacuum-1.3 {
  51. execsql {
  52. pragma auto_vacuum = 'incremental';
  53. pragma auto_vacuum;
  54. }
  55. } {2}
  56. do_test incrvacuum-1.4 {
  57. # In this case the invalid value is ignored and the auto_vacuum
  58. # setting remains unchanged.
  59. execsql {
  60. pragma auto_vacuum = 'invalid';
  61. pragma auto_vacuum;
  62. }
  63. } {2}
  64. do_test incrvacuum-1.5 {
  65. execsql {
  66. pragma auto_vacuum = 1;
  67. pragma auto_vacuum;
  68. }
  69. } {1}
  70. do_test incrvacuum-1.6 {
  71. execsql {
  72. pragma auto_vacuum = '2';
  73. pragma auto_vacuum;
  74. }
  75. } {2}
  76. do_test incrvacuum-1.7 {
  77. # Invalid value. auto_vacuum setting remains unchanged.
  78. execsql {
  79. pragma auto_vacuum = 5;
  80. pragma auto_vacuum;
  81. }
  82. } {2}
  83. #---------------------------------------------------------------------
  84. # Test the pragma on a non-empty database. It is possible to toggle
  85. # the connection between "full" and "incremental" mode, but not to
  86. # change from either of these to "none", or from "none" to "full" or
  87. # "incremental".
  88. #
  89. do_test incrvacuum-2.1 {
  90. execsql {
  91. pragma auto_vacuum = 1;
  92. CREATE TABLE abc(a, b, c);
  93. }
  94. } {}
  95. do_test incrvacuum-2.2 {
  96. execsql {
  97. pragma auto_vacuum = 'none';
  98. pragma auto_vacuum;
  99. }
  100. } {1}
  101. do_test incrvacuum-2.2.1 {
  102. db close
  103. sqlite3 db test.db
  104. execsql {
  105. pragma auto_vacuum;
  106. }
  107. } {1}
  108. do_test incrvacuum-2.3 {
  109. execsql {
  110. pragma auto_vacuum = 'incremental';
  111. pragma auto_vacuum;
  112. }
  113. } {2}
  114. do_test incrvacuum-2.4 {
  115. execsql {
  116. pragma auto_vacuum = 'full';
  117. pragma auto_vacuum;
  118. }
  119. } {1}
  120. #---------------------------------------------------------------------
  121. # Test that when the auto_vacuum mode is "incremental", the database
  122. # does not shrink when pages are removed from it. But it does if
  123. # the mode is set to "full".
  124. #
  125. do_test incrvacuum-3.1 {
  126. execsql {
  127. pragma auto_vacuum;
  128. }
  129. } {1}
  130. do_test incrvacuum-3.2 {
  131. set ::str [string repeat 1234567890 110]
  132. execsql {
  133. PRAGMA auto_vacuum = 2;
  134. BEGIN;
  135. CREATE TABLE tbl2(str);
  136. INSERT INTO tbl2 VALUES($::str);
  137. COMMIT;
  138. }
  139. # 5 pages:
  140. #
  141. # 1 -> database header
  142. # 2 -> first back-pointer page
  143. # 3 -> table abc
  144. # 4 -> table tbl2
  145. # 5 -> table tbl2 overflow page.
  146. #
  147. expr {[file size test.db] / 1024}
  148. } {5}
  149. do_test incrvacuum-3.3 {
  150. execsql {
  151. DROP TABLE abc;
  152. DELETE FROM tbl2;
  153. }
  154. expr {[file size test.db] / 1024}
  155. } {5}
  156. do_test incrvacuum-3.4 {
  157. execsql {
  158. PRAGMA auto_vacuum = 1;
  159. INSERT INTO tbl2 VALUES('hello world');
  160. }
  161. expr {[file size test.db] / 1024}
  162. } {3}
  163. #---------------------------------------------------------------------
  164. # Try to run a very simple incremental vacuum. Also verify that
  165. # PRAGMA incremental_vacuum is a harmless no-op against a database that
  166. # does not support auto-vacuum.
  167. #
  168. do_test incrvacuum-4.1 {
  169. set ::str [string repeat 1234567890 110]
  170. execsql {
  171. PRAGMA auto_vacuum = 2;
  172. INSERT INTO tbl2 VALUES($::str);
  173. CREATE TABLE tbl1(a, b, c);
  174. }
  175. expr {[file size test.db] / 1024}
  176. } {5}
  177. do_test incrvacuum-4.2 {
  178. execsql {
  179. DELETE FROM tbl2;
  180. DROP TABLE tbl1;
  181. }
  182. expr {[file size test.db] / 1024}
  183. } {5}
  184. do_test incrvacuum-4.3 {
  185. set ::nStep 0
  186. db eval {pragma incremental_vacuum(10)} {
  187. incr ::nStep
  188. }
  189. list [expr {[file size test.db] / 1024}] $::nStep
  190. } {3 2}
  191. #---------------------------------------------------------------------
  192. # The following tests - incrvacuum-5.* - test incremental vacuum
  193. # from within a transaction.
  194. #
  195. do_test incrvacuum-5.1.1 {
  196. expr {[file size test.db] / 1024}
  197. } {3}
  198. do_test incrvacuum-5.1.2 {
  199. execsql {
  200. BEGIN;
  201. DROP TABLE tbl2;
  202. PRAGMA incremental_vacuum;
  203. COMMIT;
  204. }
  205. expr {[file size test.db] / 1024}
  206. } {1}
  207. do_test incrvacuum-5.2.1 {
  208. set ::str [string repeat abcdefghij 110]
  209. execsql {
  210. BEGIN;
  211. CREATE TABLE tbl1(a);
  212. INSERT INTO tbl1 VALUES($::str);
  213. PRAGMA incremental_vacuum; -- this is a no-op.
  214. COMMIT;
  215. }
  216. expr {[file size test.db] / 1024}
  217. } {4}
  218. do_test incrvacuum-5.2.2 {
  219. set ::str [string repeat abcdefghij 110]
  220. execsql {
  221. BEGIN;
  222. INSERT INTO tbl1 VALUES($::str);
  223. INSERT INTO tbl1 SELECT * FROM tbl1;
  224. DELETE FROM tbl1 WHERE oid%2; -- Put 2 overflow pages on free-list.
  225. COMMIT;
  226. }
  227. expr {[file size test.db] / 1024}
  228. } {7}
  229. do_test incrvacuum-5.2.3 {
  230. execsql {
  231. BEGIN;
  232. PRAGMA incremental_vacuum; -- Vacuum up the two pages.
  233. CREATE TABLE tbl2(b); -- Use one free page as a table root.
  234. INSERT INTO tbl2 VALUES('a nice string');
  235. COMMIT;
  236. }
  237. expr {[file size test.db] / 1024}
  238. } {6}
  239. do_test incrvacuum-5.2.4 {
  240. execsql {
  241. SELECT * FROM tbl2;
  242. }
  243. } {{a nice string}}
  244. do_test incrvacuum-5.2.5 {
  245. execsql {
  246. DROP TABLE tbl1;
  247. DROP TABLE tbl2;
  248. PRAGMA incremental_vacuum;
  249. }
  250. expr {[file size test.db] / 1024}
  251. } {1}
  252. # Test cases incrvacuum-5.3.* use the following list as input data.
  253. # Two new databases are opened, one with incremental vacuum enabled,
  254. # the other with no auto-vacuum completely disabled. After executing
  255. # each element of the following list on both databases, test that
  256. # the integrity-check passes and the contents of each are identical.
  257. #
  258. set TestScriptList [list {
  259. BEGIN;
  260. CREATE TABLE t1(a, b);
  261. CREATE TABLE t2(a, b);
  262. CREATE INDEX t1_i ON t1(a);
  263. CREATE INDEX t2_i ON t2(a);
  264. } {
  265. INSERT INTO t1 VALUES($::str1, $::str2);
  266. INSERT INTO t1 VALUES($::str1||$::str2, $::str2||$::str1);
  267. INSERT INTO t2 SELECT b, a FROM t1;
  268. INSERT INTO t2 SELECT a, b FROM t1;
  269. INSERT INTO t1 SELECT b, a FROM t2;
  270. UPDATE t2 SET b = '';
  271. PRAGMA incremental_vacuum;
  272. } {
  273. UPDATE t2 SET b = (SELECT b FROM t1 WHERE t1.oid = t2.oid);
  274. PRAGMA incremental_vacuum;
  275. } {
  276. CREATE TABLE t3(a, b);
  277. INSERT INTO t3 SELECT * FROM t2;
  278. DROP TABLE t2;
  279. PRAGMA incremental_vacuum;
  280. } {
  281. CREATE INDEX t3_i ON t3(a);
  282. COMMIT;
  283. } {
  284. BEGIN;
  285. DROP INDEX t3_i;
  286. PRAGMA incremental_vacuum;
  287. INSERT INTO t3 VALUES('hello', 'world');
  288. ROLLBACK;
  289. } {
  290. INSERT INTO t3 VALUES('hello', 'world');
  291. }
  292. ]
  293. # If this build omits subqueries, step 2 in the above list will not
  294. # work. Replace it with "" in this case.
  295. #
  296. ifcapable !subquery { lset TestScriptList 2 "" }
  297. # Compare the contents of databases $A and $B.
  298. #
  299. proc compare_dbs {A B tname} {
  300. set tbl_list [execsql {
  301. SELECT tbl_name FROM sqlite_master WHERE type = 'table'
  302. } $A]
  303. do_test ${tname}.1 [subst {
  304. execsql {
  305. SELECT tbl_name FROM sqlite_master WHERE type = 'table'
  306. } $B
  307. }] $tbl_list
  308. set tn 1
  309. foreach tbl $tbl_list {
  310. set control [execsql "SELECT * FROM $tbl" $A]
  311. do_test ${tname}.[incr tn] [subst {
  312. execsql "SELECT * FROM $tbl" $B
  313. }] $control
  314. }
  315. }
  316. set ::str1 [string repeat abcdefghij 130]
  317. set ::str2 [string repeat 1234567890 105]
  318. forcedelete test1.db test1.db-journal test2.db test2.db-journal
  319. sqlite3 db1 test1.db
  320. sqlite3 db2 test2.db
  321. execsql { PRAGMA auto_vacuum = 'none' } db1
  322. execsql { PRAGMA auto_vacuum = 'incremental' } db2
  323. set tn 1
  324. foreach sql $::TestScriptList {
  325. execsql $sql db1
  326. execsql $sql db2
  327. compare_dbs db1 db2 incrvacuum-5.3.${tn}
  328. do_test incrvacuum-5.3.${tn}.integrity1 {
  329. execsql { PRAGMA integrity_check; } db1
  330. } {ok}
  331. do_test incrvacuum-5.3.${tn}.integrity2 {
  332. execsql { PRAGMA integrity_check; } db2
  333. } {ok}
  334. incr tn
  335. }
  336. db1 close
  337. db2 close
  338. #
  339. # End of test cases 5.3.*
  340. #---------------------------------------------------------------------
  341. # The following tests - incrvacuum-6.* - test running incremental
  342. # vacuum while another statement (a read) is being executed.
  343. #
  344. for {set jj 0} {$jj < 10} {incr jj} {
  345. # Build some test data. Two tables are created in an empty
  346. # database. tbl1 data is a contiguous block starting at page 5 (pages
  347. # 3 and 4 are the table roots). tbl2 is a contiguous block starting
  348. # right after tbl1.
  349. #
  350. # Then drop tbl1 so that when an incr vacuum is run the pages
  351. # of tbl2 have to be moved to fill the gap.
  352. #
  353. do_test incrvacuum-6.${jj}.1 {
  354. execsql {
  355. DROP TABLE IF EXISTS tbl1;
  356. DROP TABLE IF EXISTS tbl2;
  357. PRAGMA incremental_vacuum;
  358. CREATE TABLE tbl1(a, b);
  359. CREATE TABLE tbl2(a, b);
  360. BEGIN;
  361. }
  362. for {set ii 0} {$ii < 1000} {incr ii} {
  363. db eval {INSERT INTO tbl1 VALUES($ii, $ii || $ii)}
  364. }
  365. execsql {
  366. INSERT INTO tbl2 SELECT * FROM tbl1;
  367. COMMIT;
  368. DROP TABLE tbl1;
  369. }
  370. expr {[file size test.db] / 1024}
  371. } {36}
  372. # Run a linear scan query on tbl2. After reading ($jj*100) rows,
  373. # run the incremental vacuum to shrink the database.
  374. #
  375. do_test incrvacuum-6.${jj}.2 {
  376. set ::nRow 0
  377. db eval {SELECT a FROM tbl2} {} {
  378. if {$a == [expr $jj*100]} {
  379. db eval {PRAGMA incremental_vacuum}
  380. }
  381. incr ::nRow
  382. }
  383. list [expr {[file size test.db] / 1024}] $nRow
  384. } {19 1000}
  385. }
  386. #---------------------------------------------------------------------
  387. # This test - incrvacuum-7.* - is to check that the database can be
  388. # written in the middle of an incremental vacuum.
  389. #
  390. set ::iWrite 1
  391. while 1 {
  392. do_test incrvacuum-7.${::iWrite}.1 {
  393. execsql {
  394. DROP TABLE IF EXISTS tbl1;
  395. DROP TABLE IF EXISTS tbl2;
  396. PRAGMA incremental_vacuum;
  397. CREATE TABLE tbl1(a, b);
  398. CREATE TABLE tbl2(a, b);
  399. BEGIN;
  400. }
  401. for {set ii 0} {$ii < 1000} {incr ii} {
  402. db eval {INSERT INTO tbl1 VALUES($ii, $ii || $ii)}
  403. }
  404. execsql {
  405. INSERT INTO tbl2 SELECT * FROM tbl1;
  406. COMMIT;
  407. DROP TABLE tbl1;
  408. }
  409. expr {[file size test.db] / 1024}
  410. } {36}
  411. do_test incrvacuum-7.${::iWrite}.2 {
  412. set ::nRow 0
  413. db eval {PRAGMA incremental_vacuum} {
  414. incr ::nRow
  415. if {$::nRow == $::iWrite} {
  416. db eval {
  417. CREATE TABLE tbl1(a, b);
  418. INSERT INTO tbl1 VALUES('hello', 'world');
  419. }
  420. }
  421. }
  422. list [expr {[file size test.db] / 1024}]
  423. } {20}
  424. do_test incrvacuum-7.${::iWrite}.3 {
  425. execsql {
  426. SELECT * FROM tbl1;
  427. }
  428. } {hello world}
  429. if {$::nRow == $::iWrite} break
  430. incr ::iWrite
  431. }
  432. #---------------------------------------------------------------------
  433. # This test - incrvacuum-8.* - is to check that nothing goes wrong
  434. # with an incremental-vacuum if it is the first statement executed
  435. # after an existing database is opened.
  436. #
  437. # At one point, this would always return SQLITE_SCHEMA (which
  438. # causes an infinite loop in tclsqlite.c if using the Tcl interface).
  439. #
  440. do_test incrvacuum-8.1 {
  441. db close
  442. sqlite3 db test.db
  443. execsql {
  444. PRAGMA incremental_vacuum(50);
  445. }
  446. } {}
  447. #---------------------------------------------------------------------
  448. # At one point this test case was causing an assert() to fail.
  449. #
  450. do_test incrvacuum-9.1 {
  451. db close
  452. forcedelete test.db test.db-journal
  453. sqlite3 db test.db
  454. execsql {
  455. PRAGMA auto_vacuum = 'incremental';
  456. CREATE TABLE t1(a, b, c);
  457. CREATE TABLE t2(a, b, c);
  458. INSERT INTO t2 VALUES(randstr(500,500),randstr(500,500),randstr(500,500));
  459. INSERT INTO t1 VALUES(1, 2, 3);
  460. INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
  461. INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
  462. INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
  463. INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
  464. INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
  465. INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
  466. INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
  467. INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
  468. }
  469. } {}
  470. do_test incrvacuum-9.2 {
  471. execsql {
  472. PRAGMA synchronous = 'OFF';
  473. BEGIN;
  474. UPDATE t1 SET a = a, b = b, c = c;
  475. DROP TABLE t2;
  476. PRAGMA incremental_vacuum(10);
  477. ROLLBACK;
  478. }
  479. } {}
  480. do_test incrvacuum-9.3 {
  481. execsql {
  482. PRAGMA cache_size = 10;
  483. BEGIN;
  484. UPDATE t1 SET a = a, b = b, c = c;
  485. DROP TABLE t2;
  486. PRAGMA incremental_vacuum(10);
  487. ROLLBACK;
  488. }
  489. } {}
  490. #---------------------------------------------------------------------
  491. # Test that the parameter to the incremental_vacuum pragma works. That
  492. # is, if the user executes "PRAGMA incremental_vacuum(N)", at most
  493. # N pages are vacuumed.
  494. #
  495. do_test incrvacuum-10.1 {
  496. execsql {
  497. DROP TABLE t1;
  498. DROP TABLE t2;
  499. }
  500. expr [file size test.db] / 1024
  501. } {29}
  502. do_test incrvacuum-10.2 {
  503. execsql {
  504. PRAGMA incremental_vacuum(1);
  505. }
  506. expr [file size test.db] / 1024
  507. } {28}
  508. do_test incrvacuum-10.3 {
  509. execsql {
  510. PRAGMA incremental_vacuum(5);
  511. }
  512. expr [file size test.db] / 1024
  513. } {23}
  514. do_test incrvacuum-10.4 {
  515. execsql {
  516. PRAGMA incremental_vacuum('1');
  517. }
  518. expr [file size test.db] / 1024
  519. } {22}
  520. do_test incrvacuum-10.5 {
  521. execsql {
  522. PRAGMA incremental_vacuum("+3");
  523. }
  524. expr [file size test.db] / 1024
  525. } {19}
  526. do_test incrvacuum-10.6 {
  527. execsql {
  528. PRAGMA incremental_vacuum = 1;
  529. }
  530. expr [file size test.db] / 1024
  531. } {18}
  532. do_test incrvacuum-10.7 {
  533. # Use a really big number as an argument to incremetal_vacuum. Should
  534. # be interpreted as "free all possible space".
  535. execsql {
  536. PRAGMA incremental_vacuum(2147483649);
  537. }
  538. expr [file size test.db] / 1024
  539. } {1}
  540. do_test incrvacuum-10.8 {
  541. execsql {
  542. CREATE TABLE t1(x);
  543. INSERT INTO t1 VALUES(hex(randomblob(1000)));
  544. DROP TABLE t1;
  545. }
  546. # A negative number means free all possible space.
  547. execsql {
  548. PRAGMA incremental_vacuum=-1;
  549. }
  550. expr [file size test.db] / 1024
  551. } {1}
  552. #----------------------------------------------------------------
  553. # Test that if we set the auto_vacuum mode to 'incremental', then
  554. # create a database, thereafter that database defaults to incremental
  555. # vacuum mode.
  556. #
  557. db close
  558. forcedelete test.db test.db-journal
  559. sqlite3 db test.db
  560. ifcapable default_autovacuum {
  561. do_test incrvacuum-11.1-av-dflt-on {
  562. execsql {
  563. PRAGMA auto_vacuum;
  564. }
  565. } $AUTOVACUUM
  566. } else {
  567. do_test incrvacuum-11.1-av-dflt-off {
  568. execsql {
  569. PRAGMA auto_vacuum;
  570. }
  571. } {0}
  572. }
  573. do_test incrvacuum-11.2 {
  574. execsql {
  575. PRAGMA auto_vacuum = incremental;
  576. }
  577. } {}
  578. do_test incrvacuum-11.3 {
  579. execsql {
  580. PRAGMA auto_vacuum;
  581. }
  582. } {2}
  583. do_test incrvacuum-11.4 {
  584. # The database has now been created.
  585. expr {[file size test.db]>0}
  586. } {1}
  587. do_test incrvacuum-11.5 {
  588. # Close and reopen the connection.
  589. db close
  590. sqlite3 db test.db
  591. # Test we are still in incremental vacuum mode.
  592. execsql { PRAGMA auto_vacuum; }
  593. } {2}
  594. do_test incrvacuum-11.6 {
  595. execsql {
  596. PRAGMA auto_vacuum = 'full';
  597. PRAGMA auto_vacuum;
  598. }
  599. } {1}
  600. do_test incrvacuum-11.7 {
  601. # Close and reopen the connection.
  602. db close
  603. sqlite3 db test.db
  604. # Test we are still in "full" auto-vacuum mode.
  605. execsql { PRAGMA auto_vacuum; }
  606. } {1}
  607. #----------------------------------------------------------------------
  608. # Special case: What happens if the database is locked when a "PRAGMA
  609. # auto_vacuum = XXX" statement is executed.
  610. #
  611. db close
  612. forcedelete test.db test.db-journal
  613. sqlite3 db test.db
  614. do_test incrvacuum-12.1 {
  615. execsql {
  616. PRAGMA auto_vacuum = 1;
  617. }
  618. expr {[file size test.db]>0}
  619. } {1}
  620. # Try to change the auto-vacuum from "full" to "incremental" while the
  621. # database is locked. Nothing should change.
  622. #
  623. do_test incrvacuum-12.2 {
  624. sqlite3 db2 test.db
  625. execsql { BEGIN EXCLUSIVE; } db2
  626. catchsql { PRAGMA auto_vacuum = 2; }
  627. } {1 {database is locked}}
  628. do_test incrvacuum-12.3 {
  629. execsql { ROLLBACK; } db2
  630. execsql { PRAGMA auto_vacuum }
  631. } {2} ;# Still 2 because PRAGMA auto_vacuum setting held in case of vacuum
  632. do_test incrvacuum-12.4 {
  633. db close
  634. sqlite3 db test.db
  635. execsql { PRAGMA auto_vacuum }
  636. } {1} ;# Revert to 1 because the database file did not change
  637. do_test incrvacuum-12.5 {
  638. execsql { SELECT * FROM sqlite_master }
  639. execsql { PRAGMA auto_vacuum }
  640. } {1}
  641. #----------------------------------------------------------------------
  642. # Special case #2: What if one process prepares a "PRAGMA auto_vacuum = XXX"
  643. # statement when the database is empty, but doesn't execute it until
  644. # after some other process has created the database.
  645. #
  646. db2 close
  647. db close
  648. forcedelete test.db test.db-journal
  649. sqlite3 db test.db ; set ::DB [sqlite3_connection_pointer db]
  650. sqlite3 db2 test.db
  651. do_test incrvacuum-13.1 {
  652. # File size is sometimes 1 instead of 0 due to the hack we put in
  653. # to work around ticket #3260. Search for comments on #3260 in
  654. # os_unix.c.
  655. expr {[file size test.db]>1}
  656. } {0}
  657. do_test incrvacuum-13.2 {
  658. set ::STMT [sqlite3_prepare $::DB {PRAGMA auto_vacuum = 2} -1 DUMMY]
  659. execsql {
  660. PRAGMA auto_vacuum = none;
  661. PRAGMA default_cache_size = 1024;
  662. PRAGMA auto_vacuum;
  663. } db2
  664. } {0}
  665. do_test incrvacuum-13.3 {
  666. expr {[file size test.db]>0}
  667. } {1}
  668. do_test incrvacuum-13.4 {
  669. set rc [sqlite3_step $::STMT]
  670. list $rc [sqlite3_finalize $::STMT]
  671. } {SQLITE_DONE SQLITE_OK}
  672. do_test incrvacuum-13.5 {
  673. execsql {
  674. PRAGMA auto_vacuum;
  675. }
  676. } {0}
  677. # Verify that the incremental_vacuum pragma fails gracefully if it
  678. # is used against an invalid database file.
  679. #
  680. if {[permutation] == ""} {
  681. do_test incrvacuum-14.1 {
  682. set out [open invalid.db w]
  683. puts $out "This is not an SQLite database file"
  684. close $out
  685. sqlite3 db3 invalid.db
  686. catchsql {
  687. PRAGMA incremental_vacuum(10);
  688. } db3
  689. } {1 {file is encrypted or is not a database}}
  690. db3 close
  691. }
  692. do_test incrvacuum-15.1 {
  693. db close
  694. db2 close
  695. forcedelete test.db
  696. sqlite3 db test.db
  697. set str [string repeat "abcdefghij" 500]
  698. execsql {
  699. PRAGMA cache_size = 10;
  700. PRAGMA auto_vacuum = incremental;
  701. CREATE TABLE t1(x, y);
  702. INSERT INTO t1 VALUES('a', $str);
  703. INSERT INTO t1 VALUES('b', $str);
  704. INSERT INTO t1 VALUES('c', $str);
  705. INSERT INTO t1 VALUES('d', $str);
  706. INSERT INTO t1 VALUES('e', $str);
  707. INSERT INTO t1 VALUES('f', $str);
  708. INSERT INTO t1 VALUES('g', $str);
  709. INSERT INTO t1 VALUES('h', $str);
  710. INSERT INTO t1 VALUES('i', $str);
  711. INSERT INTO t1 VALUES('j', $str);
  712. INSERT INTO t1 VALUES('j', $str);
  713. CREATE TABLE t2(x PRIMARY KEY, y);
  714. INSERT INTO t2 VALUES('a', $str);
  715. INSERT INTO t2 VALUES('b', $str);
  716. INSERT INTO t2 VALUES('c', $str);
  717. INSERT INTO t2 VALUES('d', $str);
  718. BEGIN;
  719. DELETE FROM t2;
  720. PRAGMA incremental_vacuum;
  721. }
  722. catchsql {INSERT INTO t2 SELECT * FROM t1}
  723. execsql {
  724. COMMIT;
  725. PRAGMA integrity_check;
  726. }
  727. } {ok}
  728. finish_test