2 #pragma ident "%Z%%M% %I% %E% SMI"
6 # The author disclaims copyright to this source code. In place of
7 # a legal notice, here is a blessing:
9 # May you do good and not evil.
10 # May you find forgiveness for yourself and forgive others.
11 # May you share freely, never taking more than you give.
13 #***********************************************************************
14 # This file implements regression tests for SQLite library. The
15 # focus of this script is database locks.
17 # $Id: trans.test,v 1.19 2004/03/08 13:26:18 drh Exp $
20 set testdir [file dirname $argv0]
21 source $testdir/tester.tcl
24 # Create several tables to work with.
28 CREATE TABLE one(a int PRIMARY KEY, b text);
29 INSERT INTO one VALUES(1,'one');
30 INSERT INTO one VALUES(2,'two');
31 INSERT INTO one VALUES(3,'three');
32 SELECT b FROM one ORDER BY a;
37 CREATE TABLE two(a int PRIMARY KEY, b text);
38 INSERT INTO two VALUES(1,'I');
39 INSERT INTO two VALUES(5,'V');
40 INSERT INTO two VALUES(10,'X');
41 SELECT b FROM two ORDER BY a;
46 execsql {SELECT b FROM one ORDER BY a} altdb
49 execsql {SELECT b FROM two ORDER BY a} altdb
51 integrity_check trans-1.11
56 set v [catch {execsql {BEGIN}} msg]
60 set v [catch {execsql {END}} msg]
64 set v [catch {execsql {BEGIN TRANSACTION}} msg]
68 set v [catch {execsql {COMMIT TRANSACTION}} msg]
72 set v [catch {execsql {BEGIN TRANSACTION 'foo'}} msg]
76 set v [catch {execsql {ROLLBACK TRANSACTION 'foo'}} msg]
82 SELECT a FROM one ORDER BY a;
83 SELECT a FROM two ORDER BY a;
87 integrity_check trans-2.11
89 # Check the locking behavior
94 SELECT a FROM one ORDER BY a;
98 set v [catch {execsql {
99 SELECT a FROM two ORDER BY a;
102 } {1 {database is locked}}
104 set v [catch {execsql {
105 SELECT a FROM one ORDER BY a;
108 } {1 {database is locked}}
110 set v [catch {execsql {
111 INSERT INTO one VALUES(4,'four');
116 set v [catch {execsql {
117 SELECT a FROM two ORDER BY a;
120 } {1 {database is locked}}
122 set v [catch {execsql {
123 SELECT a FROM one ORDER BY a;
126 } {1 {database is locked}}
128 set v [catch {execsql {
129 INSERT INTO two VALUES(4,'IV');
134 set v [catch {execsql {
135 SELECT a FROM two ORDER BY a;
138 } {1 {database is locked}}
140 set v [catch {execsql {
141 SELECT a FROM one ORDER BY a;
144 } {1 {database is locked}}
146 execsql {END TRANSACTION}
149 set v [catch {execsql {
150 SELECT a FROM two ORDER BY a;
155 set v [catch {execsql {
156 SELECT a FROM one ORDER BY a;
161 set v [catch {execsql {
162 SELECT a FROM two ORDER BY a;
167 set v [catch {execsql {
168 SELECT a FROM one ORDER BY a;
172 integrity_check trans-3.15
175 set v [catch {execsql {
179 } {1 {cannot commit - no transaction is active}}
181 set v [catch {execsql {
185 } {1 {cannot rollback - no transaction is active}}
187 set v [catch {execsql {
189 SELECT a FROM two ORDER BY a;
194 set v [catch {execsql {
195 SELECT a FROM two ORDER BY a;
198 } {1 {database is locked}}
200 set v [catch {execsql {
201 SELECT a FROM one ORDER BY a;
204 } {1 {database is locked}}
206 set v [catch {execsql {
208 SELECT a FROM one ORDER BY a;
211 } {1 {cannot start a transaction within a transaction}}
213 set v [catch {execsql {
214 SELECT a FROM two ORDER BY a;
217 } {1 {database is locked}}
219 set v [catch {execsql {
220 SELECT a FROM one ORDER BY a;
223 } {1 {database is locked}}
225 set v [catch {execsql {
227 SELECT a FROM two ORDER BY a;
232 set v [catch {execsql {
233 SELECT a FROM two ORDER BY a;
238 set v [catch {execsql {
239 SELECT a FROM one ORDER BY a;
243 integrity_check trans-4.12
251 integrity_check trans-4.99
253 # Check out the commit/rollback behavior of the database
256 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
259 execsql {BEGIN TRANSACTION}
260 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
263 execsql {CREATE TABLE one(a text, b int)}
264 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
267 execsql {SELECT a,b FROM one ORDER BY b}
270 execsql {INSERT INTO one(a,b) VALUES('hello', 1)}
271 execsql {SELECT a,b FROM one ORDER BY b}
275 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
279 execsql {SELECT a,b FROM one ORDER BY b}
282 } {1 {no such table: one}}
284 # Test commits and rollbacks of table CREATE TABLEs, CREATE INDEXs
285 # DROP TABLEs and DROP INDEXs
289 SELECT name fROM sqlite_master
290 WHERE type='table' OR type='index'
297 CREATE TABLE t1(a int, b int, c int);
298 SELECT name fROM sqlite_master
299 WHERE type='table' OR type='index'
305 CREATE INDEX i1 ON t1(a);
306 SELECT name fROM sqlite_master
307 WHERE type='table' OR type='index'
314 SELECT name fROM sqlite_master
315 WHERE type='table' OR type='index'
322 CREATE TABLE t2(a int, b int, c int);
323 CREATE INDEX i2a ON t2(a);
324 CREATE INDEX i2b ON t2(b);
326 SELECT name fROM sqlite_master
327 WHERE type='table' OR type='index'
334 SELECT name fROM sqlite_master
335 WHERE type='table' OR type='index'
343 SELECT name fROM sqlite_master
344 WHERE type='table' OR type='index'
351 SELECT name fROM sqlite_master
352 WHERE type='table' OR type='index'
360 CREATE TABLE t2(x int, y int, z int);
361 CREATE INDEX i2x ON t2(x);
362 CREATE INDEX i2y ON t2(y);
363 INSERT INTO t2 VALUES(1,2,3);
364 SELECT name fROM sqlite_master
365 WHERE type='table' OR type='index'
372 SELECT name fROM sqlite_master
373 WHERE type='table' OR type='index'
384 SELECT x FROM t2 WHERE y=2;
392 SELECT name fROM sqlite_master
393 WHERE type='table' OR type='index'
398 set r [catch {execsql {
402 } {1 {no such table: t2}}
406 SELECT name fROM sqlite_master
407 WHERE type='table' OR type='index'
416 integrity_check trans-5.23
419 # Try to DROP and CREATE tables and indices with the same name
420 # within a transaction. Make sure ROLLBACK works.
424 INSERT INTO t1 VALUES(1,2,3);
427 CREATE TABLE t1(p,q,r);
434 INSERT INTO t1 VALUES(1,2,3);
437 CREATE TABLE t1(p,q,r);
444 INSERT INTO t1 VALUES(1,2,3);
452 CREATE TABLE t1(a,b,c);
453 INSERT INTO t1 VALUES(4,5,6);
468 CREATE TABLE t1(a,b,c);
469 INSERT INTO t1 VALUES(4,5,6);
479 } {1 {no such table: t1}}
481 # Repeat on a table with an automatically generated index.
485 CREATE TABLE t1(a unique,b,c);
486 INSERT INTO t1 VALUES(1,2,3);
489 CREATE TABLE t1(p unique,q,r);
498 CREATE TABLE t1(p unique,q,r);
505 INSERT INTO t1 VALUES(1,2,3);
513 CREATE TABLE t1(a unique,b,c);
514 INSERT INTO t1 VALUES(4,5,6);
529 CREATE TABLE t1(a unique,b,c);
530 INSERT INTO t1 VALUES(4,5,6);
540 } {1 {no such table: t1}}
544 CREATE TABLE t1(a integer primary key,b,c);
545 INSERT INTO t1 VALUES(1,-2,-3);
546 INSERT INTO t1 VALUES(4,-5,-6);
552 CREATE INDEX i1 ON t1(b);
553 SELECT * FROM t1 WHERE b<1;
560 SELECT * FROM t1 WHERE b<1;
566 SELECT * FROM t1 WHERE b<1;
574 SELECT * FROM t1 WHERE b<1;
582 CREATE INDEX i1 ON t1(c);
583 SELECT * FROM t1 WHERE b<1;
588 SELECT * FROM t1 WHERE c<1;
594 SELECT * FROM t1 WHERE b<1;
599 SELECT * FROM t1 WHERE c<1;
603 # The following repeats steps 6.20 through 6.28, but puts a "unique"
604 # constraint the first field of the table in order to generate an
611 CREATE TABLE t1(a int unique,b,c);
613 INSERT INTO t1 VALUES(1,-2,-3);
614 INSERT INTO t1 VALUES(4,-5,-6);
615 SELECT * FROM t1 ORDER BY a;
620 CREATE INDEX i1 ON t1(b);
621 SELECT * FROM t1 WHERE b<1;
628 SELECT * FROM t1 WHERE b<1;
634 SELECT * FROM t1 WHERE b<1;
642 SELECT * FROM t1 WHERE b<1;
650 CREATE INDEX i1 ON t1(c);
651 SELECT * FROM t1 WHERE b<1;
656 SELECT * FROM t1 WHERE c<1;
662 SELECT * FROM t1 WHERE c<1;
668 SELECT * FROM t1 WHERE b<1;
673 SELECT * FROM t1 WHERE c<1;
676 integrity_check trans-6.40
678 # Test to make sure rollback restores the database back to its original
683 for {set i 0} {$i<1000} {incr i} {
684 set r1 [expr {rand()}]
685 set r2 [expr {rand()}]
686 set r3 [expr {rand()}]
687 execsql "INSERT INTO t2 VALUES($r1,$r2,$r3)"
690 set ::checksum [execsql {SELECT md5sum(x,y,z) FROM t2}]
692 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
694 execsql {SELECT count(*) FROM t2}
697 execsql {SELECT md5sum(x,y,z) FROM t2}
699 do_test trans-7.2.1 {
700 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
707 SELECT md5sum(x,y,z) FROM t2;
713 INSERT INTO t2 SELECT * FROM t2;
715 SELECT md5sum(x,y,z) FROM t2;
723 SELECT md5sum(x,y,z) FROM t2;
729 INSERT INTO t2 SELECT * FROM t2;
731 SELECT md5sum(x,y,z) FROM t2;
737 CREATE TABLE t3 AS SELECT * FROM t2;
738 INSERT INTO t2 SELECT * FROM t3;
740 SELECT md5sum(x,y,z) FROM t2;
744 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
749 CREATE TEMP TABLE t3 AS SELECT * FROM t2;
750 INSERT INTO t2 SELECT * FROM t3;
752 SELECT md5sum(x,y,z) FROM t2;
756 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
761 CREATE TEMP TABLE t3 AS SELECT * FROM t2;
762 INSERT INTO t2 SELECT * FROM t3;
765 CREATE INDEX i3a ON t3(x);
767 SELECT md5sum(x,y,z) FROM t2;
771 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
778 SELECT md5sum(x,y,z) FROM t2;
782 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
784 integrity_check trans-7.15
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]
795 PRAGMA default_cache_size=20;
797 CREATE TABLE t3 AS SELECT * FROM t2;
804 catch {exec [info nameofexec] test.tcl}
805 execsql {SELECT md5sum(x,y,z) FROM t2}
808 execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
810 integrity_check trans-8.3
812 # In the following sequence of tests, compute the MD5 sum of the content
813 # of a table, make lots of modifications to that table, then do a rollback.
814 # Verify that after the rollback, the MD5 checksum is unchanged.
818 PRAGMA default_cache_size=10;
824 CREATE TABLE t3(x TEXT);
825 INSERT INTO t3 VALUES(randstr(10,400));
826 INSERT INTO t3 VALUES(randstr(10,400));
827 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
828 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
829 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
830 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
831 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
832 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
833 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
834 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
835 INSERT INTO t3 SELECT randstr(10,400) FROM t3;
837 SELECT count(*) FROM t3;
841 # The following procedure computes a "signature" for table "t3". If
842 # T3 changes in any way, the signature should change.
844 # This is used to test ROLLBACK. We gather a signature for t3, then
845 # make lots of changes to t3, then rollback and take another signature.
846 # The two signatures should be the same.
849 return [db eval {SELECT count(*), md5sum(x) FROM t3}]
852 # Repeat the following group of tests 20 times for quick testing and
853 # 40 times for full testing. Each iteration of the test makes table
854 # t3 a little larger, and thus takes a little longer, so doing 40 tests
855 # is more than 2.0 times slower than doing 20 tests. Considerably more.
857 if {[info exists ISQUICK]} {
863 # Do rollbacks. Make sure the signature does not change.
865 for {set i 2} {$i<=$limit} {incr i} {
866 set ::sig [signature]
867 set cnt [lindex $::sig 0]
868 set ::journal_format [expr {($i%3)+1}]
870 execsql {PRAGMA synchronous=FULL}
872 execsql {PRAGMA synchronous=NORMAL}
874 do_test trans-9.$i.1-$cnt {
877 DELETE FROM t3 WHERE random()%10!=0;
878 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
879 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
884 do_test trans-9.$i.2-$cnt {
887 DELETE FROM t3 WHERE random()%10!=0;
888 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
889 DELETE FROM t3 WHERE random()%10!=0;
890 INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
896 do_test trans-9.$i.9-$cnt {
898 INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0;
902 set ::pager_old_format 0