vacuum.test 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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 SQLite library. The
  12. # focus of this file is testing the VACUUM statement.
  13. #
  14. # $Id: vacuum.test,v 1.43 2009/01/31 14:54:07 danielk1977 Exp $
  15. set testdir [file dirname $argv0]
  16. source $testdir/tester.tcl
  17. # If the VACUUM statement is disabled in the current build, skip all
  18. # the tests in this file.
  19. #
  20. ifcapable {!vacuum} {
  21. omit_test vacuum.test {Compiled with SQLITE_OMIT_VACUUM}
  22. finish_test
  23. return
  24. }
  25. if $AUTOVACUUM {
  26. omit_test vacuum.test {Auto-vacuum is enabled}
  27. finish_test
  28. return
  29. }
  30. set fcnt 1
  31. do_test vacuum-1.1 {
  32. execsql {
  33. BEGIN;
  34. CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  35. INSERT INTO t1 VALUES(NULL,randstr(10,100),randstr(5,50));
  36. INSERT INTO t1 VALUES(123456,randstr(10,100),randstr(5,50));
  37. INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
  38. INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
  39. INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
  40. INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
  41. INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
  42. INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
  43. INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1;
  44. CREATE INDEX i1 ON t1(b,c);
  45. CREATE UNIQUE INDEX i2 ON t1(c,a);
  46. CREATE TABLE t2 AS SELECT * FROM t1;
  47. COMMIT;
  48. DROP TABLE t2;
  49. }
  50. set ::size1 [file size test.db]
  51. set ::cksum [cksum]
  52. expr {$::cksum!=""}
  53. } {1}
  54. # Create bogus application-defined functions for functions used
  55. # internally by VACUUM, to ensure that VACUUM falls back
  56. # to the built-in functions.
  57. #
  58. proc failing_app_func {args} {error "bad function"}
  59. do_test vacuum-1.1b {
  60. db func substr failing_app_func
  61. db func like failing_app_func
  62. db func quote failing_app_func
  63. catchsql {SELECT substr(name,1,3) FROM sqlite_master}
  64. } {1 {bad function}}
  65. do_test vacuum-1.2 {
  66. execsql {
  67. VACUUM;
  68. }
  69. cksum
  70. } $cksum
  71. ifcapable vacuum {
  72. do_test vacuum-1.3 {
  73. expr {[file size test.db]<$::size1}
  74. } {1}
  75. }
  76. do_test vacuum-1.4 {
  77. set sql_script {
  78. BEGIN;
  79. CREATE TABLE t2 AS SELECT * FROM t1;
  80. CREATE TABLE t3 AS SELECT * FROM t1;
  81. CREATE VIEW v1 AS SELECT b, c FROM t3;
  82. CREATE TRIGGER r1 AFTER DELETE ON t2 BEGIN SELECT 1; END;
  83. COMMIT;
  84. DROP TABLE t2;
  85. }
  86. # If the library was compiled to omit view support, comment out the
  87. # create view in the script $sql_script before executing it. Similarly,
  88. # if triggers are not supported, comment out the trigger definition.
  89. ifcapable !view {
  90. regsub {CREATE VIEW} $sql_script {-- CREATE VIEW} sql_script
  91. }
  92. ifcapable !trigger {
  93. regsub {CREATE TRIGGER} $sql_script {-- CREATE TRIGGER} sql_script
  94. }
  95. execsql $sql_script
  96. set ::size1 [file size test.db]
  97. set ::cksum [cksum]
  98. expr {$::cksum!=""}
  99. } {1}
  100. do_test vacuum-1.5 {
  101. execsql {
  102. VACUUM;
  103. }
  104. cksum
  105. } $cksum
  106. ifcapable vacuum {
  107. do_test vacuum-1.6 {
  108. expr {[file size test.db]<$::size1}
  109. } {1}
  110. }
  111. ifcapable vacuum {
  112. do_test vacuum-2.1.1 {
  113. catchsql {
  114. BEGIN;
  115. VACUUM;
  116. }
  117. } {1 {cannot VACUUM from within a transaction}}
  118. do_test vacuum-2.1.2 {
  119. sqlite3_get_autocommit db
  120. } {0}
  121. do_test vacuum-2.1.3 {
  122. db eval {COMMIT}
  123. } {}
  124. }
  125. do_test vacuum-2.2 {
  126. sqlite3 db2 test.db
  127. execsql {
  128. BEGIN;
  129. CREATE TABLE t4 AS SELECT * FROM t1;
  130. CREATE TABLE t5 AS SELECT * FROM t1;
  131. COMMIT;
  132. DROP TABLE t4;
  133. DROP TABLE t5;
  134. } db2
  135. set ::cksum [cksum db2]
  136. catchsql {
  137. VACUUM
  138. }
  139. } {0 {}}
  140. do_test vacuum-2.3 {
  141. cksum
  142. } $cksum
  143. do_test vacuum-2.4 {
  144. catch {db2 eval {SELECT count(*) FROM sqlite_master}}
  145. cksum db2
  146. } $cksum
  147. # Make sure the schema cookie is incremented by vacuum.
  148. #
  149. do_test vacuum-2.5 {
  150. execsql {
  151. BEGIN;
  152. CREATE TABLE t6 AS SELECT * FROM t1;
  153. CREATE TABLE t7 AS SELECT * FROM t1;
  154. COMMIT;
  155. }
  156. sqlite3 db3 test.db
  157. execsql {
  158. -- The "SELECT * FROM sqlite_master" statement ensures that this test
  159. -- works when shared-cache is enabled. If shared-cache is enabled, then
  160. -- db3 shares a cache with db2 (but not db - it was opened as
  161. -- "./test.db").
  162. SELECT * FROM sqlite_master;
  163. SELECT * FROM t7 LIMIT 1
  164. } db3
  165. execsql {
  166. VACUUM;
  167. }
  168. execsql {
  169. INSERT INTO t7 VALUES(1234567890,'hello','world');
  170. } db3
  171. execsql {
  172. SELECT * FROM t7 WHERE a=1234567890
  173. }
  174. } {1234567890 hello world}
  175. integrity_check vacuum-2.6
  176. do_test vacuum-2.7 {
  177. execsql {
  178. SELECT * FROM t7 WHERE a=1234567890
  179. } db3
  180. } {1234567890 hello world}
  181. do_test vacuum-2.8 {
  182. execsql {
  183. INSERT INTO t7 SELECT * FROM t6;
  184. SELECT count(*) FROM t7;
  185. }
  186. } 513
  187. integrity_check vacuum-2.9
  188. do_test vacuum-2.10 {
  189. execsql {
  190. DELETE FROM t7;
  191. SELECT count(*) FROM t7;
  192. } db3
  193. } 0
  194. integrity_check vacuum-2.11
  195. db3 close
  196. # Ticket #427. Make sure VACUUM works when the EMPTY_RESULT_CALLBACKS
  197. # pragma is turned on.
  198. #
  199. do_test vacuum-3.1 {
  200. db close
  201. db2 close
  202. delete_file test.db
  203. sqlite3 db test.db
  204. execsql {
  205. PRAGMA empty_result_callbacks=on;
  206. VACUUM;
  207. }
  208. } {}
  209. # Ticket #464. Make sure VACUUM works with the sqlite3_prepare() API.
  210. #
  211. do_test vacuum-4.1 {
  212. db close
  213. sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
  214. set VM [sqlite3_prepare $DB {VACUUM} -1 TAIL]
  215. sqlite3_step $VM
  216. } {SQLITE_DONE}
  217. do_test vacuum-4.2 {
  218. sqlite3_finalize $VM
  219. } SQLITE_OK
  220. # Ticket #515. VACUUM after deleting and recreating the table that
  221. # a view refers to. Omit this test if the library is not view-enabled.
  222. #
  223. ifcapable view {
  224. do_test vacuum-5.1 {
  225. db close
  226. forcedelete test.db
  227. sqlite3 db test.db
  228. catchsql {
  229. CREATE TABLE Test (TestID int primary key);
  230. INSERT INTO Test VALUES (NULL);
  231. CREATE VIEW viewTest AS SELECT * FROM Test;
  232. BEGIN;
  233. CREATE TABLE tempTest (TestID int primary key, Test2 int NULL);
  234. INSERT INTO tempTest SELECT TestID, 1 FROM Test;
  235. DROP TABLE Test;
  236. CREATE TABLE Test(TestID int primary key, Test2 int NULL);
  237. INSERT INTO Test SELECT * FROM tempTest;
  238. DROP TABLE tempTest;
  239. COMMIT;
  240. VACUUM;
  241. }
  242. } {0 {}}
  243. do_test vacuum-5.2 {
  244. catchsql {
  245. VACUUM;
  246. }
  247. } {0 {}}
  248. } ;# ifcapable view
  249. # Ensure vacuum works with complicated tables names.
  250. do_test vacuum-6.1 {
  251. execsql {
  252. CREATE TABLE "abc abc"(a, b, c);
  253. INSERT INTO "abc abc" VALUES(1, 2, 3);
  254. VACUUM;
  255. }
  256. } {}
  257. do_test vacuum-6.2 {
  258. execsql {
  259. select * from "abc abc";
  260. }
  261. } {1 2 3}
  262. # Also ensure that blobs survive a vacuum.
  263. ifcapable {bloblit} {
  264. do_test vacuum-6.3 {
  265. execsql {
  266. DELETE FROM "abc abc";
  267. INSERT INTO "abc abc" VALUES(X'00112233', NULL, NULL);
  268. VACUUM;
  269. }
  270. } {}
  271. do_test vacuum-6.4 {
  272. execsql {
  273. select count(*) from "abc abc" WHERE a = X'00112233';
  274. }
  275. } {1}
  276. }
  277. # Check what happens when an in-memory database is vacuumed. The
  278. # [delete_file] command covers us in case the library was compiled
  279. # without in-memory database support.
  280. #
  281. forcedelete :memory:
  282. do_test vacuum-7.0 {
  283. sqlite3 db2 :memory:
  284. execsql {
  285. CREATE TABLE t1(t);
  286. VACUUM;
  287. } db2
  288. } {}
  289. do_test vacuum-7.1 {
  290. execsql {
  291. CREATE TABLE t2(t);
  292. CREATE TABLE t3(t);
  293. DROP TABLE t2;
  294. PRAGMA freelist_count;
  295. }
  296. } {1}
  297. do_test vacuum-7.2 {
  298. execsql {
  299. VACUUM;
  300. pragma integrity_check;
  301. } db2
  302. } {ok}
  303. do_test vacuum-7.3 {
  304. execsql { PRAGMA freelist_count; } db2
  305. } {0}
  306. ifcapable autovacuum {
  307. do_test vacuum-7.4 {
  308. execsql { PRAGMA auto_vacuum } db2
  309. } {0}
  310. do_test vacuum-7.5 {
  311. execsql { PRAGMA auto_vacuum = 1} db2
  312. execsql { PRAGMA auto_vacuum } db2
  313. } {0}
  314. do_test vacuum-7.6 {
  315. execsql { PRAGMA auto_vacuum = 1} db2
  316. execsql { VACUUM } db2
  317. execsql { PRAGMA auto_vacuum } db2
  318. } {1}
  319. }
  320. db2 close
  321. # Ticket #873. VACUUM a database that has ' in its name.
  322. #
  323. do_test vacuum-8.1 {
  324. forcedelete a'z.db
  325. forcedelete a'z.db-journal
  326. sqlite3 db2 a'z.db
  327. execsql {
  328. CREATE TABLE t1(t);
  329. VACUUM;
  330. } db2
  331. } {}
  332. db2 close
  333. # Ticket #1095: Vacuum a table that uses AUTOINCREMENT
  334. #
  335. ifcapable {autoinc} {
  336. do_test vacuum-9.1 {
  337. execsql {
  338. DROP TABLE 'abc abc';
  339. CREATE TABLE autoinc(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
  340. INSERT INTO autoinc(b) VALUES('hi');
  341. INSERT INTO autoinc(b) VALUES('there');
  342. DELETE FROM autoinc;
  343. }
  344. set ::cksum [cksum]
  345. expr {$::cksum!=""}
  346. } {1}
  347. do_test vacuum-9.2 {
  348. execsql {
  349. VACUUM;
  350. }
  351. cksum
  352. } $::cksum
  353. do_test vacuum-9.3 {
  354. execsql {
  355. INSERT INTO autoinc(b) VALUES('one');
  356. INSERT INTO autoinc(b) VALUES('two');
  357. }
  358. set ::cksum [cksum]
  359. expr {$::cksum!=""}
  360. } {1}
  361. do_test vacuum-9.4 {
  362. execsql {
  363. VACUUM;
  364. }
  365. cksum
  366. } $::cksum
  367. }
  368. forcedelete {a'z.db}
  369. # Test that "PRAGMA count_changes" does not interfere with VACUUM or cause
  370. # it to return any rows to the user.
  371. #
  372. do_test vacuum-10.1 {
  373. db close
  374. forcedelete test.db
  375. sqlite3 db test.db
  376. execsql {
  377. CREATE TABLE t8(a, b);
  378. INSERT INTO t8 VALUES('a', 'b');
  379. INSERT INTO t8 VALUES('c', 'd');
  380. PRAGMA count_changes = 1;
  381. }
  382. } {}
  383. do_test vacuum-10.2 { execsql VACUUM } {}
  384. finish_test