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