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.
14 # $Id: trans.test,v 1.41 2009/04/28 16:37:59 danielk1977 Exp $
17 set testdir [file dirname $argv0]
18 source $testdir/tester.tcl
20 # Create several tables to work with.
25 CREATE TABLE one(a int PRIMARY KEY, b text);
26 INSERT INTO one VALUES(1,'one');
27 INSERT INTO one VALUES(2,'two');
28 INSERT INTO one VALUES(3,'three');
29 SELECT b FROM one ORDER BY a;
32 integrity_check trans-1.0.1
35 CREATE TABLE two(a int PRIMARY KEY, b text);
36 INSERT INTO two VALUES(1,'I');
37 INSERT INTO two VALUES(5,'V');
38 INSERT INTO two VALUES(10,'X');
39 SELECT b FROM two ORDER BY a;
44 execsql {SELECT b FROM one ORDER BY a} altdb
47 execsql {SELECT b FROM two ORDER BY a} altdb
49 integrity_check trans-1.11
50 wal_check_journal_mode trans-1.12
55 set v [catch {execsql {BEGIN}} msg]
59 set v [catch {execsql {END}} msg]
63 set v [catch {execsql {BEGIN TRANSACTION}} msg]
67 set v [catch {execsql {COMMIT TRANSACTION}} msg]
71 set v [catch {execsql {BEGIN TRANSACTION 'foo'}} msg]
75 set v [catch {execsql {ROLLBACK TRANSACTION 'foo'}} msg]
81 SELECT a FROM one ORDER BY a;
82 SELECT a FROM two ORDER BY a;
86 integrity_check trans-2.11
87 wal_check_journal_mode trans-2.12
89 # Check the locking behavior
94 UPDATE one SET a = 0 WHERE 0;
95 SELECT a FROM one ORDER BY a;
100 SELECT a FROM two ORDER BY a;
106 SELECT a FROM one ORDER BY a;
111 INSERT INTO one VALUES(4,'four');
116 SELECT a FROM two ORDER BY a;
121 SELECT a FROM one ORDER BY a;
126 INSERT INTO two VALUES(4,'IV');
131 SELECT a FROM two ORDER BY a;
136 SELECT a FROM one ORDER BY a;
140 execsql {END TRANSACTION}
144 set v [catch {execsql {
145 SELECT a FROM two ORDER BY a;
150 set v [catch {execsql {
151 SELECT a FROM one ORDER BY a;
156 set v [catch {execsql {
157 SELECT a FROM two ORDER BY a;
162 set v [catch {execsql {
163 SELECT a FROM one ORDER BY a;
167 integrity_check trans-3.15
168 wal_check_journal_mode trans-3.16
171 set v [catch {execsql {
175 } {1 {cannot commit - no transaction is active}}
177 set v [catch {execsql {
181 } {1 {cannot rollback - no transaction is active}}
185 UPDATE two SET a = 0 WHERE 0;
186 SELECT a FROM two ORDER BY a;
191 SELECT a FROM two ORDER BY a;
196 SELECT a FROM one ORDER BY a;
202 SELECT a FROM one ORDER BY a;
204 } {1 {cannot start a transaction within a transaction}}
207 SELECT a FROM two ORDER BY a;
212 SELECT a FROM one ORDER BY a;
216 set v [catch {execsql {
218 SELECT a FROM two ORDER BY a;
223 set v [catch {execsql {
224 SELECT a FROM two ORDER BY a;
229 set v [catch {execsql {
230 SELECT a FROM one ORDER BY a;
234 integrity_check trans-4.12
235 wal_check_journal_mode trans-4.13
236 wal_check_journal_mode trans-4.14 altdb
244 integrity_check trans-4.99
246 # Check out the commit/rollback behavior of the database
249 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
252 execsql {BEGIN TRANSACTION}
253 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
256 execsql {CREATE TABLE one(a text, b int)}
257 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
260 execsql {SELECT a,b FROM one ORDER BY b}
263 execsql {INSERT INTO one(a,b) VALUES('hello', 1)}
264 execsql {SELECT a,b FROM one ORDER BY b}
268 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
272 execsql {SELECT a,b FROM one ORDER BY b}
275 } {1 {no such table: one}}
277 # Test commits and rollbacks of table CREATE TABLEs, CREATE INDEXs
278 # DROP TABLEs and DROP INDEXs
282 SELECT name fROM sqlite_master
283 WHERE type='table' OR type='index'
290 CREATE TABLE t1(a int, b int, c int);
291 SELECT name fROM sqlite_master
292 WHERE type='table' OR type='index'
298 CREATE INDEX i1 ON t1(a);
299 SELECT name fROM sqlite_master
300 WHERE type='table' OR type='index'
307 SELECT name fROM sqlite_master
308 WHERE type='table' OR type='index'
315 CREATE TABLE t2(a int, b int, c int);
316 CREATE INDEX i2a ON t2(a);
317 CREATE INDEX i2b ON t2(b);
319 SELECT name fROM sqlite_master
320 WHERE type='table' OR type='index'
327 SELECT name fROM sqlite_master
328 WHERE type='table' OR type='index'
336 SELECT name fROM sqlite_master
337 WHERE type='table' OR type='index'
344 SELECT name fROM sqlite_master
345 WHERE type='table' OR type='index'
353 CREATE TABLE t2(x int, y int, z int);
354 CREATE INDEX i2x ON t2(x);
355 CREATE INDEX i2y ON t2(y);
356 INSERT INTO t2 VALUES(1,2,3);
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'
377 SELECT x FROM t2 WHERE y=2;
385 SELECT name fROM sqlite_master
386 WHERE type='table' OR type='index'
391 set r [catch {execsql {
395 } {1 {no such table: t2}}
399 SELECT name fROM sqlite_master
400 WHERE type='table' OR type='index'
409 integrity_check trans-5.23
412 # Try to DROP and CREATE tables and indices with the same name
413 # within a transaction. Make sure ROLLBACK works.
417 INSERT INTO t1 VALUES(1,2,3);
420 CREATE TABLE t1(p,q,r);
427 INSERT INTO t1 VALUES(1,2,3);
430 CREATE TABLE t1(p,q,r);
437 INSERT INTO t1 VALUES(1,2,3);
445 CREATE TABLE t1(a,b,c);
446 INSERT INTO t1 VALUES(4,5,6);
461 CREATE TABLE t1(a,b,c);
462 INSERT INTO t1 VALUES(4,5,6);
472 } {1 {no such table: t1}}
474 # Repeat on a table with an automatically generated index.
478 CREATE TABLE t1(a unique,b,c);
479 INSERT INTO t1 VALUES(1,2,3);
482 CREATE TABLE t1(p unique,q,r);
491 CREATE TABLE t1(p unique,q,r);
498 INSERT INTO t1 VALUES(1,2,3);
506 CREATE TABLE t1(a unique,b,c);
507 INSERT INTO t1 VALUES(4,5,6);
522 CREATE TABLE t1(a unique,b,c);
523 INSERT INTO t1 VALUES(4,5,6);
533 } {1 {no such table: t1}}
537 CREATE TABLE t1(a integer primary key,b,c);
538 INSERT INTO t1 VALUES(1,-2,-3);
539 INSERT INTO t1 VALUES(4,-5,-6);
545 CREATE INDEX i1 ON t1(b);
546 SELECT * FROM t1 WHERE b<1;
553 SELECT * FROM t1 WHERE b<1;
559 SELECT * FROM t1 WHERE b<1;
567 SELECT * FROM t1 WHERE b<1;
575 CREATE INDEX i1 ON t1(c);
576 SELECT * FROM t1 WHERE b<1;
581 SELECT * FROM t1 WHERE c<1;
587 SELECT * FROM t1 WHERE b<1;
592 SELECT * FROM t1 WHERE c<1;
596 # The following repeats steps 6.20 through 6.28, but puts a "unique"
597 # constraint the first field of the table in order to generate an
604 CREATE TABLE t1(a int unique,b,c);
606 INSERT INTO t1 VALUES(1,-2,-3);
607 INSERT INTO t1 VALUES(4,-5,-6);
608 SELECT * FROM t1 ORDER BY a;
613 CREATE INDEX i1 ON t1(b);
614 SELECT * FROM t1 WHERE b<1;
621 SELECT * FROM t1 WHERE b<1;
627 SELECT * FROM t1 WHERE b<1;
635 SELECT * FROM t1 WHERE b<1;
643 CREATE INDEX i1 ON t1(c);
644 SELECT * FROM t1 WHERE b<1;
649 SELECT * FROM t1 WHERE c<1;
655 SELECT * FROM t1 WHERE c<1;
661 SELECT * FROM t1 WHERE b<1;
666 SELECT * FROM t1 WHERE c<1;
669 integrity_check trans-6.40
671 # Test to make sure rollback restores the database back to its original
676 for {set i 0} {$i<1000} {incr i} {
677 set r1 [expr {rand()}]
678 set r2 [expr {rand()}]
679 set r3 [expr {rand()}]
680 execsql "INSERT INTO t2 VALUES($r1,$r2,$r3)"
683 set ::checksum [execsql {SELECT md5sum(x,y,z) FROM t2}]
685 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
687 execsql {SELECT count(*) FROM t2}
690 execsql {SELECT md5sum(x,y,z) FROM t2}
692 do_test trans-7.2.1 {
693 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
700 SELECT md5sum(x,y,z) FROM t2;
706 INSERT INTO t2 SELECT * FROM t2;
708 SELECT md5sum(x,y,z) FROM t2;
716 SELECT md5sum(x,y,z) FROM t2;
722 INSERT INTO t2 SELECT * FROM t2;
724 SELECT md5sum(x,y,z) FROM t2;
730 CREATE TABLE t3 AS SELECT * FROM t2;
731 INSERT INTO t2 SELECT * FROM t3;
733 SELECT md5sum(x,y,z) FROM t2;
737 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
743 CREATE TEMP TABLE t3 AS SELECT * FROM t2;
744 INSERT INTO t2 SELECT * FROM t3;
746 SELECT md5sum(x,y,z) FROM t2;
751 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
757 CREATE TEMP TABLE t3 AS SELECT * FROM t2;
758 INSERT INTO t2 SELECT * FROM t3;
761 CREATE INDEX i3a ON t3(x);
763 SELECT md5sum(x,y,z) FROM t2;
768 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
776 SELECT md5sum(x,y,z) FROM t2;
781 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
783 integrity_check trans-7.15
784 wal_check_journal_mode trans-7.16
786 # Arrange for another process to begin modifying the database but abort
787 # and die in the middle of the modification. Then have this process read
788 # the database. This process should detect the journal file and roll it
789 # back. Verify that this happens correctly.
791 set fd [open test.tcl w]
793 sqlite3_test_control_pending_byte 0x0010000
796 PRAGMA default_cache_size=20;
798 CREATE TABLE t3 AS SELECT * FROM t2;
805 catch {exec [info nameofexec] test.tcl}
806 execsql {SELECT md5sum(x,y,z) FROM t2}
809 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
811 integrity_check trans-8.3
812 set fd [open test.tcl w]
814 sqlite3_test_control_pending_byte 0x0010000
817 PRAGMA journal_mode=persist;
818 PRAGMA default_cache_size=20;
820 CREATE TABLE t3 AS SELECT * FROM t2;
827 catch {exec [info nameofexec] test.tcl}
828 execsql {SELECT md5sum(x,y,z) FROM t2}
831 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
833 integrity_check trans-8.6
834 wal_check_journal_mode trans-8.7
836 # In the following sequence of tests, compute the MD5 sum of the content
837 # of a table, make lots of modifications to that table, then do a rollback.
838 # Verify that after the rollback, the MD5 checksum is unchanged.
842 PRAGMA default_cache_size=10;
848 CREATE TABLE t3(x TEXT);
849 INSERT INTO t3 VALUES(randstr(10,400));
850 INSERT INTO t3 VALUES(randstr(10,400));
851 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
852 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
853 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
854 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
855 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
856 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
857 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
858 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
859 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
861 SELECT count(*) FROM t3;
864 wal_check_journal_mode trans-9.1.1
866 # The following procedure computes a "signature" for table "t3". If
867 # T3 changes in any way, the signature should change.
869 # This is used to test ROLLBACK. We gather a signature for t3, then
870 # make lots of changes to t3, then rollback and take another signature.
871 # The two signatures should be the same.
874 return [db eval {SELECT count(*), md5sum(x) FROM t3}]
877 # Repeat the following group of tests 20 times for quick testing and
878 # 40 times for full testing. Each iteration of the test makes table
879 # t3 a little larger, and thus takes a little longer, so doing 40 tests
880 # is more than 2.0 times slower than doing 20 tests. Considerably more.
882 # Also, if temporary tables are stored in memory and the test pcache
883 # is in use, only 20 iterations. Otherwise the test pcache runs out
884 # of page slots and SQLite reports "out of memory".
886 if {[info exists G(isquick)] || (
887 $TEMP_STORE==3 && [regexp {^pcache[[:digit:]]*$} [permutation]]
890 } elseif {[info exists G(issoak)]} {
896 # Do rollbacks. Make sure the signature does not change.
898 for {set i 2} {$i<=$limit} {incr i} {
899 set ::sig [signature]
900 set cnt [lindex $::sig 0]
902 execsql {PRAGMA fullfsync=ON}
904 execsql {PRAGMA fullfsync=OFF}
906 set sqlite_sync_count 0
907 set sqlite_fullsync_count 0
908 do_test trans-9.$i.1-$cnt {
911 DELETE FROM t3 WHERE random()%10!=0;
912 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
913 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
918 do_test trans-9.$i.2-$cnt {
921 DELETE FROM t3 WHERE random()%10!=0;
922 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
923 DELETE FROM t3 WHERE random()%10!=0;
924 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
930 do_test trans-9.$i.3-$cnt {
932 INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0;
935 catch flush_async_queue
936 if {$tcl_platform(platform)=="unix"} {
937 do_test trans-9.$i.4-$cnt {
938 expr {$sqlite_sync_count>0}
940 ifcapable pager_pragmas {
941 do_test trans-9.$i.5-$cnt {
942 expr {$sqlite_fullsync_count>0}
945 do_test trans-9.$i.5-$cnt {
946 expr {$sqlite_fullsync_count==0}
952 wal_check_journal_mode trans-9.$i.6-$cnt
953 set ::pager_old_format 0