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