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