• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 2001 September 15
2#
3# The author disclaims copyright to this source code.  In place of
4# a legal notice, here is a blessing:
5#
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.
9#
10#***********************************************************************
11# This file implements regression tests for SQLite library.  The
12# focus of this script is database locks.
13#
14# $Id: trans.test,v 1.41 2009/04/28 16:37:59 danielk1977 Exp $
15
16
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20# Create several tables to work with.
21#
22wal_set_journal_mode
23do_test trans-1.0 {
24  execsql {
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;
30  }
31} {one two three}
32integrity_check trans-1.0.1
33do_test trans-1.1 {
34  execsql {
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;
40  }
41} {I V X}
42do_test trans-1.9 {
43  sqlite3 altdb test.db
44  execsql {SELECT b FROM one ORDER BY a} altdb
45} {one two three}
46do_test trans-1.10 {
47  execsql {SELECT b FROM two ORDER BY a} altdb
48} {I V X}
49integrity_check trans-1.11
50wal_check_journal_mode trans-1.12
51
52# Basic transactions
53#
54do_test trans-2.1 {
55  set v [catch {execsql {BEGIN}} msg]
56  lappend v $msg
57} {0 {}}
58do_test trans-2.2 {
59  set v [catch {execsql {END}} msg]
60  lappend v $msg
61} {0 {}}
62do_test trans-2.3 {
63  set v [catch {execsql {BEGIN TRANSACTION}} msg]
64  lappend v $msg
65} {0 {}}
66do_test trans-2.4 {
67  set v [catch {execsql {COMMIT TRANSACTION}} msg]
68  lappend v $msg
69} {0 {}}
70do_test trans-2.5 {
71  set v [catch {execsql {BEGIN TRANSACTION 'foo'}} msg]
72  lappend v $msg
73} {0 {}}
74do_test trans-2.6 {
75  set v [catch {execsql {ROLLBACK TRANSACTION 'foo'}} msg]
76  lappend v $msg
77} {0 {}}
78do_test trans-2.10 {
79  execsql {
80    BEGIN;
81    SELECT a FROM one ORDER BY a;
82    SELECT a FROM two ORDER BY a;
83    END;
84  }
85} {1 2 3 1 5 10}
86integrity_check trans-2.11
87wal_check_journal_mode trans-2.12
88
89# Check the locking behavior
90#
91do_test trans-3.1 {
92  execsql {
93    BEGIN;
94    UPDATE one SET a = 0 WHERE 0;
95    SELECT a FROM one ORDER BY a;
96  }
97} {1 2 3}
98do_test trans-3.2 {
99  catchsql {
100    SELECT a FROM two ORDER BY a;
101  } altdb
102} {0 {1 5 10}}
103
104do_test trans-3.3 {
105  catchsql {
106    SELECT a FROM one ORDER BY a;
107  } altdb
108} {0 {1 2 3}}
109do_test trans-3.4 {
110  catchsql {
111    INSERT INTO one VALUES(4,'four');
112  }
113} {0 {}}
114do_test trans-3.5 {
115  catchsql {
116    SELECT a FROM two ORDER BY a;
117  } altdb
118} {0 {1 5 10}}
119do_test trans-3.6 {
120  catchsql {
121    SELECT a FROM one ORDER BY a;
122  } altdb
123} {0 {1 2 3}}
124do_test trans-3.7 {
125  catchsql {
126    INSERT INTO two VALUES(4,'IV');
127  }
128} {0 {}}
129do_test trans-3.8 {
130  catchsql {
131    SELECT a FROM two ORDER BY a;
132  } altdb
133} {0 {1 5 10}}
134do_test trans-3.9 {
135  catchsql {
136    SELECT a FROM one ORDER BY a;
137  } altdb
138} {0 {1 2 3}}
139do_test trans-3.10 {
140  execsql {END TRANSACTION}
141} {}
142
143do_test trans-3.11 {
144  set v [catch {execsql {
145    SELECT a FROM two ORDER BY a;
146  } altdb} msg]
147  lappend v $msg
148} {0 {1 4 5 10}}
149do_test trans-3.12 {
150  set v [catch {execsql {
151    SELECT a FROM one ORDER BY a;
152  } altdb} msg]
153  lappend v $msg
154} {0 {1 2 3 4}}
155do_test trans-3.13 {
156  set v [catch {execsql {
157    SELECT a FROM two ORDER BY a;
158  } db} msg]
159  lappend v $msg
160} {0 {1 4 5 10}}
161do_test trans-3.14 {
162  set v [catch {execsql {
163    SELECT a FROM one ORDER BY a;
164  } db} msg]
165  lappend v $msg
166} {0 {1 2 3 4}}
167integrity_check trans-3.15
168wal_check_journal_mode trans-3.16
169
170do_test trans-4.1 {
171  set v [catch {execsql {
172    COMMIT;
173  } db} msg]
174  lappend v $msg
175} {1 {cannot commit - no transaction is active}}
176do_test trans-4.2 {
177  set v [catch {execsql {
178    ROLLBACK;
179  } db} msg]
180  lappend v $msg
181} {1 {cannot rollback - no transaction is active}}
182do_test trans-4.3 {
183  catchsql {
184    BEGIN TRANSACTION;
185    UPDATE two SET a = 0 WHERE 0;
186    SELECT a FROM two ORDER BY a;
187  } db
188} {0 {1 4 5 10}}
189do_test trans-4.4 {
190  catchsql {
191    SELECT a FROM two ORDER BY a;
192  } altdb
193} {0 {1 4 5 10}}
194do_test trans-4.5 {
195  catchsql {
196    SELECT a FROM one ORDER BY a;
197  } altdb
198} {0 {1 2 3 4}}
199do_test trans-4.6 {
200  catchsql {
201    BEGIN TRANSACTION;
202    SELECT a FROM one ORDER BY a;
203  } db
204} {1 {cannot start a transaction within a transaction}}
205do_test trans-4.7 {
206  catchsql {
207    SELECT a FROM two ORDER BY a;
208  } altdb
209} {0 {1 4 5 10}}
210do_test trans-4.8 {
211  catchsql {
212    SELECT a FROM one ORDER BY a;
213  } altdb
214} {0 {1 2 3 4}}
215do_test trans-4.9 {
216  set v [catch {execsql {
217    END TRANSACTION;
218    SELECT a FROM two ORDER BY a;
219  } db} msg]
220  lappend v $msg
221} {0 {1 4 5 10}}
222do_test trans-4.10 {
223  set v [catch {execsql {
224    SELECT a FROM two ORDER BY a;
225  } altdb} msg]
226  lappend v $msg
227} {0 {1 4 5 10}}
228do_test trans-4.11 {
229  set v [catch {execsql {
230    SELECT a FROM one ORDER BY a;
231  } altdb} msg]
232  lappend v $msg
233} {0 {1 2 3 4}}
234integrity_check trans-4.12
235wal_check_journal_mode trans-4.13
236wal_check_journal_mode trans-4.14 altdb
237do_test trans-4.98 {
238  altdb close
239  execsql {
240    DROP TABLE one;
241    DROP TABLE two;
242  }
243} {}
244integrity_check trans-4.99
245
246# Check out the commit/rollback behavior of the database
247#
248do_test trans-5.1 {
249  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
250} {}
251do_test trans-5.2 {
252  execsql {BEGIN TRANSACTION}
253  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
254} {}
255do_test trans-5.3 {
256  execsql {CREATE TABLE one(a text, b int)}
257  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
258} {one}
259do_test trans-5.4 {
260  execsql {SELECT a,b FROM one ORDER BY b}
261} {}
262do_test trans-5.5 {
263  execsql {INSERT INTO one(a,b) VALUES('hello', 1)}
264  execsql {SELECT a,b FROM one ORDER BY b}
265} {hello 1}
266do_test trans-5.6 {
267  execsql {ROLLBACK}
268  execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
269} {}
270do_test trans-5.7 {
271  set v [catch {
272    execsql {SELECT a,b FROM one ORDER BY b}
273  } msg]
274  lappend v $msg
275} {1 {no such table: one}}
276
277# Test commits and rollbacks of table CREATE TABLEs, CREATE INDEXs
278# DROP TABLEs and DROP INDEXs
279#
280do_test trans-5.8 {
281  execsql {
282    SELECT name fROM sqlite_master
283    WHERE type='table' OR type='index'
284    ORDER BY name
285  }
286} {}
287do_test trans-5.9 {
288  execsql {
289    BEGIN TRANSACTION;
290    CREATE TABLE t1(a int, b int, c int);
291    SELECT name fROM sqlite_master
292    WHERE type='table' OR type='index'
293    ORDER BY name;
294  }
295} {t1}
296do_test trans-5.10 {
297  execsql {
298    CREATE INDEX i1 ON t1(a);
299    SELECT name fROM sqlite_master
300    WHERE type='table' OR type='index'
301    ORDER BY name;
302  }
303} {i1 t1}
304do_test trans-5.11 {
305  execsql {
306    COMMIT;
307    SELECT name fROM sqlite_master
308    WHERE type='table' OR type='index'
309    ORDER BY name;
310  }
311} {i1 t1}
312do_test trans-5.12 {
313  execsql {
314    BEGIN TRANSACTION;
315    CREATE TABLE t2(a int, b int, c int);
316    CREATE INDEX i2a ON t2(a);
317    CREATE INDEX i2b ON t2(b);
318    DROP TABLE t1;
319    SELECT name fROM sqlite_master
320    WHERE type='table' OR type='index'
321    ORDER BY name;
322  }
323} {i2a i2b t2}
324do_test trans-5.13 {
325  execsql {
326    ROLLBACK;
327    SELECT name fROM sqlite_master
328    WHERE type='table' OR type='index'
329    ORDER BY name;
330  }
331} {i1 t1}
332do_test trans-5.14 {
333  execsql {
334    BEGIN TRANSACTION;
335    DROP INDEX i1;
336    SELECT name fROM sqlite_master
337    WHERE type='table' OR type='index'
338    ORDER BY name;
339  }
340} {t1}
341do_test trans-5.15 {
342  execsql {
343    ROLLBACK;
344    SELECT name fROM sqlite_master
345    WHERE type='table' OR type='index'
346    ORDER BY name;
347  }
348} {i1 t1}
349do_test trans-5.16 {
350  execsql {
351    BEGIN TRANSACTION;
352    DROP INDEX i1;
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'
359    ORDER BY name;
360  }
361} {i2x i2y t1 t2}
362do_test trans-5.17 {
363  execsql {
364    COMMIT;
365    SELECT name fROM sqlite_master
366    WHERE type='table' OR type='index'
367    ORDER BY name;
368  }
369} {i2x i2y t1 t2}
370do_test trans-5.18 {
371  execsql {
372    SELECT * FROM t2;
373  }
374} {1 2 3}
375do_test trans-5.19 {
376  execsql {
377    SELECT x FROM t2 WHERE y=2;
378  }
379} {1}
380do_test trans-5.20 {
381  execsql {
382    BEGIN TRANSACTION;
383    DROP TABLE t1;
384    DROP TABLE t2;
385    SELECT name fROM sqlite_master
386    WHERE type='table' OR type='index'
387    ORDER BY name;
388  }
389} {}
390do_test trans-5.21 {
391  set r [catch {execsql {
392    SELECT * FROM t2
393  }} msg]
394  lappend r $msg
395} {1 {no such table: t2}}
396do_test trans-5.22 {
397  execsql {
398    ROLLBACK;
399    SELECT name fROM sqlite_master
400    WHERE type='table' OR type='index'
401    ORDER BY name;
402  }
403} {i2x i2y t1 t2}
404do_test trans-5.23 {
405  execsql {
406    SELECT * FROM t2;
407  }
408} {1 2 3}
409integrity_check trans-5.23
410
411
412# Try to DROP and CREATE tables and indices with the same name
413# within a transaction.  Make sure ROLLBACK works.
414#
415do_test trans-6.1 {
416  execsql2 {
417    INSERT INTO t1 VALUES(1,2,3);
418    BEGIN TRANSACTION;
419    DROP TABLE t1;
420    CREATE TABLE t1(p,q,r);
421    ROLLBACK;
422    SELECT * FROM t1;
423  }
424} {a 1 b 2 c 3}
425do_test trans-6.2 {
426  execsql2 {
427    INSERT INTO t1 VALUES(1,2,3);
428    BEGIN TRANSACTION;
429    DROP TABLE t1;
430    CREATE TABLE t1(p,q,r);
431    COMMIT;
432    SELECT * FROM t1;
433  }
434} {}
435do_test trans-6.3 {
436  execsql2 {
437    INSERT INTO t1 VALUES(1,2,3);
438    SELECT * FROM t1;
439  }
440} {p 1 q 2 r 3}
441do_test trans-6.4 {
442  execsql2 {
443    BEGIN TRANSACTION;
444    DROP TABLE t1;
445    CREATE TABLE t1(a,b,c);
446    INSERT INTO t1 VALUES(4,5,6);
447    SELECT * FROM t1;
448    DROP TABLE t1;
449  }
450} {a 4 b 5 c 6}
451do_test trans-6.5 {
452  execsql2 {
453    ROLLBACK;
454    SELECT * FROM t1;
455  }
456} {p 1 q 2 r 3}
457do_test trans-6.6 {
458  execsql2 {
459    BEGIN TRANSACTION;
460    DROP TABLE t1;
461    CREATE TABLE t1(a,b,c);
462    INSERT INTO t1 VALUES(4,5,6);
463    SELECT * FROM t1;
464    DROP TABLE t1;
465  }
466} {a 4 b 5 c 6}
467do_test trans-6.7 {
468  catchsql {
469    COMMIT;
470    SELECT * FROM t1;
471  }
472} {1 {no such table: t1}}
473
474# Repeat on a table with an automatically generated index.
475#
476do_test trans-6.10 {
477  execsql2 {
478    CREATE TABLE t1(a unique,b,c);
479    INSERT INTO t1 VALUES(1,2,3);
480    BEGIN TRANSACTION;
481    DROP TABLE t1;
482    CREATE TABLE t1(p unique,q,r);
483    ROLLBACK;
484    SELECT * FROM t1;
485  }
486} {a 1 b 2 c 3}
487do_test trans-6.11 {
488  execsql2 {
489    BEGIN TRANSACTION;
490    DROP TABLE t1;
491    CREATE TABLE t1(p unique,q,r);
492    COMMIT;
493    SELECT * FROM t1;
494  }
495} {}
496do_test trans-6.12 {
497  execsql2 {
498    INSERT INTO t1 VALUES(1,2,3);
499    SELECT * FROM t1;
500  }
501} {p 1 q 2 r 3}
502do_test trans-6.13 {
503  execsql2 {
504    BEGIN TRANSACTION;
505    DROP TABLE t1;
506    CREATE TABLE t1(a unique,b,c);
507    INSERT INTO t1 VALUES(4,5,6);
508    SELECT * FROM t1;
509    DROP TABLE t1;
510  }
511} {a 4 b 5 c 6}
512do_test trans-6.14 {
513  execsql2 {
514    ROLLBACK;
515    SELECT * FROM t1;
516  }
517} {p 1 q 2 r 3}
518do_test trans-6.15 {
519  execsql2 {
520    BEGIN TRANSACTION;
521    DROP TABLE t1;
522    CREATE TABLE t1(a unique,b,c);
523    INSERT INTO t1 VALUES(4,5,6);
524    SELECT * FROM t1;
525    DROP TABLE t1;
526  }
527} {a 4 b 5 c 6}
528do_test trans-6.16 {
529  catchsql {
530    COMMIT;
531    SELECT * FROM t1;
532  }
533} {1 {no such table: t1}}
534
535do_test trans-6.20 {
536  execsql {
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);
540    SELECT * FROM t1;
541  }
542} {1 -2 -3 4 -5 -6}
543do_test trans-6.21 {
544  execsql {
545    CREATE INDEX i1 ON t1(b);
546    SELECT * FROM t1 WHERE b<1;
547  }
548} {4 -5 -6 1 -2 -3}
549do_test trans-6.22 {
550  execsql {
551    BEGIN TRANSACTION;
552    DROP INDEX i1;
553    SELECT * FROM t1 WHERE b<1;
554    ROLLBACK;
555  }
556} {1 -2 -3 4 -5 -6}
557do_test trans-6.23 {
558  execsql {
559    SELECT * FROM t1 WHERE b<1;
560  }
561} {4 -5 -6 1 -2 -3}
562do_test trans-6.24 {
563  execsql {
564    BEGIN TRANSACTION;
565    DROP TABLE t1;
566    ROLLBACK;
567    SELECT * FROM t1 WHERE b<1;
568  }
569} {4 -5 -6 1 -2 -3}
570
571do_test trans-6.25 {
572  execsql {
573    BEGIN TRANSACTION;
574    DROP INDEX i1;
575    CREATE INDEX i1 ON t1(c);
576    SELECT * FROM t1 WHERE b<1;
577  }
578} {1 -2 -3 4 -5 -6}
579do_test trans-6.26 {
580  execsql {
581    SELECT * FROM t1 WHERE c<1;
582  }
583} {4 -5 -6 1 -2 -3}
584do_test trans-6.27 {
585  execsql {
586    ROLLBACK;
587    SELECT * FROM t1 WHERE b<1;
588  }
589} {4 -5 -6 1 -2 -3}
590do_test trans-6.28 {
591  execsql {
592    SELECT * FROM t1 WHERE c<1;
593  }
594} {1 -2 -3 4 -5 -6}
595
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
598# automatic index.
599#
600do_test trans-6.30 {
601  execsql {
602    BEGIN TRANSACTION;
603    DROP TABLE t1;
604    CREATE TABLE t1(a int unique,b,c);
605    COMMIT;
606    INSERT INTO t1 VALUES(1,-2,-3);
607    INSERT INTO t1 VALUES(4,-5,-6);
608    SELECT * FROM t1 ORDER BY a;
609  }
610} {1 -2 -3 4 -5 -6}
611do_test trans-6.31 {
612  execsql {
613    CREATE INDEX i1 ON t1(b);
614    SELECT * FROM t1 WHERE b<1;
615  }
616} {4 -5 -6 1 -2 -3}
617do_test trans-6.32 {
618  execsql {
619    BEGIN TRANSACTION;
620    DROP INDEX i1;
621    SELECT * FROM t1 WHERE b<1;
622    ROLLBACK;
623  }
624} {1 -2 -3 4 -5 -6}
625do_test trans-6.33 {
626  execsql {
627    SELECT * FROM t1 WHERE b<1;
628  }
629} {4 -5 -6 1 -2 -3}
630do_test trans-6.34 {
631  execsql {
632    BEGIN TRANSACTION;
633    DROP TABLE t1;
634    ROLLBACK;
635    SELECT * FROM t1 WHERE b<1;
636  }
637} {4 -5 -6 1 -2 -3}
638
639do_test trans-6.35 {
640  execsql {
641    BEGIN TRANSACTION;
642    DROP INDEX i1;
643    CREATE INDEX i1 ON t1(c);
644    SELECT * FROM t1 WHERE b<1;
645  }
646} {1 -2 -3 4 -5 -6}
647do_test trans-6.36 {
648  execsql {
649    SELECT * FROM t1 WHERE c<1;
650  }
651} {4 -5 -6 1 -2 -3}
652do_test trans-6.37 {
653  execsql {
654    DROP INDEX i1;
655    SELECT * FROM t1 WHERE c<1;
656  }
657} {1 -2 -3 4 -5 -6}
658do_test trans-6.38 {
659  execsql {
660    ROLLBACK;
661    SELECT * FROM t1 WHERE b<1;
662  }
663} {4 -5 -6 1 -2 -3}
664do_test trans-6.39 {
665  execsql {
666    SELECT * FROM t1 WHERE c<1;
667  }
668} {1 -2 -3 4 -5 -6}
669integrity_check trans-6.40
670
671# Test to make sure rollback restores the database back to its original
672# state.
673#
674do_test trans-7.1 {
675  execsql {BEGIN}
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)"
681  }
682  execsql {COMMIT}
683  set ::checksum [execsql {SELECT md5sum(x,y,z) FROM t2}]
684  set ::checksum2 [
685    execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
686  ]
687  execsql {SELECT count(*) FROM t2}
688} {1001}
689do_test trans-7.2 {
690  execsql {SELECT md5sum(x,y,z) FROM t2}
691} $checksum
692do_test trans-7.2.1 {
693  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
694} $checksum2
695do_test trans-7.3 {
696  execsql {
697    BEGIN;
698    DELETE FROM t2;
699    ROLLBACK;
700    SELECT md5sum(x,y,z) FROM t2;
701  }
702} $checksum
703do_test trans-7.4 {
704  execsql {
705    BEGIN;
706    INSERT INTO t2 SELECT * FROM t2;
707    ROLLBACK;
708    SELECT md5sum(x,y,z) FROM t2;
709  }
710} $checksum
711do_test trans-7.5 {
712  execsql {
713    BEGIN;
714    DELETE FROM t2;
715    ROLLBACK;
716    SELECT md5sum(x,y,z) FROM t2;
717  }
718} $checksum
719do_test trans-7.6 {
720  execsql {
721    BEGIN;
722    INSERT INTO t2 SELECT * FROM t2;
723    ROLLBACK;
724    SELECT md5sum(x,y,z) FROM t2;
725  }
726} $checksum
727do_test trans-7.7 {
728  execsql {
729    BEGIN;
730    CREATE TABLE t3 AS SELECT * FROM t2;
731    INSERT INTO t2 SELECT * FROM t3;
732    ROLLBACK;
733    SELECT md5sum(x,y,z) FROM t2;
734  }
735} $checksum
736do_test trans-7.8 {
737  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
738} $checksum2
739ifcapable tempdb {
740  do_test trans-7.9 {
741    execsql {
742      BEGIN;
743      CREATE TEMP TABLE t3 AS SELECT * FROM t2;
744      INSERT INTO t2 SELECT * FROM t3;
745      ROLLBACK;
746      SELECT md5sum(x,y,z) FROM t2;
747    }
748  } $checksum
749}
750do_test trans-7.10 {
751  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
752} $checksum2
753ifcapable tempdb {
754  do_test trans-7.11 {
755    execsql {
756      BEGIN;
757      CREATE TEMP TABLE t3 AS SELECT * FROM t2;
758      INSERT INTO t2 SELECT * FROM t3;
759      DROP INDEX i2x;
760      DROP INDEX i2y;
761      CREATE INDEX i3a ON t3(x);
762      ROLLBACK;
763      SELECT md5sum(x,y,z) FROM t2;
764    }
765  } $checksum
766}
767do_test trans-7.12 {
768  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
769} $checksum2
770ifcapable tempdb {
771  do_test trans-7.13 {
772    execsql {
773      BEGIN;
774      DROP TABLE t2;
775      ROLLBACK;
776      SELECT md5sum(x,y,z) FROM t2;
777    }
778  } $checksum
779}
780do_test trans-7.14 {
781  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
782} $checksum2
783integrity_check trans-7.15
784wal_check_journal_mode trans-7.16
785
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.
790#
791set fd [open test.tcl w]
792puts $fd {
793  sqlite3_test_control_pending_byte 0x0010000
794  sqlite3 db test.db
795  db eval {
796    PRAGMA default_cache_size=20;
797    BEGIN;
798    CREATE TABLE t3 AS SELECT * FROM t2;
799    DELETE FROM t2;
800  }
801  sqlite_abort
802}
803close $fd
804do_test trans-8.1 {
805  catch {exec [info nameofexec] test.tcl}
806  execsql {SELECT md5sum(x,y,z) FROM t2}
807} $checksum
808do_test trans-8.2 {
809  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
810} $checksum2
811integrity_check trans-8.3
812set fd [open test.tcl w]
813puts $fd {
814  sqlite3_test_control_pending_byte 0x0010000
815  sqlite3 db test.db
816  db eval {
817    PRAGMA journal_mode=persist;
818    PRAGMA default_cache_size=20;
819    BEGIN;
820    CREATE TABLE t3 AS SELECT * FROM t2;
821    DELETE FROM t2;
822  }
823  sqlite_abort
824}
825close $fd
826do_test trans-8.4 {
827  catch {exec [info nameofexec] test.tcl}
828  execsql {SELECT md5sum(x,y,z) FROM t2}
829} $checksum
830do_test trans-8.5 {
831  execsql {SELECT md5sum(type,name,tbl_name,rootpage,sql) FROM sqlite_master}
832} $checksum2
833integrity_check trans-8.6
834wal_check_journal_mode trans-8.7
835
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.
839#
840do_test trans-9.1 {
841  execsql {
842    PRAGMA default_cache_size=10;
843  }
844  db close
845  sqlite3 db test.db
846  execsql {
847    BEGIN;
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;
860    COMMIT;
861    SELECT count(*) FROM t3;
862  }
863} {1024}
864wal_check_journal_mode trans-9.1.1
865
866# The following procedure computes a "signature" for table "t3".  If
867# T3 changes in any way, the signature should change.
868#
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.
872#
873proc signature {} {
874  return [db eval {SELECT count(*), md5sum(x) FROM t3}]
875}
876
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.
881#
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".
885#
886if {[info exists G(isquick)] || (
887  $TEMP_STORE==3 && [regexp {^pcache[[:digit:]]*$} [permutation]]
888) } {
889  set limit 20
890} elseif {[info exists G(issoak)]} {
891  set limit 100
892} else {
893  set limit 40
894}
895
896# Do rollbacks.  Make sure the signature does not change.
897#
898for {set i 2} {$i<=$limit} {incr i} {
899  set ::sig [signature]
900  set cnt [lindex $::sig 0]
901  if {$i%2==0} {
902    execsql {PRAGMA fullfsync=ON}
903  } else {
904    execsql {PRAGMA fullfsync=OFF}
905  }
906  set sqlite_sync_count 0
907  set sqlite_fullsync_count 0
908  do_test trans-9.$i.1-$cnt {
909     execsql {
910       BEGIN;
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;
914       ROLLBACK;
915     }
916     signature
917  } $sig
918  do_test trans-9.$i.2-$cnt {
919     execsql {
920       BEGIN;
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;
925       ROLLBACK;
926     }
927     signature
928  } $sig
929  if {$i<$limit} {
930    do_test trans-9.$i.3-$cnt {
931       execsql {
932         INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0;
933       }
934    } {}
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}
939      } 1
940      ifcapable pager_pragmas {
941        do_test trans-9.$i.5-$cnt {
942           expr {$sqlite_fullsync_count>0}
943        } [expr {$i%2==0}]
944      } else {
945        do_test trans-9.$i.5-$cnt {
946          expr {$sqlite_fullsync_count==0}
947        } {1}
948      }
949    }
950  }
951
952  wal_check_journal_mode trans-9.$i.6-$cnt
953  set ::pager_old_format 0
954}
955
956finish_test
957