xref: /sqlite-3.40.0/test/pager1.test (revision 1f4cb65a)
1e91a54e1Sdan# 2010 June 15
2e91a54e1Sdan#
3e91a54e1Sdan# The author disclaims copyright to this source code.  In place of
4e91a54e1Sdan# a legal notice, here is a blessing:
5e91a54e1Sdan#
6e91a54e1Sdan#    May you do good and not evil.
7e91a54e1Sdan#    May you find forgiveness for yourself and forgive others.
8e91a54e1Sdan#    May you share freely, never taking more than you give.
9e91a54e1Sdan#
10e91a54e1Sdan#***********************************************************************
11e91a54e1Sdan#
12e91a54e1Sdan
13e91a54e1Sdanset testdir [file dirname $argv0]
14e91a54e1Sdansource $testdir/tester.tcl
15e91a54e1Sdansource $testdir/lock_common.tcl
16e91a54e1Sdansource $testdir/malloc_common.tcl
17e91a54e1Sdan
18b0ac3e3aSdan#
19b0ac3e3aSdan# pager1-1.*: Test inter-process locking (clients in multiple processes).
20b0ac3e3aSdan#
21b0ac3e3aSdan# pager1-2.*: Test intra-process locking (multiple clients in this process).
22b0ac3e3aSdan#
23b0ac3e3aSdan# pager1-3.*: Savepoint related tests.
24b0ac3e3aSdan#
25*1f4cb65aSdan# pager1-4.*: Hot-journal related tests.
26*1f4cb65aSdan#
27b0ac3e3aSdan
28b0ac3e3aSdanproc do_execsql_test {testname sql result} {
29b0ac3e3aSdan  uplevel do_test $testname [list "execsql {$sql}"] [list $result]
30b0ac3e3aSdan}
31b0ac3e3aSdanproc do_catchsql_test {testname sql result} {
32b0ac3e3aSdan  uplevel do_test $testname [list "catchsql {$sql}"] [list $result]
33b0ac3e3aSdan}
34b0ac3e3aSdan
3553f04f3bSdanset a_string_counter 1
3653f04f3bSdanproc a_string {n} {
3753f04f3bSdan  global a_string_counter
3853f04f3bSdan  incr a_string_counter
3953f04f3bSdan  string range [string repeat "${a_string_counter}." $n] 1 $n
4053f04f3bSdan}
4153f04f3bSdandb func a_string a_string
4253f04f3bSdan
43a4a9095eSdando_multiclient_test tn {
44e91a54e1Sdan
45e91a54e1Sdan  # Create and populate a database table using connection [db]. Check
46e91a54e1Sdan  # that connections [db2] and [db3] can see the schema and content.
47e91a54e1Sdan  #
48e91a54e1Sdan  do_test pager1-$tn.1 {
49e91a54e1Sdan    sql1 {
50e91a54e1Sdan      CREATE TABLE t1(a PRIMARY KEY, b);
51e91a54e1Sdan      CREATE INDEX i1 ON t1(b);
52e91a54e1Sdan      INSERT INTO t1 VALUES(1, 'one');
53e91a54e1Sdan      INSERT INTO t1 VALUES(2, 'two');
54e91a54e1Sdan    }
55e91a54e1Sdan  } {}
56e91a54e1Sdan  do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
57e91a54e1Sdan  do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two}
58e91a54e1Sdan
59e91a54e1Sdan  # Open a transaction and add a row using [db]. This puts [db] in
60e91a54e1Sdan  # RESERVED state. Check that connections [db2] and [db3] can still
61e91a54e1Sdan  # read the database content as it was before the transaction was
62e91a54e1Sdan  # opened. [db] should see the inserted row.
63e91a54e1Sdan  #
64e91a54e1Sdan  do_test pager1-$tn.4 {
65e91a54e1Sdan    sql1 {
66e91a54e1Sdan      BEGIN;
67e91a54e1Sdan        INSERT INTO t1 VALUES(3, 'three');
68e91a54e1Sdan    }
69e91a54e1Sdan  } {}
70e91a54e1Sdan  do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
71e91a54e1Sdan  do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three}
72e91a54e1Sdan
73e91a54e1Sdan  # [db] still has an open write transaction. Check that this prevents
74e91a54e1Sdan  # other connections (specifically [db2]) from writing to the database.
75e91a54e1Sdan  #
76e91a54e1Sdan  # Even if [db2] opens a transaction first, it may not write to the
77e91a54e1Sdan  # database. After the attempt to write the db within a transaction,
78e91a54e1Sdan  # [db2] is left with an open transaction, but not a read-lock on
79e91a54e1Sdan  # the main database. So it does not prevent [db] from committing.
80e91a54e1Sdan  #
81e91a54e1Sdan  do_test pager1-$tn.8 {
82e91a54e1Sdan    csql2 { UPDATE t1 SET a = a + 10 }
83e91a54e1Sdan  } {1 {database is locked}}
84e91a54e1Sdan  do_test pager1-$tn.9 {
85e91a54e1Sdan    csql2 {
86e91a54e1Sdan      BEGIN;
87e91a54e1Sdan      UPDATE t1 SET a = a + 10;
88e91a54e1Sdan    }
89e91a54e1Sdan  } {1 {database is locked}}
90e91a54e1Sdan
91e91a54e1Sdan  # Have [db] commit its transactions. Check the other connections can
92e91a54e1Sdan  # now see the new database content.
93e91a54e1Sdan  #
94e91a54e1Sdan  do_test pager1-$tn.10 { sql1 { COMMIT } } {}
95e91a54e1Sdan  do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three}
96e91a54e1Sdan  do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three}
97e91a54e1Sdan  do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
98e91a54e1Sdan
99e91a54e1Sdan  # Check that, as noted above, [db2] really did keep an open transaction
100e91a54e1Sdan  # after the attempt to write the database failed.
101e91a54e1Sdan  #
102e91a54e1Sdan  do_test pager1-$tn.14 {
103e91a54e1Sdan    csql2 { BEGIN }
104e91a54e1Sdan  } {1 {cannot start a transaction within a transaction}}
105e91a54e1Sdan  do_test pager1-$tn.15 { sql2 { ROLLBACK } } {}
106e91a54e1Sdan
107e91a54e1Sdan  # Have [db2] open a transaction and take a read-lock on the database.
108e91a54e1Sdan  # Check that this prevents [db] from writing to the database (outside
109e91a54e1Sdan  # of any transaction). After this fails, check that [db3] can read
110e91a54e1Sdan  # the db (showing that [db] did not take a PENDING lock etc.)
111e91a54e1Sdan  #
112e91a54e1Sdan  do_test pager1-$tn.15 {
113e91a54e1Sdan    sql2 { BEGIN; SELECT * FROM t1; }
114e91a54e1Sdan  } {1 one 2 two 3 three}
115e91a54e1Sdan  do_test pager1-$tn.16 {
116e91a54e1Sdan    csql1 { UPDATE t1 SET a = a + 10 }
117e91a54e1Sdan  } {1 {database is locked}}
118e91a54e1Sdan  do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
119e91a54e1Sdan
120e91a54e1Sdan  # This time, have [db] open a transaction before writing the database.
121e91a54e1Sdan  # This works - [db] gets a RESERVED lock which does not conflict with
122e91a54e1Sdan  # the SHARED lock [db2] is holding.
123e91a54e1Sdan  #
124e91a54e1Sdan  do_test pager1-$tn.18 {
125e91a54e1Sdan    sql1 {
126e91a54e1Sdan      BEGIN;
127e91a54e1Sdan      UPDATE t1 SET a = a + 10;
128e91a54e1Sdan    }
129e91a54e1Sdan  } {}
130e91a54e1Sdan  do_test pager1-$tn-19 {
131e91a54e1Sdan    sql1 { PRAGMA lock_status }
132e91a54e1Sdan  } {main reserved temp closed}
133e91a54e1Sdan  do_test pager1-$tn-20 {
134e91a54e1Sdan    sql2 { PRAGMA lock_status }
135e91a54e1Sdan  } {main shared temp closed}
136e91a54e1Sdan
137e91a54e1Sdan  # Check that all connections can still read the database. Only [db] sees
138e91a54e1Sdan  # the updated content (as the transaction has not been committed yet).
139e91a54e1Sdan  #
140e91a54e1Sdan  do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three}
141e91a54e1Sdan  do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three}
142e91a54e1Sdan  do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
143e91a54e1Sdan
144e91a54e1Sdan  # Because [db2] still has the SHARED lock, [db] is unable to commit the
145e91a54e1Sdan  # transaction. If it tries, an error is returned and the connection
146e91a54e1Sdan  # upgrades to a PENDING lock.
147e91a54e1Sdan  #
148e91a54e1Sdan  # Once this happens, [db] can read the database and see the new content,
149e91a54e1Sdan  # [db2] (still holding SHARED) can still read the old content, but [db3]
150e91a54e1Sdan  # (not holding any lock) is prevented by [db]'s PENDING from reading
151e91a54e1Sdan  # the database.
152e91a54e1Sdan  #
153e91a54e1Sdan  do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}}
154e91a54e1Sdan  do_test pager1-$tn-25 {
155e91a54e1Sdan    sql1 { PRAGMA lock_status }
156e91a54e1Sdan  } {main pending temp closed}
157e91a54e1Sdan  do_test pager1-$tn.26 { sql1 { SELECT * FROM t1  } } {11 one 12 two 13 three}
158e91a54e1Sdan  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1  } } {1 one 2 two 3 three}
159e91a54e1Sdan  do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}}
160e91a54e1Sdan
161e91a54e1Sdan  # Have [db2] commit its read transaction, releasing the SHARED lock it
162e91a54e1Sdan  # is holding. Now, neither [db2] nor [db3] may read the database (as [db]
163e91a54e1Sdan  # is still holding a PENDING).
164e91a54e1Sdan  #
165e91a54e1Sdan  do_test pager1-$tn.29 { sql2 { COMMIT } } {}
166e91a54e1Sdan  do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}}
167e91a54e1Sdan  do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}}
168e91a54e1Sdan
169e91a54e1Sdan  # [db] is now able to commit the transaction. Once the transaction is
170e91a54e1Sdan  # committed, all three connections can read the new content.
171e91a54e1Sdan  #
172e91a54e1Sdan  do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {}
173e91a54e1Sdan  do_test pager1-$tn.26 { sql1 { COMMIT } } {}
174e91a54e1Sdan  do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three}
175e91a54e1Sdan  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three}
176e91a54e1Sdan  do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three}
177e91a54e1Sdan}
178e91a54e1Sdan
17953f04f3bSdan#-------------------------------------------------------------------------
18053f04f3bSdan# Savepoint related test cases.
18153f04f3bSdan#
182b0ac3e3aSdando_test pager1-3.1 {
183b0ac3e3aSdan  faultsim_delete_and_reopen
184b0ac3e3aSdan  execsql {
185b0ac3e3aSdan    CREATE TABLE t1(a PRIMARY KEY, b);
186b0ac3e3aSdan    CREATE TABLE counter(
187b0ac3e3aSdan      i CHECK (i<5),
188b0ac3e3aSdan      u CHECK (u<10)
189b0ac3e3aSdan    );
190b0ac3e3aSdan    INSERT INTO counter VALUES(0, 0);
191b0ac3e3aSdan    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
192b0ac3e3aSdan      UPDATE counter SET i = i+1;
193b0ac3e3aSdan    END;
194b0ac3e3aSdan    CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN
195b0ac3e3aSdan      UPDATE counter SET u = u+1;
196b0ac3e3aSdan    END;
197b0ac3e3aSdan  }
198b0ac3e3aSdan  execsql { SELECT * FROM counter }
199b0ac3e3aSdan} {0 0}
200b0ac3e3aSdan
201b0ac3e3aSdando_execsql_test pager1-3.2 {
202b0ac3e3aSdan  BEGIN;
203b0ac3e3aSdan    INSERT INTO t1 VALUES(1, randomblob(1500));
204b0ac3e3aSdan    INSERT INTO t1 VALUES(2, randomblob(1500));
205b0ac3e3aSdan    INSERT INTO t1 VALUES(3, randomblob(1500));
206b0ac3e3aSdan    SELECT * FROM counter;
207b0ac3e3aSdan} {3 0}
208b0ac3e3aSdando_catchsql_test pager1-3.3 {
209b0ac3e3aSdan    INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1
210b0ac3e3aSdan} {1 {constraint failed}}
211b0ac3e3aSdando_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0}
212b0ac3e3aSdando_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3}
213b0ac3e3aSdando_execsql_test pager1-3.6 { COMMIT } {}
214b0ac3e3aSdan
215*1f4cb65aSdantestvfs tv -default 1
216*1f4cb65aSdanforeach code [list {
217*1f4cb65aSdan  set s 512
218*1f4cb65aSdan  set sql { PRAGMA synchronous = off }
219*1f4cb65aSdan} {
220*1f4cb65aSdan  set s 1024
221*1f4cb65aSdan  set sql { PRAGMA journal_mode = memory }
222*1f4cb65aSdan} {
223*1f4cb65aSdan  set s 2048
224*1f4cb65aSdan  tv devchar safe_append
225*1f4cb65aSdan} {
226*1f4cb65aSdan  set s 4096
227*1f4cb65aSdan  set sql { PRAGMA journal_mode = WAL }
228*1f4cb65aSdan}] {
229*1f4cb65aSdan  eval $code
230*1f4cb65aSdan  tv sectorsize $s
231*1f4cb65aSdan
232*1f4cb65aSdan  do_test pager1-3.7.$s.1 {
233*1f4cb65aSdan    faultsim_delete_and_reopen
234*1f4cb65aSdan    execsql $sql
235*1f4cb65aSdan    execsql {
236*1f4cb65aSdan      PRAGMA cache_size = 10;
237*1f4cb65aSdan      CREATE TABLE t1(i INTEGER PRIMARY KEY, j blob);
238*1f4cb65aSdan    }
239*1f4cb65aSdan  } {}
240*1f4cb65aSdan
241*1f4cb65aSdan  set tn 0
242*1f4cb65aSdan  set lowpoint 0
243*1f4cb65aSdan  foreach x {
244*1f4cb65aSdan    70 22 96 59 96 50 22 56 21 16 37 64 43 40  0 38 22 38 55  0  6
245*1f4cb65aSdan    43 62 32 93 54 18 13 29 45 66 29 25 61 31 53 82 75 25 96 86 10 69
246*1f4cb65aSdan     2 29  6 60 80 95 42 82 85 50 68 96 90 39 78 69 87 97 48 74 65 43
247*1f4cb65aSdan  x
248*1f4cb65aSdan    86 34 26 50 41 85 58 44 89 22  6 51 45 46 58 32 97  6  1 12 32  2
249*1f4cb65aSdan    69 39 48 71 33 31  5 58 90 43 24 54 12  9 18 57  4 38 91 42 27 45
250*1f4cb65aSdan    50 38 56 29 10  0 26 37 83  1 78 15 47 30 75 62 46 29 68  5 30  4
251*1f4cb65aSdan    27 96 33 95 79 75 56 10 29 70 32 75 52 88  5 36 50 57 46 63 88 65
252*1f4cb65aSdan  x
253*1f4cb65aSdan    44 95 64 20 24 35 69 61 61  2 35 92 42 46 23 98 78  1 38 72 79 35
254*1f4cb65aSdan    94 37 13 59  5 93 27 58 80 75 58  7 67 13 10 76 84  4  8 70 81 45
255*1f4cb65aSdan     8 41 98  5 60 26 92 29 91 90  2 62 40  4  5 22 80 15 83 76 52 88
256*1f4cb65aSdan    29  5 68 73 72  7 54 17 89 32 81 94 51 28 53 71  8 42 54 59 70 79
257*1f4cb65aSdan  x
258*1f4cb65aSdan    35 59 37 22  8 72 10 48 79  6 87 96 59 95 45 56  6  4 86 68 25 28
259*1f4cb65aSdan    43 75 47  9 53 18 69 51 11 94 86 65 23 87 49 19 20 20 33 14 11 86
260*1f4cb65aSdan    42 23  8 40 94 55  4 38 52 30  6 25 44 79 57 82 30 87 86 75 40 92
261*1f4cb65aSdan    29 26 82 91 67 64 15 51 17 11 15 27 32  7 38  1 52 82 26 99 17 18
262*1f4cb65aSdan    38 13 20 65 91 98 50 81 49 15 94 45 84 35 31 67 13 43 78  3 94 77
263*1f4cb65aSdan    47 18 96 66 99 77 11 11 70 18  1 29 79 57 59 86 94 34 91 15 24 53
264*1f4cb65aSdan    61 73 58 46 36 79 90 89 12  0 91  0 86 44 71 83 75 76 97 65 13 80
265*1f4cb65aSdan    42 39 15 44 90 18 67 69  1 72 17 99 12 72 77 17  3 34 75 59 92 76
266*1f4cb65aSdan    18 86 60 12 20 98 48 14 12 67 45 44 10  2  5 88  7 45  5 47 45 75
267*1f4cb65aSdan    19 25 42 62 66 17 94 63  0 53 38 81 26 11 97 33 13 36 81 82 73 26
268*1f4cb65aSdan    78 90 28 78 26 61  9 74 70 53 17 86 51 90  3 30 99  5 25 44  6 72
269*1f4cb65aSdan    84 32 74 46 16 44 74 82 84  9 58 90 85 82 53 40 37
270*1f4cb65aSdan  } {
271*1f4cb65aSdan    incr tn
272*1f4cb65aSdan    set now [db one {SELECT count(i) FROM t1}]
273*1f4cb65aSdan    if {$x == "x"} {
274*1f4cb65aSdan      execsql { COMMIT ; BEGIN }
275*1f4cb65aSdan      set lowpoint $now
276*1f4cb65aSdan      do_test pager1.3.7.$s.2.$tn {
277*1f4cb65aSdan        sqlite3 db2 test.db
278*1f4cb65aSdan        execsql {
279*1f4cb65aSdan          SELECT COALESCE(max(i), 0) FROM t1;
280*1f4cb65aSdan          PRAGMA integrity_check;
281*1f4cb65aSdan        }
282*1f4cb65aSdan      } [list $lowpoint ok]
283*1f4cb65aSdan      db2 close
284*1f4cb65aSdan    } else {
285*1f4cb65aSdan      if {$now > $x } {
286*1f4cb65aSdan        if { $x>=$lowpoint } {
287*1f4cb65aSdan          execsql "ROLLBACK TO sp_$x"
288*1f4cb65aSdan        } else {
289*1f4cb65aSdan          execsql "DELETE FROM t1 WHERE i>$x"
290*1f4cb65aSdan          set lowpoint $x
291*1f4cb65aSdan        }
292*1f4cb65aSdan      } elseif {$now < $x} {
293*1f4cb65aSdan        for {set k $now} {$k < $x} {incr k} {
294*1f4cb65aSdan          execsql "SAVEPOINT sp_$k"
295*1f4cb65aSdan          execsql { INSERT INTO t1(j) VALUES(randomblob(1500)) }
296*1f4cb65aSdan        }
297*1f4cb65aSdan      }
298*1f4cb65aSdan      do_execsql_test pager1.3.7.$s.2.$tn {
299*1f4cb65aSdan        SELECT COALESCE(max(i), 0) FROM t1;
300*1f4cb65aSdan        PRAGMA integrity_check;
301*1f4cb65aSdan      } [list $x ok]
302*1f4cb65aSdan    }
303*1f4cb65aSdan  }
304*1f4cb65aSdan}
305*1f4cb65aSdandb close
306*1f4cb65aSdantv delete
307*1f4cb65aSdan
30853f04f3bSdan#-------------------------------------------------------------------------
30953f04f3bSdan# Hot journal rollback related test cases.
31053f04f3bSdan#
31153f04f3bSdan# pager1.4.1.*: Test that the pager module deletes very small invalid
31253f04f3bSdan#               journal files.
31353f04f3bSdan#
31453f04f3bSdan# pager1.4.2.*: Test that if the master journal pointer at the end of a
31553f04f3bSdan#               hot-journal file appears to be corrupt (checksum does not
31653f04f3bSdan#               compute) the associated journal is rolled back (and no
31753f04f3bSdan#               xAccess() call to check for the presence of any master
31853f04f3bSdan#               journal file is made).
31953f04f3bSdan#
32053f04f3bSdando_test pager1.4.1.1 {
32153f04f3bSdan  faultsim_delete_and_reopen
32253f04f3bSdan  execsql {
32353f04f3bSdan    CREATE TABLE x(y, z);
32453f04f3bSdan    INSERT INTO x VALUES(1, 2);
32553f04f3bSdan  }
32653f04f3bSdan  set fd [open test.db-journal w]
32753f04f3bSdan  puts -nonewline $fd "helloworld"
32853f04f3bSdan  close $fd
32953f04f3bSdan  file exists test.db-journal
33053f04f3bSdan} {1}
33153f04f3bSdando_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2}
33253f04f3bSdando_test pager1.4.1.3 { file exists test.db-journal } {0}
33353f04f3bSdan
33453f04f3bSdan# Set up a [testvfs] to snapshot the file-system just before SQLite
33553f04f3bSdan# deletes the master-journal to commit a multi-file transaction.
33653f04f3bSdan#
33753f04f3bSdan# In subsequent test cases, invoking [faultsim_restore_and_reopen] sets
33853f04f3bSdan# up the file system to contain two databases, two hot-journal files and
33953f04f3bSdan# a master-journal.
34053f04f3bSdan#
34153f04f3bSdando_test pager1.4.2.1 {
34253f04f3bSdan  testvfs tstvfs -default 1
34353f04f3bSdan  tstvfs filter xDelete
34453f04f3bSdan  tstvfs script xDeleteCallback
34553f04f3bSdan  proc xDeleteCallback {method file args} {
34653f04f3bSdan    set file [file tail $file]
34753f04f3bSdan    if { [string match *mj* $file] } { faultsim_save }
34853f04f3bSdan  }
34953f04f3bSdan  faultsim_delete_and_reopen
35053f04f3bSdan  db func a_string a_string
35153f04f3bSdan  execsql {
35253f04f3bSdan    ATTACH 'test.db2' AS aux;
35353f04f3bSdan    PRAGMA journal_mode = DELETE;
35453f04f3bSdan    PRAGMA main.cache_size = 10;
35553f04f3bSdan    PRAGMA aux.cache_size = 10;
35653f04f3bSdan    CREATE TABLE t1(a UNIQUE, b UNIQUE);
35753f04f3bSdan    CREATE TABLE aux.t2(a UNIQUE, b UNIQUE);
35853f04f3bSdan    INSERT INTO t1 VALUES(a_string(200), a_string(300));
35953f04f3bSdan    INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
36053f04f3bSdan    INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
36153f04f3bSdan    INSERT INTO t2 SELECT * FROM t1;
36253f04f3bSdan    BEGIN;
36353f04f3bSdan      INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
36453f04f3bSdan      INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
36553f04f3bSdan      INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
36653f04f3bSdan      INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
36753f04f3bSdan      REPLACE INTO t2 SELECT * FROM t1;
36853f04f3bSdan    COMMIT;
36953f04f3bSdan  }
37053f04f3bSdan  db close
37153f04f3bSdan  tstvfs delete
37253f04f3bSdan} {}
37353f04f3bSdando_test pager1.4.2.2 {
37453f04f3bSdan  faultsim_restore_and_reopen
37553f04f3bSdan  execsql {
37653f04f3bSdan    SELECT count(*) FROM t1;
37753f04f3bSdan    PRAGMA integrity_check;
37853f04f3bSdan  }
37953f04f3bSdan} {4 ok}
38053f04f3bSdando_test pager1.4.2.3 {
38153f04f3bSdan  faultsim_restore_and_reopen
38253f04f3bSdan  foreach f [glob test.db-mj*] { file delete -force $f }
38353f04f3bSdan  execsql {
38453f04f3bSdan    SELECT count(*) FROM t1;
38553f04f3bSdan    PRAGMA integrity_check;
38653f04f3bSdan  }
38753f04f3bSdan} {64 ok}
38853f04f3bSdando_test pager1.4.2.4 {
38953f04f3bSdan  faultsim_restore_and_reopen
39053f04f3bSdan  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
39153f04f3bSdan  execsql {
39253f04f3bSdan    SELECT count(*) FROM t1;
39353f04f3bSdan    PRAGMA integrity_check;
39453f04f3bSdan  }
39553f04f3bSdan} {4 ok}
39653f04f3bSdando_test pager1.4.2.5 {
39753f04f3bSdan  faultsim_restore_and_reopen
39853f04f3bSdan  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
39953f04f3bSdan  foreach f [glob test.db-mj*] { file delete -force $f }
40053f04f3bSdan  execsql {
40153f04f3bSdan    SELECT count(*) FROM t1;
40253f04f3bSdan    PRAGMA integrity_check;
40353f04f3bSdan  }
40453f04f3bSdan} {4 ok}
40553f04f3bSdan
406e91a54e1Sdanfinish_test
407e91a54e1Sdan
408