summaryrefslogtreecommitdiffstats
path: root/test/trans.test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:28:19 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:28:19 +0000
commit18657a960e125336f704ea058e25c27bd3900dcb (patch)
tree17b438b680ed45a996d7b59951e6aa34023783f2 /test/trans.test
parentInitial commit. (diff)
downloadsqlite3-upstream.tar.xz
sqlite3-upstream.zip
Adding upstream version 3.40.1.upstream/3.40.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'test/trans.test')
-rw-r--r--test/trans.test994
1 files changed, 994 insertions, 0 deletions
diff --git a/test/trans.test b/test/trans.test
new file mode 100644
index 0000000..6b8ad21
--- /dev/null
+++ b/test/trans.test
@@ -0,0 +1,994 @@
+# 2001 September 15
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is database locks.
+#
+
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Create several tables to work with.
+#
+wal_set_journal_mode
+do_test trans-1.0 {
+ execsql {
+ CREATE TABLE one(a int PRIMARY KEY, b text);
+ INSERT INTO one VALUES(1,'one');
+ INSERT INTO one VALUES(2,'two');
+ INSERT INTO one VALUES(3,'three');
+ SELECT b FROM one ORDER BY a;
+ }
+} {one two three}
+integrity_check trans-1.0.1
+do_test trans-1.1 {
+ execsql {
+ CREATE TABLE two(a int PRIMARY KEY, b text);
+ INSERT INTO two VALUES(1,'I');
+ INSERT INTO two VALUES(5,'V');
+ INSERT INTO two VALUES(10,'X');
+ SELECT b FROM two ORDER BY a;
+ }
+} {I V X}
+do_test trans-1.2.1 {
+ sqlite3_txn_state db
+} {0}
+do_test trans-1.2.2 {
+ sqlite3_txn_state db main
+} {0}
+do_test trans-1.2.3 {
+ sqlite3_txn_state db temp
+} {0}
+do_test trans-1.2.4 {
+ sqlite3_txn_state db no-such-schema
+} {-1}
+
+do_test trans-1.9 {
+ sqlite3 altdb test.db
+ execsql {SELECT b FROM one ORDER BY a} altdb
+} {one two three}
+do_test trans-1.10 {
+ execsql {SELECT b FROM two ORDER BY a} altdb
+} {I V X}
+integrity_check trans-1.11
+wal_check_journal_mode trans-1.12
+
+# Basic transactions
+#
+do_test trans-2.1 {
+ set v [catch {execsql {BEGIN}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.1b {
+ sqlite3_txn_state db
+} {0}
+do_test trans-2.2 {
+ set v [catch {execsql {END}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.3 {
+ set v [catch {execsql {BEGIN TRANSACTION}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.4 {
+ set v [catch {execsql {COMMIT TRANSACTION}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.5 {
+ set v [catch {execsql {BEGIN TRANSACTION 'foo'}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.6 {
+ set v [catch {execsql {ROLLBACK TRANSACTION 'foo'}} msg]
+ lappend v $msg
+} {0 {}}
+do_test trans-2.10 {
+ execsql {
+ BEGIN;
+ SELECT a FROM one ORDER BY a;
+ SELECT a FROM two ORDER BY a;
+ END;
+ }
+} {1 2 3 1 5 10}
+integrity_check trans-2.11
+wal_check_journal_mode trans-2.12
+
+# Check the locking behavior
+#
+do_test trans-3.1 {
+ execsql {
+ BEGIN;
+ UPDATE one SET a = 0 WHERE 0;
+ SELECT a FROM one ORDER BY a;
+ }
+} {1 2 3}
+do_test trans-3.1b {
+ sqlite3_txn_state db
+} {2}
+do_test trans-3.1c {
+ sqlite3_txn_state db main
+} {2}
+do_test trans-3.1d {
+ sqlite3_txn_state db temp
+} {0}
+
+do_test trans-3.2 {
+ catchsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb
+} {0 {1 5 10}}
+
+do_test trans-3.3 {
+ catchsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb
+} {0 {1 2 3}}
+do_test trans-3.4 {
+ catchsql {
+ INSERT INTO one VALUES(4,'four');
+ }
+} {0 {}}
+do_test trans-3.5 {
+ catchsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb
+} {0 {1 5 10}}
+do_test trans-3.6 {
+ catchsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb
+} {0 {1 2 3}}
+do_test trans-3.7 {
+ catchsql {
+ INSERT INTO two VALUES(4,'IV');
+ }
+} {0 {}}
+do_test trans-3.8 {
+ catchsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb
+} {0 {1 5 10}}
+do_test trans-3.9 {
+ catchsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb
+} {0 {1 2 3}}
+do_test trans-3.10 {
+ execsql {END TRANSACTION}
+} {}
+do_test trans-3.10b {
+ sqlite3_txn_state db
+} {0}
+
+
+do_test trans-3.11 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {0 {1 4 5 10}}
+do_test trans-3.12 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {0 {1 2 3 4}}
+do_test trans-3.13 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } db} msg]
+ lappend v $msg
+} {0 {1 4 5 10}}
+do_test trans-3.14 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } db} msg]
+ lappend v $msg
+} {0 {1 2 3 4}}
+integrity_check trans-3.15
+wal_check_journal_mode trans-3.16
+
+do_test trans-4.1 {
+ set v [catch {execsql {
+ COMMIT;
+ } db} msg]
+ lappend v $msg
+} {1 {cannot commit - no transaction is active}}
+do_test trans-4.2 {
+ set v [catch {execsql {
+ ROLLBACK;
+ } db} msg]
+ lappend v $msg
+} {1 {cannot rollback - no transaction is active}}
+do_test trans-4.3 {
+ catchsql {
+ BEGIN TRANSACTION;
+ UPDATE two SET a = 0 WHERE 0;
+ SELECT a FROM two ORDER BY a;
+ } db
+} {0 {1 4 5 10}}
+do_test trans-4.4 {
+ catchsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb
+} {0 {1 4 5 10}}
+do_test trans-4.5 {
+ catchsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb
+} {0 {1 2 3 4}}
+do_test trans-4.6 {
+ catchsql {
+ BEGIN TRANSACTION;
+ SELECT a FROM one ORDER BY a;
+ } db
+} {1 {cannot start a transaction within a transaction}}
+do_test trans-4.7 {
+ catchsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb
+} {0 {1 4 5 10}}
+do_test trans-4.8 {
+ catchsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb
+} {0 {1 2 3 4}}
+do_test trans-4.9 {
+ set v [catch {execsql {
+ END TRANSACTION;
+ SELECT a FROM two ORDER BY a;
+ } db} msg]
+ lappend v $msg
+} {0 {1 4 5 10}}
+do_test trans-4.10 {
+ set v [catch {execsql {
+ SELECT a FROM two ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {0 {1 4 5 10}}
+do_test trans-4.11 {
+ set v [catch {execsql {
+ SELECT a FROM one ORDER BY a;
+ } altdb} msg]
+ lappend v $msg
+} {0 {1 2 3 4}}
+integrity_check trans-4.12
+wal_check_journal_mode trans-4.13
+wal_check_journal_mode trans-4.14 altdb
+do_test trans-4.98 {
+ altdb close
+ execsql {
+ DROP TABLE one;
+ DROP TABLE two;
+ }
+} {}
+integrity_check trans-4.99
+
+# Check out the commit/rollback behavior of the database
+#
+do_test trans-5.1 {
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
+} {}
+do_test trans-5.2 {
+ execsql {BEGIN TRANSACTION}
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
+} {}
+do_test trans-5.2b {
+ sqlite3_txn_state db
+} {1}
+do_test trans-5.2c {
+ sqlite3_txn_state db main
+} {1}
+do_test trans-5.2d {
+ sqlite3_txn_state db temp
+} {0}
+do_test trans-5.3 {
+ execsql {CREATE TABLE one(a text, b int)}
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
+} {one}
+do_test trans-5.4 {
+ execsql {SELECT a,b FROM one ORDER BY b}
+} {}
+do_test trans-5.5 {
+ execsql {INSERT INTO one(a,b) VALUES('hello', 1)}
+ execsql {SELECT a,b FROM one ORDER BY b}
+} {hello 1}
+do_test trans-5.6 {
+ execsql {ROLLBACK}
+ execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
+} {}
+do_test trans-5.7 {
+ set v [catch {
+ execsql {SELECT a,b FROM one ORDER BY b}
+ } msg]
+ lappend v $msg
+} {1 {no such table: one}}
+
+# Test commits and rollbacks of table CREATE TABLEs, CREATE INDEXs
+# DROP TABLEs and DROP INDEXs
+#
+do_test trans-5.8 {
+ execsql {
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name
+ }
+} {}
+do_test trans-5.9 {
+ execsql {
+ BEGIN TRANSACTION;
+ CREATE TABLE t1(a int, b int, c int);
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {t1}
+do_test trans-5.10 {
+ execsql {
+ CREATE INDEX i1 ON t1(a);
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i1 t1}
+do_test trans-5.11 {
+ execsql {
+ COMMIT;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i1 t1}
+do_test trans-5.12 {
+ execsql {
+ BEGIN TRANSACTION;
+ CREATE TABLE t2(a int, b int, c int);
+ CREATE INDEX i2a ON t2(a);
+ CREATE INDEX i2b ON t2(b);
+ DROP TABLE t1;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i2a i2b t2}
+do_test trans-5.13 {
+ execsql {
+ ROLLBACK;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i1 t1}
+do_test trans-5.14 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {t1}
+do_test trans-5.15 {
+ execsql {
+ ROLLBACK;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i1 t1}
+do_test trans-5.16 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ CREATE TABLE t2(x int, y int, z int);
+ CREATE INDEX i2x ON t2(x);
+ CREATE INDEX i2y ON t2(y);
+ INSERT INTO t2 VALUES(1,2,3);
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i2x i2y t1 t2}
+do_test trans-5.17 {
+ execsql {
+ COMMIT;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i2x i2y t1 t2}
+do_test trans-5.18 {
+ execsql {
+ SELECT * FROM t2;
+ }
+} {1 2 3}
+do_test trans-5.19 {
+ execsql {
+ SELECT x FROM t2 WHERE y=2;
+ }
+} {1}
+do_test trans-5.20 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ DROP TABLE t2;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {}
+do_test trans-5.21 {
+ set r [catch {execsql {
+ SELECT * FROM t2
+ }} msg]
+ lappend r $msg
+} {1 {no such table: t2}}
+do_test trans-5.22 {
+ execsql {
+ ROLLBACK;
+ SELECT name fROM sqlite_master
+ WHERE type='table' OR type='index'
+ ORDER BY name;
+ }
+} {i2x i2y t1 t2}
+do_test trans-5.23 {
+ execsql {
+ SELECT * FROM t2;
+ }
+} {1 2 3}
+integrity_check trans-5.23
+
+
+# Try to DROP and CREATE tables and indices with the same name
+# within a transaction. Make sure ROLLBACK works.
+#
+do_test trans-6.1 {
+ execsql2 {
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(p,q,r);
+ ROLLBACK;
+ SELECT * FROM t1;
+ }
+} {a 1 b 2 c 3}
+do_test trans-6.2 {
+ execsql2 {
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(p,q,r);
+ COMMIT;
+ SELECT * FROM t1;
+ }
+} {}
+do_test trans-6.3 {
+ execsql2 {
+ INSERT INTO t1 VALUES(1,2,3);
+ SELECT * FROM t1;
+ }
+} {p 1 q 2 r 3}
+do_test trans-6.4 {
+ execsql2 {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(a,b,c);
+ INSERT INTO t1 VALUES(4,5,6);
+ SELECT * FROM t1;
+ DROP TABLE t1;
+ }
+} {a 4 b 5 c 6}
+do_test trans-6.5 {
+ execsql2 {
+ ROLLBACK;
+ SELECT * FROM t1;
+ }
+} {p 1 q 2 r 3}
+do_test trans-6.6 {
+ execsql2 {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(a,b,c);
+ INSERT INTO t1 VALUES(4,5,6);
+ SELECT * FROM t1;
+ DROP TABLE t1;
+ }
+} {a 4 b 5 c 6}
+do_test trans-6.7 {
+ catchsql {
+ COMMIT;
+ SELECT * FROM t1;
+ }
+} {1 {no such table: t1}}
+
+# Repeat on a table with an automatically generated index.
+#
+do_test trans-6.10 {
+ execsql2 {
+ CREATE TABLE t1(a unique,b,c);
+ INSERT INTO t1 VALUES(1,2,3);
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(p unique,q,r);
+ ROLLBACK;
+ SELECT * FROM t1;
+ }
+} {a 1 b 2 c 3}
+do_test trans-6.11 {
+ execsql2 {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(p unique,q,r);
+ COMMIT;
+ SELECT * FROM t1;
+ }
+} {}
+do_test trans-6.12 {
+ execsql2 {
+ INSERT INTO t1 VALUES(1,2,3);
+ SELECT * FROM t1;
+ }
+} {p 1 q 2 r 3}
+do_test trans-6.13 {
+ execsql2 {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(a unique,b,c);
+ INSERT INTO t1 VALUES(4,5,6);
+ SELECT * FROM t1;
+ DROP TABLE t1;
+ }
+} {a 4 b 5 c 6}
+do_test trans-6.14 {
+ execsql2 {
+ ROLLBACK;
+ SELECT * FROM t1;
+ }
+} {p 1 q 2 r 3}
+do_test trans-6.15 {
+ execsql2 {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(a unique,b,c);
+ INSERT INTO t1 VALUES(4,5,6);
+ SELECT * FROM t1;
+ DROP TABLE t1;
+ }
+} {a 4 b 5 c 6}
+do_test trans-6.16 {
+ catchsql {
+ COMMIT;
+ SELECT * FROM t1;
+ }
+} {1 {no such table: t1}}
+
+do_test trans-6.20 {
+ execsql {
+ CREATE TABLE t1(a integer primary key,b,c);
+ INSERT INTO t1 VALUES(1,-2,-3);
+ INSERT INTO t1 VALUES(4,-5,-6);
+ SELECT * FROM t1;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.21 {
+ execsql {
+ CREATE INDEX i1 ON t1(b);
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.22 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ SELECT * FROM t1 WHERE b<1;
+ ROLLBACK;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.23 {
+ execsql {
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.24 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ ROLLBACK;
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+
+do_test trans-6.25 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ CREATE INDEX i1 ON t1(c);
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.26 {
+ execsql {
+ SELECT * FROM t1 WHERE c<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.27 {
+ execsql {
+ ROLLBACK;
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.28 {
+ execsql {
+ SELECT * FROM t1 WHERE c<1;
+ }
+} {1 -2 -3 4 -5 -6}
+
+# The following repeats steps 6.20 through 6.28, but puts a "unique"
+# constraint the first field of the table in order to generate an
+# automatic index.
+#
+do_test trans-6.30 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ CREATE TABLE t1(a int unique,b,c);
+ COMMIT;
+ INSERT INTO t1 VALUES(1,-2,-3);
+ INSERT INTO t1 VALUES(4,-5,-6);
+ SELECT * FROM t1 ORDER BY a;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.31 {
+ execsql {
+ CREATE INDEX i1 ON t1(b);
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.32 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ SELECT * FROM t1 WHERE b<1;
+ ROLLBACK;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.33 {
+ execsql {
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.34 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP TABLE t1;
+ ROLLBACK;
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+
+do_test trans-6.35 {
+ execsql {
+ BEGIN TRANSACTION;
+ DROP INDEX i1;
+ CREATE INDEX i1 ON t1(c);
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.36 {
+ execsql {
+ SELECT * FROM t1 WHERE c<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.37 {
+ execsql {
+ DROP INDEX i1;
+ SELECT * FROM t1 WHERE c<1;
+ }
+} {1 -2 -3 4 -5 -6}
+do_test trans-6.38 {
+ execsql {
+ ROLLBACK;
+ SELECT * FROM t1 WHERE b<1;
+ }
+} {4 -5 -6 1 -2 -3}
+do_test trans-6.39 {
+ execsql {
+ SELECT * FROM t1 WHERE c<1;
+ }
+} {1 -2 -3 4 -5 -6}
+integrity_check trans-6.40
+
+# Test to make sure rollback restores the database back to its original
+# state.
+#
+do_test trans-7.1 {
+ execsql {BEGIN}
+ for {set i 0} {$i<1000} {incr i} {
+ set r1 [expr {rand()}]
+ set r2 [expr {rand()}]
+ set r3 [expr {rand()}]
+ execsql "INSERT INTO t2 VALUES($r1,$r2,$r3)"
+ }
+ execsql {COMMIT}
+ set ::checksum [execsql {SELECT md5sum(x,y,z) FROM t2}]
+ set ::checksum2 [
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+ ]
+ execsql {SELECT count(*) FROM t2}
+} {1001}
+do_test trans-7.2 {
+ execsql {SELECT md5sum(x,y,z) FROM t2}
+} $checksum
+do_test trans-7.2.1 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+do_test trans-7.3 {
+ execsql {
+ BEGIN;
+ DELETE FROM t2;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.4 {
+ execsql {
+ BEGIN;
+ INSERT INTO t2 SELECT * FROM t2;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.5 {
+ execsql {
+ BEGIN;
+ DELETE FROM t2;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.6 {
+ execsql {
+ BEGIN;
+ INSERT INTO t2 SELECT * FROM t2;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.7 {
+ execsql {
+ BEGIN;
+ CREATE TABLE t3 AS SELECT * FROM t2;
+ INSERT INTO t2 SELECT * FROM t3;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+} $checksum
+do_test trans-7.8 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+ifcapable tempdb {
+ do_test trans-7.9 {
+ execsql {
+ BEGIN;
+ CREATE TEMP TABLE t3 AS SELECT * FROM t2;
+ INSERT INTO t2 SELECT * FROM t3;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+ } $checksum
+}
+do_test trans-7.10 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+ifcapable tempdb {
+ do_test trans-7.11 {
+ execsql {
+ BEGIN;
+ CREATE TEMP TABLE t3 AS SELECT * FROM t2;
+ INSERT INTO t2 SELECT * FROM t3;
+ DROP INDEX i2x;
+ DROP INDEX i2y;
+ CREATE INDEX i3a ON t3(x);
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+ } $checksum
+}
+do_test trans-7.12 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+ifcapable tempdb {
+ do_test trans-7.13 {
+ execsql {
+ BEGIN;
+ DROP TABLE t2;
+ ROLLBACK;
+ SELECT md5sum(x,y,z) FROM t2;
+ }
+ } $checksum
+}
+do_test trans-7.14 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+integrity_check trans-7.15
+wal_check_journal_mode trans-7.16
+
+# Arrange for another process to begin modifying the database but abort
+# and die in the middle of the modification. Then have this process read
+# the database. This process should detect the journal file and roll it
+# back. Verify that this happens correctly.
+#
+set fd [open test.tcl w]
+puts $fd {
+ sqlite3_test_control_pending_byte 0x0010000
+ sqlite3 db test.db
+ db eval {
+ PRAGMA default_cache_size=20;
+ BEGIN;
+ CREATE TABLE t3 AS SELECT * FROM t2;
+ DELETE FROM t2;
+ }
+ sqlite_abort
+}
+close $fd
+do_test trans-8.1 {
+ catch {exec [info nameofexec] test.tcl}
+ execsql {SELECT md5sum(x,y,z) FROM t2}
+} $checksum
+do_test trans-8.2 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+integrity_check trans-8.3
+set fd [open test.tcl w]
+puts $fd {
+ sqlite3_test_control_pending_byte 0x0010000
+ sqlite3 db test.db
+ db eval {
+ PRAGMA journal_mode=persist;
+ PRAGMA default_cache_size=20;
+ BEGIN;
+ CREATE TABLE t3 AS SELECT * FROM t2;
+ DELETE FROM t2;
+ }
+ sqlite_abort
+}
+close $fd
+do_test trans-8.4 {
+ catch {exec [info nameofexec] test.tcl}
+ execsql {SELECT md5sum(x,y,z) FROM t2}
+} $checksum
+do_test trans-8.5 {
+ execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
+} $checksum2
+integrity_check trans-8.6
+wal_check_journal_mode trans-8.7
+
+# In the following sequence of tests, compute the MD5 sum of the content
+# of a table, make lots of modifications to that table, then do a rollback.
+# Verify that after the rollback, the MD5 checksum is unchanged.
+#
+do_test trans-9.1 {
+ execsql {
+ PRAGMA default_cache_size=10;
+ }
+ db close
+ sqlite3 db test.db
+ execsql {
+ BEGIN;
+ CREATE TABLE t3(x TEXT);
+ INSERT INTO t3 VALUES(randstr(10,400));
+ INSERT INTO t3 VALUES(randstr(10,400));
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ COMMIT;
+ SELECT count(*) FROM t3;
+ }
+} {1024}
+wal_check_journal_mode trans-9.1.1
+
+# The following procedure computes a "signature" for table "t3". If
+# T3 changes in any way, the signature should change.
+#
+# This is used to test ROLLBACK. We gather a signature for t3, then
+# make lots of changes to t3, then rollback and take another signature.
+# The two signatures should be the same.
+#
+proc signature {} {
+ return [db eval {SELECT count(*), md5sum(x) FROM t3}]
+}
+
+# Repeat the following group of tests 20 times for quick testing and
+# 40 times for full testing. Each iteration of the test makes table
+# t3 a little larger, and thus takes a little longer, so doing 40 tests
+# is more than 2.0 times slower than doing 20 tests. Considerably more.
+#
+# Also, if temporary tables are stored in memory and the test pcache
+# is in use, only 20 iterations. Otherwise the test pcache runs out
+# of page slots and SQLite reports "out of memory".
+#
+if {[info exists G(isquick)] || (
+ $TEMP_STORE==3 && [regexp {^pcache[[:digit:]]*$} [permutation]]
+) } {
+ set limit 20
+} elseif {[info exists G(issoak)]} {
+ set limit 100
+} else {
+ set limit 40
+}
+
+# Do rollbacks. Make sure the signature does not change.
+#
+for {set i 2} {$i<=$limit} {incr i} {
+ set ::sig [signature]
+ set cnt [lindex $::sig 0]
+ if {$i%2==0} {
+ execsql {PRAGMA fullfsync=ON}
+ } else {
+ execsql {PRAGMA fullfsync=OFF}
+ }
+ set sqlite_sync_count 0
+ set sqlite_fullsync_count 0
+ do_test trans-9.$i.1-$cnt {
+ execsql {
+ BEGIN;
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ ROLLBACK;
+ }
+ signature
+ } $sig
+ do_test trans-9.$i.2-$cnt {
+ execsql {
+ BEGIN;
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ ROLLBACK;
+ }
+ signature
+ } $sig
+ if {$i<$limit} {
+ do_test trans-9.$i.3-$cnt {
+ execsql {
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0;
+ }
+ } {}
+ catch flush_async_queue
+ if {$tcl_platform(platform)=="unix"} {
+ do_test trans-9.$i.4-$cnt {
+ expr {$sqlite_sync_count>0}
+ } 1
+ ifcapable pager_pragmas {
+ do_test trans-9.$i.5-$cnt {
+ expr {$sqlite_fullsync_count>0}
+ } [expr {$i%2==0}]
+ } else {
+ do_test trans-9.$i.5-$cnt {
+ expr {$sqlite_fullsync_count==0}
+ } {1}
+ }
+ }
+ }
+
+ wal_check_journal_mode trans-9.$i.6-$cnt
+ set ::pager_old_format 0
+}
+
+finish_test