sl@0: # 2001 September 15 sl@0: # sl@0: # The author disclaims copyright to this source code. In place of sl@0: # a legal notice, here is a blessing: sl@0: # sl@0: # May you do good and not evil. sl@0: # May you find forgiveness for yourself and forgive others. sl@0: # May you share freely, never taking more than you give. sl@0: # sl@0: #*********************************************************************** sl@0: # This file implements regression tests for SQLite library. The sl@0: # focus of this file is testing the VACUUM statement. sl@0: # sl@0: # $Id: vacuum.test,v 1.41 2008/04/15 02:36:34 drh Exp $ sl@0: sl@0: set testdir [file dirname $argv0] sl@0: source $testdir/tester.tcl sl@0: sl@0: # If the VACUUM statement is disabled in the current build, skip all sl@0: # the tests in this file. sl@0: # sl@0: ifcapable {!vacuum} { sl@0: omit_test vacuum.test {Compiled with SQLITE_OMIT_VACUUM} sl@0: finish_test sl@0: return sl@0: } sl@0: if $AUTOVACUUM { sl@0: omit_test vacuum.test {Auto-vacuum is enabled} sl@0: finish_test sl@0: return sl@0: } sl@0: sl@0: set fcnt 1 sl@0: do_test vacuum-1.1 { sl@0: execsql { sl@0: BEGIN; sl@0: CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); sl@0: INSERT INTO t1 VALUES(NULL,randstr(10,100),randstr(5,50)); sl@0: INSERT INTO t1 VALUES(123456,randstr(10,100),randstr(5,50)); sl@0: INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; sl@0: INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; sl@0: INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; sl@0: INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; sl@0: INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; sl@0: INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; sl@0: INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; sl@0: CREATE INDEX i1 ON t1(b,c); sl@0: CREATE UNIQUE INDEX i2 ON t1(c,a); sl@0: CREATE TABLE t2 AS SELECT * FROM t1; sl@0: COMMIT; sl@0: DROP TABLE t2; sl@0: } sl@0: set ::size1 [file size test.db] sl@0: set ::cksum [cksum] sl@0: expr {$::cksum!=""} sl@0: } {1} sl@0: do_test vacuum-1.2 { sl@0: execsql { sl@0: VACUUM; sl@0: } sl@0: cksum sl@0: } $cksum sl@0: ifcapable vacuum { sl@0: do_test vacuum-1.3 { sl@0: expr {[file size test.db]<$::size1} sl@0: } {1} sl@0: } sl@0: do_test vacuum-1.4 { sl@0: set sql_script { sl@0: BEGIN; sl@0: CREATE TABLE t2 AS SELECT * FROM t1; sl@0: CREATE TABLE t3 AS SELECT * FROM t1; sl@0: CREATE VIEW v1 AS SELECT b, c FROM t3; sl@0: CREATE TRIGGER r1 AFTER DELETE ON t2 BEGIN SELECT 1; END; sl@0: COMMIT; sl@0: DROP TABLE t2; sl@0: } sl@0: # If the library was compiled to omit view support, comment out the sl@0: # create view in the script $sql_script before executing it. Similarly, sl@0: # if triggers are not supported, comment out the trigger definition. sl@0: ifcapable !view { sl@0: regsub {CREATE VIEW} $sql_script {-- CREATE VIEW} sql_script sl@0: } sl@0: ifcapable !trigger { sl@0: regsub {CREATE TRIGGER} $sql_script {-- CREATE TRIGGER} sql_script sl@0: } sl@0: execsql $sql_script sl@0: set ::size1 [file size test.db] sl@0: set ::cksum [cksum] sl@0: expr {$::cksum!=""} sl@0: } {1} sl@0: do_test vacuum-1.5 { sl@0: execsql { sl@0: VACUUM; sl@0: } sl@0: cksum sl@0: } $cksum sl@0: sl@0: ifcapable vacuum { sl@0: do_test vacuum-1.6 { sl@0: expr {[file size test.db]<$::size1} sl@0: } {1} sl@0: } sl@0: ifcapable vacuum { sl@0: do_test vacuum-2.1 { sl@0: catchsql { sl@0: BEGIN; sl@0: VACUUM; sl@0: COMMIT; sl@0: } sl@0: } {1 {cannot VACUUM from within a transaction}} sl@0: catch {db eval COMMIT} sl@0: } sl@0: do_test vacuum-2.2 { sl@0: sqlite3 db2 test.db sl@0: execsql { sl@0: BEGIN; sl@0: CREATE TABLE t4 AS SELECT * FROM t1; sl@0: CREATE TABLE t5 AS SELECT * FROM t1; sl@0: COMMIT; sl@0: DROP TABLE t4; sl@0: DROP TABLE t5; sl@0: } db2 sl@0: set ::cksum [cksum db2] sl@0: catchsql { sl@0: VACUUM sl@0: } sl@0: } {0 {}} sl@0: do_test vacuum-2.3 { sl@0: cksum sl@0: } $cksum sl@0: do_test vacuum-2.4 { sl@0: catch {db2 eval {SELECT count(*) FROM sqlite_master}} sl@0: cksum db2 sl@0: } $cksum sl@0: sl@0: # Make sure the schema cookie is incremented by vacuum. sl@0: # sl@0: do_test vacuum-2.5 { sl@0: execsql { sl@0: BEGIN; sl@0: CREATE TABLE t6 AS SELECT * FROM t1; sl@0: CREATE TABLE t7 AS SELECT * FROM t1; sl@0: COMMIT; sl@0: } sl@0: sqlite3 db3 test.db sl@0: execsql { sl@0: -- The "SELECT * FROM sqlite_master" statement ensures that this test sl@0: -- works when shared-cache is enabled. If shared-cache is enabled, then sl@0: -- db3 shares a cache with db2 (but not db - it was opened as sl@0: -- "./test.db"). sl@0: SELECT * FROM sqlite_master; sl@0: SELECT * FROM t7 LIMIT 1 sl@0: } db3 sl@0: execsql { sl@0: VACUUM; sl@0: } sl@0: execsql { sl@0: INSERT INTO t7 VALUES(1234567890,'hello','world'); sl@0: } db3 sl@0: execsql { sl@0: SELECT * FROM t7 WHERE a=1234567890 sl@0: } sl@0: } {1234567890 hello world} sl@0: integrity_check vacuum-2.6 sl@0: do_test vacuum-2.7 { sl@0: execsql { sl@0: SELECT * FROM t7 WHERE a=1234567890 sl@0: } db3 sl@0: } {1234567890 hello world} sl@0: do_test vacuum-2.8 { sl@0: execsql { sl@0: INSERT INTO t7 SELECT * FROM t6; sl@0: SELECT count(*) FROM t7; sl@0: } sl@0: } 513 sl@0: integrity_check vacuum-2.9 sl@0: do_test vacuum-2.10 { sl@0: execsql { sl@0: DELETE FROM t7; sl@0: SELECT count(*) FROM t7; sl@0: } db3 sl@0: } 0 sl@0: integrity_check vacuum-2.11 sl@0: db3 close sl@0: sl@0: sl@0: # Ticket #427. Make sure VACUUM works when the EMPTY_RESULT_CALLBACKS sl@0: # pragma is turned on. sl@0: # sl@0: do_test vacuum-3.1 { sl@0: db close sl@0: db2 close sl@0: file delete test.db sl@0: sqlite3 db test.db sl@0: execsql { sl@0: PRAGMA empty_result_callbacks=on; sl@0: VACUUM; sl@0: } sl@0: } {} sl@0: sl@0: # Ticket #464. Make sure VACUUM works with the sqlite3_prepare() API. sl@0: # sl@0: do_test vacuum-4.1 { sl@0: db close sl@0: sqlite3 db test.db; set DB [sqlite3_connection_pointer db] sl@0: set VM [sqlite3_prepare $DB {VACUUM} -1 TAIL] sl@0: sqlite3_step $VM sl@0: } {SQLITE_DONE} sl@0: do_test vacuum-4.2 { sl@0: sqlite3_finalize $VM sl@0: } SQLITE_OK sl@0: sl@0: # Ticket #515. VACUUM after deleting and recreating the table that sl@0: # a view refers to. Omit this test if the library is not view-enabled. sl@0: # sl@0: ifcapable view { sl@0: do_test vacuum-5.1 { sl@0: db close sl@0: file delete -force test.db sl@0: sqlite3 db test.db sl@0: catchsql { sl@0: CREATE TABLE Test (TestID int primary key); sl@0: INSERT INTO Test VALUES (NULL); sl@0: CREATE VIEW viewTest AS SELECT * FROM Test; sl@0: sl@0: BEGIN; sl@0: CREATE TABLE tempTest (TestID int primary key, Test2 int NULL); sl@0: INSERT INTO tempTest SELECT TestID, 1 FROM Test; sl@0: DROP TABLE Test; sl@0: CREATE TABLE Test(TestID int primary key, Test2 int NULL); sl@0: INSERT INTO Test SELECT * FROM tempTest; sl@0: DROP TABLE tempTest; sl@0: COMMIT; sl@0: VACUUM; sl@0: } sl@0: } {0 {}} sl@0: do_test vacuum-5.2 { sl@0: catchsql { sl@0: VACUUM; sl@0: } sl@0: } {0 {}} sl@0: } ;# ifcapable view sl@0: sl@0: # Ensure vacuum works with complicated tables names. sl@0: do_test vacuum-6.1 { sl@0: execsql { sl@0: CREATE TABLE "abc abc"(a, b, c); sl@0: INSERT INTO "abc abc" VALUES(1, 2, 3); sl@0: VACUUM; sl@0: } sl@0: } {} sl@0: do_test vacuum-6.2 { sl@0: execsql { sl@0: select * from "abc abc"; sl@0: } sl@0: } {1 2 3} sl@0: sl@0: # Also ensure that blobs survive a vacuum. sl@0: ifcapable {bloblit} { sl@0: do_test vacuum-6.3 { sl@0: execsql { sl@0: DELETE FROM "abc abc"; sl@0: INSERT INTO "abc abc" VALUES(X'00112233', NULL, NULL); sl@0: VACUUM; sl@0: } sl@0: } {} sl@0: do_test vacuum-6.4 { sl@0: execsql { sl@0: select count(*) from "abc abc" WHERE a = X'00112233'; sl@0: } sl@0: } {1} sl@0: } sl@0: sl@0: # Check what happens when an in-memory database is vacuumed. The sl@0: # [file delete] command covers us in case the library was compiled sl@0: # without in-memory database support. sl@0: # sl@0: file delete -force :memory: sl@0: do_test vacuum-7.0 { sl@0: sqlite3 db2 :memory: sl@0: execsql { sl@0: CREATE TABLE t1(t); sl@0: VACUUM; sl@0: } db2 sl@0: } {} sl@0: db2 close sl@0: sl@0: # Ticket #873. VACUUM a database that has ' in its name. sl@0: # sl@0: do_test vacuum-8.1 { sl@0: file delete -force a'z.db sl@0: file delete -force a'z.db-journal sl@0: sqlite3 db2 a'z.db sl@0: execsql { sl@0: CREATE TABLE t1(t); sl@0: VACUUM; sl@0: } db2 sl@0: } {} sl@0: db2 close sl@0: sl@0: # Ticket #1095: Vacuum a table that uses AUTOINCREMENT sl@0: # sl@0: ifcapable {autoinc} { sl@0: do_test vacuum-9.1 { sl@0: execsql { sl@0: DROP TABLE 'abc abc'; sl@0: CREATE TABLE autoinc(a INTEGER PRIMARY KEY AUTOINCREMENT, b); sl@0: INSERT INTO autoinc(b) VALUES('hi'); sl@0: INSERT INTO autoinc(b) VALUES('there'); sl@0: DELETE FROM autoinc; sl@0: } sl@0: set ::cksum [cksum] sl@0: expr {$::cksum!=""} sl@0: } {1} sl@0: do_test vacuum-9.2 { sl@0: execsql { sl@0: VACUUM; sl@0: } sl@0: cksum sl@0: } $::cksum sl@0: do_test vacuum-9.3 { sl@0: execsql { sl@0: INSERT INTO autoinc(b) VALUES('one'); sl@0: INSERT INTO autoinc(b) VALUES('two'); sl@0: } sl@0: set ::cksum [cksum] sl@0: expr {$::cksum!=""} sl@0: } {1} sl@0: do_test vacuum-9.4 { sl@0: execsql { sl@0: VACUUM; sl@0: } sl@0: cksum sl@0: } $::cksum sl@0: } sl@0: sl@0: file delete -force {a'z.db} sl@0: sl@0: finish_test