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