3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
11 # This file implements regression tests for SQLite library. The
12 # focus of this script is database locks.
16 set testdir [file dirname $argv0]
17 source $testdir/tester.tcl
19 # Create several tables to work with.
24 CREATE TABLE one(a int PRIMARY KEY, b text);
25 INSERT INTO one VALUES(1,'one');
26 INSERT INTO one VALUES(2,'two');
27 INSERT INTO one VALUES(3,'three');
28 SELECT b FROM one ORDER BY a;
31 integrity_check trans-1.0.1
34 CREATE TABLE two(a int PRIMARY KEY, b text);
35 INSERT INTO two VALUES(1,'I');
36 INSERT INTO two VALUES(5,'V');
37 INSERT INTO two VALUES(10,'X');
38 SELECT b FROM two ORDER BY a;
45 sqlite3_txn_state db main
48 sqlite3_txn_state db temp
51 sqlite3_txn_state db no-such-schema
56 execsql {SELECT b FROM one ORDER BY a} altdb
59 execsql {SELECT b FROM two ORDER BY a} altdb
61 integrity_check trans-1.11
62 wal_check_journal_mode trans-1.12
67 set v [catch {execsql {BEGIN}} msg]
74 set v [catch {execsql {END}} msg]
78 set v [catch {execsql {BEGIN TRANSACTION}} msg]
82 set v [catch {execsql {COMMIT TRANSACTION}} msg]
86 set v [catch {execsql {BEGIN TRANSACTION 'foo'}} msg]
90 set v [catch {execsql {ROLLBACK TRANSACTION 'foo'}} msg]
96 SELECT a FROM one ORDER BY a;
97 SELECT a FROM two ORDER BY a;
101 integrity_check trans-2.11
102 wal_check_journal_mode trans-2.12
104 # Check the locking behavior
109 UPDATE one SET a = 0 WHERE 0;
110 SELECT a FROM one ORDER BY a;
117 sqlite3_txn_state db main
120 sqlite3_txn_state db temp
125 SELECT a FROM two ORDER BY a;
131 SELECT a FROM one ORDER BY a;
136 INSERT INTO one VALUES(4,'four');
141 SELECT a FROM two ORDER BY a;
146 SELECT a FROM one ORDER BY a;
151 INSERT INTO two VALUES(4,'IV');
156 SELECT a FROM two ORDER BY a;
161 SELECT a FROM one ORDER BY a;
165 execsql {END TRANSACTION}
167 do_test trans-3.10b {
173 set v [catch {execsql {
174 SELECT a FROM two ORDER BY a;
179 set v [catch {execsql {
180 SELECT a FROM one ORDER BY a;
185 set v [catch {execsql {
186 SELECT a FROM two ORDER BY a;
191 set v [catch {execsql {
192 SELECT a FROM one ORDER BY a;
196 integrity_check trans-3.15
197 wal_check_journal_mode trans-3.16
200 set v [catch {execsql {
204 } {1 {cannot commit - no transaction is active}}
206 set v [catch {execsql {
210 } {1 {cannot rollback - no transaction is active}}
214 UPDATE two SET a = 0 WHERE 0;
215 SELECT a FROM two ORDER BY a;
220 SELECT a FROM two ORDER BY a;
225 SELECT a FROM one ORDER BY a;
231 SELECT a FROM one ORDER BY a;
233 } {1 {cannot start a transaction within a transaction}}
236 SELECT a FROM two ORDER BY a;
241 SELECT a FROM one ORDER BY a;
245 set v [catch {execsql {
247 SELECT a FROM two ORDER BY a;
252 set v [catch {execsql {
253 SELECT a FROM two ORDER BY a;
258 set v [catch {execsql {
259 SELECT a FROM one ORDER BY a;
263 integrity_check trans-4.12
264 wal_check_journal_mode trans-4.13
265 wal_check_journal_mode trans-4.14 altdb
273 integrity_check trans-4.99
275 # Check out the commit/rollback behavior of the database
278 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
281 execsql {BEGIN TRANSACTION}
282 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
288 sqlite3_txn_state db main
291 sqlite3_txn_state db temp
294 execsql {CREATE TABLE one(a text, b int)}
295 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
298 execsql {SELECT a,b FROM one ORDER BY b}
301 execsql {INSERT INTO one(a,b) VALUES('hello', 1)}
302 execsql {SELECT a,b FROM one ORDER BY b}
306 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
310 execsql {SELECT a,b FROM one ORDER BY b}
313 } {1 {no such table: one}}
315 # Test commits and rollbacks of table CREATE TABLEs, CREATE INDEXs
316 # DROP TABLEs and DROP INDEXs
320 SELECT name fROM sqlite_master
321 WHERE type='table' OR type='index'
328 CREATE TABLE t1(a int, b int, c int);
329 SELECT name fROM sqlite_master
330 WHERE type='table' OR type='index'
336 CREATE INDEX i1 ON t1(a);
337 SELECT name fROM sqlite_master
338 WHERE type='table' OR type='index'
345 SELECT name fROM sqlite_master
346 WHERE type='table' OR type='index'
353 CREATE TABLE t2(a int, b int, c int);
354 CREATE INDEX i2a ON t2(a);
355 CREATE INDEX i2b ON t2(b);
357 SELECT name fROM sqlite_master
358 WHERE type='table' OR type='index'
365 SELECT name fROM sqlite_master
366 WHERE type='table' OR type='index'
374 SELECT name fROM sqlite_master
375 WHERE type='table' OR type='index'
382 SELECT name fROM sqlite_master
383 WHERE type='table' OR type='index'
391 CREATE TABLE t2(x int, y int, z int);
392 CREATE INDEX i2x ON t2(x);
393 CREATE INDEX i2y ON t2(y);
394 INSERT INTO t2 VALUES(1,2,3);
395 SELECT name fROM sqlite_master
396 WHERE type='table' OR type='index'
403 SELECT name fROM sqlite_master
404 WHERE type='table' OR type='index'
415 SELECT x FROM t2 WHERE y=2;
423 SELECT name fROM sqlite_master
424 WHERE type='table' OR type='index'
429 set r [catch {execsql {
433 } {1 {no such table: t2}}
437 SELECT name fROM sqlite_master
438 WHERE type='table' OR type='index'
447 integrity_check trans-5.23
450 # Try to DROP and CREATE tables and indices with the same name
451 # within a transaction. Make sure ROLLBACK works.
455 INSERT INTO t1 VALUES(1,2,3);
458 CREATE TABLE t1(p,q,r);
465 INSERT INTO t1 VALUES(1,2,3);
468 CREATE TABLE t1(p,q,r);
475 INSERT INTO t1 VALUES(1,2,3);
483 CREATE TABLE t1(a,b,c);
484 INSERT INTO t1 VALUES(4,5,6);
499 CREATE TABLE t1(a,b,c);
500 INSERT INTO t1 VALUES(4,5,6);
510 } {1 {no such table: t1}}
512 # Repeat on a table with an automatically generated index.
516 CREATE TABLE t1(a unique,b,c);
517 INSERT INTO t1 VALUES(1,2,3);
520 CREATE TABLE t1(p unique,q,r);
529 CREATE TABLE t1(p unique,q,r);
536 INSERT INTO t1 VALUES(1,2,3);
544 CREATE TABLE t1(a unique,b,c);
545 INSERT INTO t1 VALUES(4,5,6);
560 CREATE TABLE t1(a unique,b,c);
561 INSERT INTO t1 VALUES(4,5,6);
571 } {1 {no such table: t1}}
575 CREATE TABLE t1(a integer primary key,b,c);
576 INSERT INTO t1 VALUES(1,-2,-3);
577 INSERT INTO t1 VALUES(4,-5,-6);
583 CREATE INDEX i1 ON t1(b);
584 SELECT * FROM t1 WHERE b<1;
591 SELECT * FROM t1 WHERE b<1;
597 SELECT * FROM t1 WHERE b<1;
605 SELECT * FROM t1 WHERE b<1;
613 CREATE INDEX i1 ON t1(c);
614 SELECT * FROM t1 WHERE b<1;
619 SELECT * FROM t1 WHERE c<1;
625 SELECT * FROM t1 WHERE b<1;
630 SELECT * FROM t1 WHERE c<1;
634 # The following repeats steps 6.20 through 6.28, but puts a "unique"
635 # constraint the first field of the table in order to generate an
642 CREATE TABLE t1(a int unique,b,c);
644 INSERT INTO t1 VALUES(1,-2,-3);
645 INSERT INTO t1 VALUES(4,-5,-6);
646 SELECT * FROM t1 ORDER BY a;
651 CREATE INDEX i1 ON t1(b);
652 SELECT * FROM t1 WHERE b<1;
659 SELECT * FROM t1 WHERE b<1;
665 SELECT * FROM t1 WHERE b<1;
673 SELECT * FROM t1 WHERE b<1;
681 CREATE INDEX i1 ON t1(c);
682 SELECT * FROM t1 WHERE b<1;
687 SELECT * FROM t1 WHERE c<1;
693 SELECT * FROM t1 WHERE c<1;
699 SELECT * FROM t1 WHERE b<1;
704 SELECT * FROM t1 WHERE c<1;
707 integrity_check trans-6.40
709 # Test to make sure rollback restores the database back to its original
714 for {set i 0} {$i<1000} {incr i} {
715 set r1 [expr {rand()}]
716 set r2 [expr {rand()}]
717 set r3 [expr {rand()}]
718 execsql "INSERT INTO t2 VALUES($r1,$r2,$r3)"
721 set ::checksum [execsql {SELECT md5sum(x,y,z) FROM t2}]
723 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
725 execsql {SELECT count(*) FROM t2}
728 execsql {SELECT md5sum(x,y,z) FROM t2}
730 do_test trans-7.2.1 {
731 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
738 SELECT md5sum(x,y,z) FROM t2;
744 INSERT INTO t2 SELECT * FROM t2;
746 SELECT md5sum(x,y,z) FROM t2;
754 SELECT md5sum(x,y,z) FROM t2;
760 INSERT INTO t2 SELECT * FROM t2;
762 SELECT md5sum(x,y,z) FROM t2;
768 CREATE TABLE t3 AS SELECT * FROM t2;
769 INSERT INTO t2 SELECT * FROM t3;
771 SELECT md5sum(x,y,z) FROM t2;
775 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
781 CREATE TEMP TABLE t3 AS SELECT * FROM t2;
782 INSERT INTO t2 SELECT * FROM t3;
784 SELECT md5sum(x,y,z) FROM t2;
789 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
795 CREATE TEMP TABLE t3 AS SELECT * FROM t2;
796 INSERT INTO t2 SELECT * FROM t3;
799 CREATE INDEX i3a ON t3(x);
801 SELECT md5sum(x,y,z) FROM t2;
806 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
814 SELECT md5sum(x,y,z) FROM t2;
819 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
821 integrity_check trans-7.15
822 wal_check_journal_mode trans-7.16
824 # Arrange for another process to begin modifying the database but abort
825 # and die in the middle of the modification. Then have this process read
826 # the database. This process should detect the journal file and roll it
827 # back. Verify that this happens correctly.
829 set fd [open test.tcl w]
831 sqlite3_test_control_pending_byte 0x0010000
834 PRAGMA default_cache_size=20;
836 CREATE TABLE t3 AS SELECT * FROM t2;
843 catch {exec [info nameofexec] test.tcl}
844 execsql {SELECT md5sum(x,y,z) FROM t2}
847 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
849 integrity_check trans-8.3
850 set fd [open test.tcl w]
852 sqlite3_test_control_pending_byte 0x0010000
855 PRAGMA journal_mode=persist;
856 PRAGMA default_cache_size=20;
858 CREATE TABLE t3 AS SELECT * FROM t2;
865 catch {exec [info nameofexec] test.tcl}
866 execsql {SELECT md5sum(x,y,z) FROM t2}
869 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
871 integrity_check trans-8.6
872 wal_check_journal_mode trans-8.7
874 # In the following sequence of tests, compute the MD5 sum of the content
875 # of a table, make lots of modifications to that table, then do a rollback.
876 # Verify that after the rollback, the MD5 checksum is unchanged.
880 PRAGMA default_cache_size=10;
886 CREATE TABLE t3(x TEXT);
887 INSERT INTO t3 VALUES(randstr(10,400));
888 INSERT INTO t3 VALUES(randstr(10,400));
889 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
890 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
891 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
892 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
893 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
894 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
895 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
896 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
897 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
899 SELECT count(*) FROM t3;
902 wal_check_journal_mode trans-9.1.1
904 # The following procedure computes a "signature" for table "t3". If
905 # T3 changes in any way, the signature should change.
907 # This is used to test ROLLBACK. We gather a signature for t3, then
908 # make lots of changes to t3, then rollback and take another signature.
909 # The two signatures should be the same.
912 return [db eval {SELECT count(*), md5sum(x) FROM t3}]
915 # Repeat the following group of tests 20 times for quick testing and
916 # 40 times for full testing. Each iteration of the test makes table
917 # t3 a little larger, and thus takes a little longer, so doing 40 tests
918 # is more than 2.0 times slower than doing 20 tests. Considerably more.
920 # Also, if temporary tables are stored in memory and the test pcache
921 # is in use, only 20 iterations. Otherwise the test pcache runs out
922 # of page slots and SQLite reports "out of memory".
924 if {[info exists G(isquick)] || (
925 $TEMP_STORE==3 && [regexp {^pcache[[:digit:]]*$} [permutation]]
928 } elseif {[info exists G(issoak)]} {
934 # Do rollbacks. Make sure the signature does not change.
936 for {set i 2} {$i<=$limit} {incr i} {
937 set ::sig [signature]
938 set cnt [lindex $::sig 0]
940 execsql {PRAGMA fullfsync=ON}
942 execsql {PRAGMA fullfsync=OFF}
944 set sqlite_sync_count 0
945 set sqlite_fullsync_count 0
946 do_test trans-9.$i.1-$cnt {
949 DELETE FROM t3 WHERE random()%10!=0;
950 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
951 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
956 do_test trans-9.$i.2-$cnt {
959 DELETE FROM t3 WHERE random()%10!=0;
960 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
961 DELETE FROM t3 WHERE random()%10!=0;
962 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
968 do_test trans-9.$i.3-$cnt {
970 INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0;
973 catch flush_async_queue
974 if {$tcl_platform(platform)=="unix"} {
975 do_test trans-9.$i.4-$cnt {
976 expr {$sqlite_sync_count>0}
978 ifcapable pager_pragmas {
979 do_test trans-9.$i.5-$cnt {
980 expr {$sqlite_fullsync_count>0}
983 do_test trans-9.$i.5-$cnt {
984 expr {$sqlite_fullsync_count==0}
990 wal_check_journal_mode trans-9.$i.6-$cnt
991 set ::pager_old_format 0