xref: /sqlite-3.40.0/test/pager1.test (revision c396d4af)
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
17153eda0aSdansource $testdir/wal_common.tcl
1868928b6cSdan
1968928b6cSdan# Do not use a codec for tests in this file, as the database file is
2068928b6cSdan# manipulated directly using tcl scripts (using the [hexio_write] command).
2168928b6cSdan#
2268928b6cSdando_not_use_codec
23e91a54e1Sdan
24b0ac3e3aSdan#
25b0ac3e3aSdan# pager1-1.*: Test inter-process locking (clients in multiple processes).
26b0ac3e3aSdan#
27b0ac3e3aSdan# pager1-2.*: Test intra-process locking (multiple clients in this process).
28b0ac3e3aSdan#
29b0ac3e3aSdan# pager1-3.*: Savepoint related tests.
30b0ac3e3aSdan#
311f4cb65aSdan# pager1-4.*: Hot-journal related tests.
321f4cb65aSdan#
33de4996e2Sdan# pager1-5.*: Cases related to multi-file commits.
34de4996e2Sdan#
35146ed78bSdan# pager1-6.*: Cases related to "PRAGMA max_page_count"
36146ed78bSdan#
37153eda0aSdan# pager1-7.*: Cases specific to "PRAGMA journal_mode=TRUNCATE"
38153eda0aSdan#
390e986f51Sdan# pager1-8.*: Cases using temporary and in-memory databases.
400e986f51Sdan#
41dca321aeSdan# pager1-9.*: Tests related to the backup API.
42dca321aeSdan#
43ec6ffc1aSdan# pager1-10.*: Test that the assumed file-system sector-size is limited to
44ec6ffc1aSdan#              64KB.
45ec6ffc1aSdan#
46d353331aSdan# pager1-12.*: Tests involving "PRAGMA page_size"
47d353331aSdan#
48d353331aSdan# pager1-13.*: Cases specific to "PRAGMA journal_mode=PERSIST"
49d353331aSdan#
50d353331aSdan# pager1-14.*: Cases specific to "PRAGMA journal_mode=OFF"
51ec6ffc1aSdan#
52c8ce3972Sdan# pager1-15.*: Varying sqlite3_vfs.szOsFile
53c8ce3972Sdan#
54c8ce3972Sdan# pager1-16.*: Varying sqlite3_vfs.mxPathname
55c8ce3972Sdan#
56c8ce3972Sdan# pager1-17.*: Tests related to "PRAGMA omit_readlock"
57c8ce3972Sdan#
58c8ce3972Sdan# pager1-18.*: Test that the pager layer responds correctly if the b-tree
59c8ce3972Sdan#              requests an invalid page number (due to db corruption).
60c8ce3972Sdan#
61b0ac3e3aSdan
62*c396d4afSdanproc recursive_select {id table {script {}}} {
63*c396d4afSdan  set cnt 0
64*c396d4afSdan  db eval "SELECT rowid, * FROM $table WHERE rowid = ($id-1)" {
65*c396d4afSdan    recursive_select $rowid $table $script
66*c396d4afSdan    incr cnt
67*c396d4afSdan  }
68*c396d4afSdan  if {$cnt==0} { eval $script }
69*c396d4afSdan}
70*c396d4afSdan
7153f04f3bSdanset a_string_counter 1
7253f04f3bSdanproc a_string {n} {
7353f04f3bSdan  global a_string_counter
7453f04f3bSdan  incr a_string_counter
7553f04f3bSdan  string range [string repeat "${a_string_counter}." $n] 1 $n
7653f04f3bSdan}
7753f04f3bSdandb func a_string a_string
7853f04f3bSdan
79a4a9095eSdando_multiclient_test tn {
80e91a54e1Sdan
81e91a54e1Sdan  # Create and populate a database table using connection [db]. Check
82e91a54e1Sdan  # that connections [db2] and [db3] can see the schema and content.
83e91a54e1Sdan  #
84e91a54e1Sdan  do_test pager1-$tn.1 {
85e91a54e1Sdan    sql1 {
86e91a54e1Sdan      CREATE TABLE t1(a PRIMARY KEY, b);
87e91a54e1Sdan      CREATE INDEX i1 ON t1(b);
88d353331aSdan      INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two');
89e91a54e1Sdan    }
90e91a54e1Sdan  } {}
91e91a54e1Sdan  do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
92e91a54e1Sdan  do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two}
93e91a54e1Sdan
94e91a54e1Sdan  # Open a transaction and add a row using [db]. This puts [db] in
95e91a54e1Sdan  # RESERVED state. Check that connections [db2] and [db3] can still
96e91a54e1Sdan  # read the database content as it was before the transaction was
97e91a54e1Sdan  # opened. [db] should see the inserted row.
98e91a54e1Sdan  #
99e91a54e1Sdan  do_test pager1-$tn.4 {
100e91a54e1Sdan    sql1 {
101e91a54e1Sdan      BEGIN;
102e91a54e1Sdan        INSERT INTO t1 VALUES(3, 'three');
103e91a54e1Sdan    }
104e91a54e1Sdan  } {}
105e91a54e1Sdan  do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
106e91a54e1Sdan  do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three}
107e91a54e1Sdan
108e91a54e1Sdan  # [db] still has an open write transaction. Check that this prevents
109e91a54e1Sdan  # other connections (specifically [db2]) from writing to the database.
110e91a54e1Sdan  #
111e91a54e1Sdan  # Even if [db2] opens a transaction first, it may not write to the
112e91a54e1Sdan  # database. After the attempt to write the db within a transaction,
113e91a54e1Sdan  # [db2] is left with an open transaction, but not a read-lock on
114e91a54e1Sdan  # the main database. So it does not prevent [db] from committing.
115e91a54e1Sdan  #
116e91a54e1Sdan  do_test pager1-$tn.8 {
117e91a54e1Sdan    csql2 { UPDATE t1 SET a = a + 10 }
118e91a54e1Sdan  } {1 {database is locked}}
119e91a54e1Sdan  do_test pager1-$tn.9 {
120e91a54e1Sdan    csql2 {
121e91a54e1Sdan      BEGIN;
122e91a54e1Sdan      UPDATE t1 SET a = a + 10;
123e91a54e1Sdan    }
124e91a54e1Sdan  } {1 {database is locked}}
125e91a54e1Sdan
126e91a54e1Sdan  # Have [db] commit its transactions. Check the other connections can
127e91a54e1Sdan  # now see the new database content.
128e91a54e1Sdan  #
129e91a54e1Sdan  do_test pager1-$tn.10 { sql1 { COMMIT } } {}
130e91a54e1Sdan  do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three}
131e91a54e1Sdan  do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three}
132e91a54e1Sdan  do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
133e91a54e1Sdan
134e91a54e1Sdan  # Check that, as noted above, [db2] really did keep an open transaction
135e91a54e1Sdan  # after the attempt to write the database failed.
136e91a54e1Sdan  #
137e91a54e1Sdan  do_test pager1-$tn.14 {
138e91a54e1Sdan    csql2 { BEGIN }
139e91a54e1Sdan  } {1 {cannot start a transaction within a transaction}}
140e91a54e1Sdan  do_test pager1-$tn.15 { sql2 { ROLLBACK } } {}
141e91a54e1Sdan
142e91a54e1Sdan  # Have [db2] open a transaction and take a read-lock on the database.
143e91a54e1Sdan  # Check that this prevents [db] from writing to the database (outside
144e91a54e1Sdan  # of any transaction). After this fails, check that [db3] can read
145e91a54e1Sdan  # the db (showing that [db] did not take a PENDING lock etc.)
146e91a54e1Sdan  #
147e91a54e1Sdan  do_test pager1-$tn.15 {
148e91a54e1Sdan    sql2 { BEGIN; SELECT * FROM t1; }
149e91a54e1Sdan  } {1 one 2 two 3 three}
150e91a54e1Sdan  do_test pager1-$tn.16 {
151e91a54e1Sdan    csql1 { UPDATE t1 SET a = a + 10 }
152e91a54e1Sdan  } {1 {database is locked}}
153e91a54e1Sdan  do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
154e91a54e1Sdan
155e91a54e1Sdan  # This time, have [db] open a transaction before writing the database.
156e91a54e1Sdan  # This works - [db] gets a RESERVED lock which does not conflict with
157e91a54e1Sdan  # the SHARED lock [db2] is holding.
158e91a54e1Sdan  #
159e91a54e1Sdan  do_test pager1-$tn.18 {
160e91a54e1Sdan    sql1 {
161e91a54e1Sdan      BEGIN;
162e91a54e1Sdan      UPDATE t1 SET a = a + 10;
163e91a54e1Sdan    }
164e91a54e1Sdan  } {}
165e91a54e1Sdan  do_test pager1-$tn-19 {
166e91a54e1Sdan    sql1 { PRAGMA lock_status }
167e91a54e1Sdan  } {main reserved temp closed}
168e91a54e1Sdan  do_test pager1-$tn-20 {
169e91a54e1Sdan    sql2 { PRAGMA lock_status }
170e91a54e1Sdan  } {main shared temp closed}
171e91a54e1Sdan
172e91a54e1Sdan  # Check that all connections can still read the database. Only [db] sees
173e91a54e1Sdan  # the updated content (as the transaction has not been committed yet).
174e91a54e1Sdan  #
175e91a54e1Sdan  do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three}
176e91a54e1Sdan  do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three}
177e91a54e1Sdan  do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
178e91a54e1Sdan
179e91a54e1Sdan  # Because [db2] still has the SHARED lock, [db] is unable to commit the
180e91a54e1Sdan  # transaction. If it tries, an error is returned and the connection
181e91a54e1Sdan  # upgrades to a PENDING lock.
182e91a54e1Sdan  #
183e91a54e1Sdan  # Once this happens, [db] can read the database and see the new content,
184e91a54e1Sdan  # [db2] (still holding SHARED) can still read the old content, but [db3]
185e91a54e1Sdan  # (not holding any lock) is prevented by [db]'s PENDING from reading
186e91a54e1Sdan  # the database.
187e91a54e1Sdan  #
188e91a54e1Sdan  do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}}
189e91a54e1Sdan  do_test pager1-$tn-25 {
190e91a54e1Sdan    sql1 { PRAGMA lock_status }
191e91a54e1Sdan  } {main pending temp closed}
192e91a54e1Sdan  do_test pager1-$tn.26 { sql1 { SELECT * FROM t1  } } {11 one 12 two 13 three}
193e91a54e1Sdan  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1  } } {1 one 2 two 3 three}
194e91a54e1Sdan  do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}}
195e91a54e1Sdan
196e91a54e1Sdan  # Have [db2] commit its read transaction, releasing the SHARED lock it
197e91a54e1Sdan  # is holding. Now, neither [db2] nor [db3] may read the database (as [db]
198e91a54e1Sdan  # is still holding a PENDING).
199e91a54e1Sdan  #
200e91a54e1Sdan  do_test pager1-$tn.29 { sql2 { COMMIT } } {}
201e91a54e1Sdan  do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}}
202e91a54e1Sdan  do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}}
203e91a54e1Sdan
204e91a54e1Sdan  # [db] is now able to commit the transaction. Once the transaction is
205e91a54e1Sdan  # committed, all three connections can read the new content.
206e91a54e1Sdan  #
207e91a54e1Sdan  do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {}
208e91a54e1Sdan  do_test pager1-$tn.26 { sql1 { COMMIT } } {}
209e91a54e1Sdan  do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three}
210e91a54e1Sdan  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three}
211e91a54e1Sdan  do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three}
212d353331aSdan
213d353331aSdan  # Install a busy-handler for connection [db].
214d353331aSdan  #
215d353331aSdan  set ::nbusy [list]
216d353331aSdan  proc busy {n} {
217d353331aSdan    lappend ::nbusy $n
218d353331aSdan    if {$n>5} { sql2 COMMIT }
219d353331aSdan    return 0
220d353331aSdan  }
221d353331aSdan  db busy busy
222d353331aSdan
223d353331aSdan  do_test pager1-$tn.29 {
224d353331aSdan    sql1 { BEGIN ; INSERT INTO t1 VALUES('x', 'y') }
225d353331aSdan  } {}
226d353331aSdan  do_test pager1-$tn.30 {
227d353331aSdan    sql2 { BEGIN ; SELECT * FROM t1 }
228d353331aSdan  } {21 one 22 two 23 three}
229d353331aSdan  do_test pager1-$tn.31 { sql1 COMMIT } {}
230d353331aSdan  do_test pager1-$tn.32 { set ::nbusy } {0 1 2 3 4 5 6}
231e91a54e1Sdan}
232e91a54e1Sdan
23353f04f3bSdan#-------------------------------------------------------------------------
23453f04f3bSdan# Savepoint related test cases.
23553f04f3bSdan#
236dca321aeSdan# pager1-3.1.2.*: Force a savepoint rollback to cause the database file
237dca321aeSdan#                 to grow.
238dca321aeSdan#
239273f3f0dSdan# pager1-3.1.3.*: Use a journal created in synchronous=off mode as part
240273f3f0dSdan#                 of a savepoint rollback.
241273f3f0dSdan#
2420e986f51Sdando_test pager1-3.1.1 {
243b0ac3e3aSdan  faultsim_delete_and_reopen
244b0ac3e3aSdan  execsql {
245b0ac3e3aSdan    CREATE TABLE t1(a PRIMARY KEY, b);
246b0ac3e3aSdan    CREATE TABLE counter(
247b0ac3e3aSdan      i CHECK (i<5),
248b0ac3e3aSdan      u CHECK (u<10)
249b0ac3e3aSdan    );
250b0ac3e3aSdan    INSERT INTO counter VALUES(0, 0);
251b0ac3e3aSdan    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
252b0ac3e3aSdan      UPDATE counter SET i = i+1;
253b0ac3e3aSdan    END;
254b0ac3e3aSdan    CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN
255b0ac3e3aSdan      UPDATE counter SET u = u+1;
256b0ac3e3aSdan    END;
257b0ac3e3aSdan  }
258b0ac3e3aSdan  execsql { SELECT * FROM counter }
259b0ac3e3aSdan} {0 0}
260b0ac3e3aSdan
2610e986f51Sdando_execsql_test pager1-3.1.2 {
262d353331aSdan  PRAGMA cache_size = 10;
263b0ac3e3aSdan  BEGIN;
264b0ac3e3aSdan    INSERT INTO t1 VALUES(1, randomblob(1500));
265b0ac3e3aSdan    INSERT INTO t1 VALUES(2, randomblob(1500));
266b0ac3e3aSdan    INSERT INTO t1 VALUES(3, randomblob(1500));
267b0ac3e3aSdan    SELECT * FROM counter;
268b0ac3e3aSdan} {3 0}
2690e986f51Sdando_catchsql_test pager1-3.1.3 {
270b0ac3e3aSdan    INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1
271b0ac3e3aSdan} {1 {constraint failed}}
272b0ac3e3aSdando_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0}
273b0ac3e3aSdando_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3}
274b0ac3e3aSdando_execsql_test pager1-3.6 { COMMIT } {}
275b0ac3e3aSdan
276273f3f0dSdanforeach {tn sql tcl} {
277d353331aSdan  7  { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 0 } {
278273f3f0dSdan    testvfs tv -default 1
279273f3f0dSdan    tv devchar safe_append
280273f3f0dSdan  }
281d353331aSdan  8  { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 2 } {
282d353331aSdan    testvfs tv -default 1
283d353331aSdan    tv devchar sequential
284d353331aSdan  }
285d353331aSdan  9  { PRAGMA synchronous = FULL } { }
286d353331aSdan  10 { PRAGMA synchronous = NORMAL } { }
287d353331aSdan  11 { PRAGMA synchronous = OFF } { }
288d353331aSdan  12 { PRAGMA synchronous = FULL ; PRAGMA fullfsync = 1 } { }
289d353331aSdan  13 { PRAGMA synchronous = FULL } {
290d353331aSdan    testvfs tv -default 1
291d353331aSdan    tv devchar sequential
292d353331aSdan  }
2936b63ab47Sdan  14 { PRAGMA locking_mode = EXCLUSIVE } {
2946b63ab47Sdan  }
295273f3f0dSdan} {
296273f3f0dSdan  do_test pager1-3.$tn.1 {
297273f3f0dSdan    eval $tcl
298dca321aeSdan    faultsim_delete_and_reopen
299dca321aeSdan    db func a_string a_string
300273f3f0dSdan    execsql $sql
301dca321aeSdan    execsql {
302dca321aeSdan      PRAGMA auto_vacuum = 2;
303dca321aeSdan      PRAGMA cache_size = 10;
304dca321aeSdan      CREATE TABLE z(x INTEGER PRIMARY KEY, y);
305dca321aeSdan      BEGIN;
306dca321aeSdan        INSERT INTO z VALUES(NULL, a_string(800));
307dca321aeSdan        INSERT INTO z SELECT NULL, a_string(800) FROM z;     --   2
308dca321aeSdan        INSERT INTO z SELECT NULL, a_string(800) FROM z;     --   4
309dca321aeSdan        INSERT INTO z SELECT NULL, a_string(800) FROM z;     --   8
310dca321aeSdan        INSERT INTO z SELECT NULL, a_string(800) FROM z;     --  16
311dca321aeSdan        INSERT INTO z SELECT NULL, a_string(800) FROM z;     --  32
312dca321aeSdan        INSERT INTO z SELECT NULL, a_string(800) FROM z;     --  64
313dca321aeSdan        INSERT INTO z SELECT NULL, a_string(800) FROM z;     -- 128
314dca321aeSdan        INSERT INTO z SELECT NULL, a_string(800) FROM z;     -- 256
315dca321aeSdan      COMMIT;
316dca321aeSdan    }
317dca321aeSdan    execsql { PRAGMA auto_vacuum }
318dca321aeSdan  } {2}
319273f3f0dSdan  do_execsql_test pager1-3.$tn.2 {
320dca321aeSdan    BEGIN;
321dca321aeSdan      INSERT INTO z VALUES(NULL, a_string(800));
322dca321aeSdan      INSERT INTO z VALUES(NULL, a_string(800));
323dca321aeSdan      SAVEPOINT one;
324273f3f0dSdan        UPDATE z SET y = NULL WHERE x>256;
325dca321aeSdan        PRAGMA incremental_vacuum;
326dca321aeSdan        SELECT count(*) FROM z WHERE x < 100;
327dca321aeSdan      ROLLBACK TO one;
328dca321aeSdan    COMMIT;
329dca321aeSdan  } {99}
330dca321aeSdan
331273f3f0dSdan  do_execsql_test pager1-3.$tn.3 {
332273f3f0dSdan    BEGIN;
333273f3f0dSdan      SAVEPOINT one;
334273f3f0dSdan        UPDATE z SET y = y||x;
335273f3f0dSdan      ROLLBACK TO one;
336273f3f0dSdan    COMMIT;
337273f3f0dSdan    SELECT count(*) FROM z;
338273f3f0dSdan  } {258}
339273f3f0dSdan
340273f3f0dSdan  do_execsql_test pager1-3.$tn.4 {
341273f3f0dSdan    SAVEPOINT one;
342273f3f0dSdan      UPDATE z SET y = y||x;
343273f3f0dSdan    ROLLBACK TO one;
344273f3f0dSdan  } {}
345273f3f0dSdan  do_execsql_test pager1-3.$tn.5 {
346273f3f0dSdan    SELECT count(*) FROM z;
347273f3f0dSdan    RELEASE one;
348273f3f0dSdan    PRAGMA integrity_check;
349273f3f0dSdan  } {258 ok}
350273f3f0dSdan
351273f3f0dSdan  db close
352273f3f0dSdan  catch { tv delete }
353273f3f0dSdan}
354273f3f0dSdan
35553f04f3bSdan#-------------------------------------------------------------------------
35653f04f3bSdan# Hot journal rollback related test cases.
35753f04f3bSdan#
35853f04f3bSdan# pager1.4.1.*: Test that the pager module deletes very small invalid
35953f04f3bSdan#               journal files.
36053f04f3bSdan#
36153f04f3bSdan# pager1.4.2.*: Test that if the master journal pointer at the end of a
36253f04f3bSdan#               hot-journal file appears to be corrupt (checksum does not
36353f04f3bSdan#               compute) the associated journal is rolled back (and no
36453f04f3bSdan#               xAccess() call to check for the presence of any master
36553f04f3bSdan#               journal file is made).
36653f04f3bSdan#
367de4996e2Sdan# pager1.4.3.*: Test that the contents of a hot-journal are ignored if the
368de4996e2Sdan#               page-size or sector-size in the journal header appear to
369de4996e2Sdan#               be invalid (too large, too small or not a power of 2).
370de4996e2Sdan#
371e08341c6Sdan# pager1.4.4.*: Test hot-journal rollback of journal file with a master
372e08341c6Sdan#               journal pointer generated in various "PRAGMA synchronous"
373e08341c6Sdan#               modes.
374e08341c6Sdan#
375e08341c6Sdan# pager1.4.5.*: Test that hot-journal rollback stops if it encounters a
376e08341c6Sdan#               journal-record for which the checksum fails.
377e08341c6Sdan#
378ec6ffc1aSdan# pager1.4.6.*: Test that when rolling back a hot-journal that contains a
379ec6ffc1aSdan#               master journal pointer, the master journal file is deleted
380ec6ffc1aSdan#               after all the hot-journals that refer to it are deleted.
381ec6ffc1aSdan#
382c8ce3972Sdan# pager1.4.7.*: Test that if a hot-journal file exists but a client can
383c8ce3972Sdan#               open it for reading only, the database cannot be accessed and
384c8ce3972Sdan#               SQLITE_CANTOPEN is returned.
385c8ce3972Sdan#
38653f04f3bSdando_test pager1.4.1.1 {
38753f04f3bSdan  faultsim_delete_and_reopen
38853f04f3bSdan  execsql {
38953f04f3bSdan    CREATE TABLE x(y, z);
39053f04f3bSdan    INSERT INTO x VALUES(1, 2);
39153f04f3bSdan  }
39253f04f3bSdan  set fd [open test.db-journal w]
39353f04f3bSdan  puts -nonewline $fd "helloworld"
39453f04f3bSdan  close $fd
39553f04f3bSdan  file exists test.db-journal
39653f04f3bSdan} {1}
39753f04f3bSdando_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2}
39853f04f3bSdando_test pager1.4.1.3 { file exists test.db-journal } {0}
39953f04f3bSdan
40053f04f3bSdan# Set up a [testvfs] to snapshot the file-system just before SQLite
40153f04f3bSdan# deletes the master-journal to commit a multi-file transaction.
40253f04f3bSdan#
40353f04f3bSdan# In subsequent test cases, invoking [faultsim_restore_and_reopen] sets
40453f04f3bSdan# up the file system to contain two databases, two hot-journal files and
40553f04f3bSdan# a master-journal.
40653f04f3bSdan#
40753f04f3bSdando_test pager1.4.2.1 {
40853f04f3bSdan  testvfs tstvfs -default 1
40953f04f3bSdan  tstvfs filter xDelete
41053f04f3bSdan  tstvfs script xDeleteCallback
41153f04f3bSdan  proc xDeleteCallback {method file args} {
41253f04f3bSdan    set file [file tail $file]
41353f04f3bSdan    if { [string match *mj* $file] } { faultsim_save }
41453f04f3bSdan  }
41553f04f3bSdan  faultsim_delete_and_reopen
41653f04f3bSdan  db func a_string a_string
41753f04f3bSdan  execsql {
41853f04f3bSdan    ATTACH 'test.db2' AS aux;
41953f04f3bSdan    PRAGMA journal_mode = DELETE;
42053f04f3bSdan    PRAGMA main.cache_size = 10;
42153f04f3bSdan    PRAGMA aux.cache_size = 10;
42253f04f3bSdan    CREATE TABLE t1(a UNIQUE, b UNIQUE);
42353f04f3bSdan    CREATE TABLE aux.t2(a UNIQUE, b UNIQUE);
42453f04f3bSdan    INSERT INTO t1 VALUES(a_string(200), a_string(300));
42553f04f3bSdan    INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
42653f04f3bSdan    INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
42753f04f3bSdan    INSERT INTO t2 SELECT * FROM t1;
42853f04f3bSdan    BEGIN;
42953f04f3bSdan      INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
43053f04f3bSdan      INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
43153f04f3bSdan      INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
43253f04f3bSdan      INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
43353f04f3bSdan      REPLACE INTO t2 SELECT * FROM t1;
43453f04f3bSdan    COMMIT;
43553f04f3bSdan  }
43653f04f3bSdan  db close
43753f04f3bSdan  tstvfs delete
43853f04f3bSdan} {}
43953f04f3bSdando_test pager1.4.2.2 {
44053f04f3bSdan  faultsim_restore_and_reopen
44153f04f3bSdan  execsql {
44253f04f3bSdan    SELECT count(*) FROM t1;
44353f04f3bSdan    PRAGMA integrity_check;
44453f04f3bSdan  }
44553f04f3bSdan} {4 ok}
44653f04f3bSdando_test pager1.4.2.3 {
44753f04f3bSdan  faultsim_restore_and_reopen
44853f04f3bSdan  foreach f [glob test.db-mj*] { file delete -force $f }
44953f04f3bSdan  execsql {
45053f04f3bSdan    SELECT count(*) FROM t1;
45153f04f3bSdan    PRAGMA integrity_check;
45253f04f3bSdan  }
45353f04f3bSdan} {64 ok}
45453f04f3bSdando_test pager1.4.2.4 {
45553f04f3bSdan  faultsim_restore_and_reopen
45653f04f3bSdan  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
45753f04f3bSdan  execsql {
45853f04f3bSdan    SELECT count(*) FROM t1;
45953f04f3bSdan    PRAGMA integrity_check;
46053f04f3bSdan  }
46153f04f3bSdan} {4 ok}
46253f04f3bSdando_test pager1.4.2.5 {
46353f04f3bSdan  faultsim_restore_and_reopen
46453f04f3bSdan  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
46553f04f3bSdan  foreach f [glob test.db-mj*] { file delete -force $f }
46653f04f3bSdan  execsql {
46753f04f3bSdan    SELECT count(*) FROM t1;
46853f04f3bSdan    PRAGMA integrity_check;
46953f04f3bSdan  }
47053f04f3bSdan} {4 ok}
47153f04f3bSdan
472de4996e2Sdando_test pager1.4.3.1 {
473de4996e2Sdan  testvfs tstvfs -default 1
474de4996e2Sdan  tstvfs filter xSync
475de4996e2Sdan  tstvfs script xSyncCallback
476de4996e2Sdan  proc xSyncCallback {method file args} {
477de4996e2Sdan    set file [file tail $file]
478de4996e2Sdan    if { 0==[string match *journal $file] } { faultsim_save }
479de4996e2Sdan  }
480de4996e2Sdan  faultsim_delete_and_reopen
481de4996e2Sdan  execsql {
482de4996e2Sdan    PRAGMA journal_mode = DELETE;
483de4996e2Sdan    CREATE TABLE t1(a, b);
484de4996e2Sdan    INSERT INTO t1 VALUES(1, 2);
485de4996e2Sdan    INSERT INTO t1 VALUES(3, 4);
486de4996e2Sdan  }
487de4996e2Sdan  db close
488de4996e2Sdan  tstvfs delete
489de4996e2Sdan} {}
490de4996e2Sdan
491de4996e2Sdanforeach {tn ofst value result} {
492de4996e2Sdan          2   20    31       {1 2 3 4}
493de4996e2Sdan          3   20    32       {1 2 3 4}
494de4996e2Sdan          4   20    33       {1 2 3 4}
495de4996e2Sdan          5   20    65536    {1 2 3 4}
496de4996e2Sdan          6   20    131072   {1 2 3 4}
497de4996e2Sdan
498de4996e2Sdan          7   24    511      {1 2 3 4}
499de4996e2Sdan          8   24    513      {1 2 3 4}
500de4996e2Sdan          9   24    65536    {1 2 3 4}
501de4996e2Sdan
502de4996e2Sdan         10   32    65536    {1 2}
503de4996e2Sdan} {
504de4996e2Sdan  do_test pager1.4.3.$tn {
505de4996e2Sdan    faultsim_restore_and_reopen
506de4996e2Sdan    hexio_write test.db-journal $ofst [format %.8x $value]
507de4996e2Sdan    execsql { SELECT * FROM t1 }
508de4996e2Sdan  } $result
509de4996e2Sdan}
510de4996e2Sdandb close
511de4996e2Sdan
512e08341c6Sdan# Set up a VFS that snapshots the file-system just before a master journal
513e08341c6Sdan# file is deleted to commit a multi-file transaction. Specifically, the
514e08341c6Sdan# file-system is saved just before the xDelete() call to remove the
515e08341c6Sdan# master journal file from the file-system.
516e08341c6Sdan#
517e08341c6Sdantestvfs tv -default 1
518e08341c6Sdantv script copy_on_mj_delete
519e08341c6Sdanset ::mj_filename_length 0
520e08341c6Sdanproc copy_on_mj_delete {method filename args} {
521e08341c6Sdan  if {[string match *mj* [file tail $filename]]} {
522e08341c6Sdan    set ::mj_filename_length [string length $filename]
523e08341c6Sdan    faultsim_save
524e08341c6Sdan  }
525e08341c6Sdan  return SQLITE_OK
526e08341c6Sdan}
527e08341c6Sdan
528e08341c6Sdanset pwd [pwd]
529e08341c6Sdanforeach {tn1 tcl} {
530e08341c6Sdan  1 { set prefix "test.db" }
531e08341c6Sdan  2 {
532e08341c6Sdan    # This test depends on the underlying VFS being able to open paths
533e08341c6Sdan    # 512 bytes in length. The idea is to create a hot-journal file that
534e08341c6Sdan    # contains a master-journal pointer so large that it could contain
535e08341c6Sdan    # a valid page record (if the file page-size is 512 bytes). So as to
536e08341c6Sdan    # make sure SQLite doesn't get confused by this.
537e08341c6Sdan    #
538e08341c6Sdan    set nPadding [expr 511 - $::mj_filename_length]
539e08341c6Sdan
540e08341c6Sdan    # We cannot just create a really long database file name to open, as
541e08341c6Sdan    # Linux limits a single component of a path to 255 bytes by default
542e08341c6Sdan    # (and presumably other systems have limits too). So create a directory
543e08341c6Sdan    # hierarchy to work in.
544e08341c6Sdan    #
545e08341c6Sdan    set dirname "d123456789012345678901234567890/"
546e08341c6Sdan    set nDir [expr $nPadding / 32]
547e08341c6Sdan    if { $nDir } {
548e08341c6Sdan      set p [string repeat $dirname $nDir]
549e08341c6Sdan      file mkdir $p
550e08341c6Sdan      cd $p
551e08341c6Sdan    }
552e08341c6Sdan
553e08341c6Sdan    set padding [string repeat x [expr $nPadding %32]]
554e08341c6Sdan    set prefix "test.db${padding}"
555e08341c6Sdan  }
556e08341c6Sdan} {
557e08341c6Sdan  eval $tcl
558e08341c6Sdan  foreach {tn2 sql} {
559e08341c6Sdan    o {
560e08341c6Sdan      PRAGMA main.synchronous=OFF;
561e08341c6Sdan      PRAGMA aux.synchronous=OFF;
562e08341c6Sdan    }
563e08341c6Sdan    o512 {
564e08341c6Sdan      PRAGMA main.synchronous=OFF;
565e08341c6Sdan      PRAGMA aux.synchronous=OFF;
566e08341c6Sdan      PRAGMA main.page_size = 512;
567e08341c6Sdan      PRAGMA aux.page_size = 512;
568e08341c6Sdan    }
569e08341c6Sdan    n {
570e08341c6Sdan      PRAGMA main.synchronous=NORMAL;
571e08341c6Sdan      PRAGMA aux.synchronous=NORMAL;
572e08341c6Sdan    }
573e08341c6Sdan    f {
574e08341c6Sdan      PRAGMA main.synchronous=FULL;
575e08341c6Sdan      PRAGMA aux.synchronous=FULL;
576e08341c6Sdan    }
577e08341c6Sdan  } {
578e08341c6Sdan
579e08341c6Sdan    set tn "${tn1}.${tn2}"
580e08341c6Sdan
581e08341c6Sdan    # Set up a connection to have two databases, test.db (main) and
582e08341c6Sdan    # test.db2 (aux). Then run a multi-file transaction on them. The
583e08341c6Sdan    # VFS will snapshot the file-system just before the master-journal
584e08341c6Sdan    # file is deleted to commit the transaction.
585e08341c6Sdan    #
586e08341c6Sdan    tv filter xDelete
587e08341c6Sdan    do_test pager1-4.4.$tn.1 {
588e08341c6Sdan      faultsim_delete_and_reopen $prefix
589e08341c6Sdan      execsql "
590e08341c6Sdan        ATTACH '${prefix}2' AS aux;
591e08341c6Sdan        $sql
592e08341c6Sdan        CREATE TABLE a(x);
593e08341c6Sdan        CREATE TABLE aux.b(x);
594e08341c6Sdan        INSERT INTO a VALUES('double-you');
595e08341c6Sdan        INSERT INTO a VALUES('why');
596e08341c6Sdan        INSERT INTO a VALUES('zed');
597e08341c6Sdan        INSERT INTO b VALUES('won');
598e08341c6Sdan        INSERT INTO b VALUES('too');
599e08341c6Sdan        INSERT INTO b VALUES('free');
600e08341c6Sdan      "
601e08341c6Sdan      execsql {
602e08341c6Sdan        BEGIN;
603e08341c6Sdan          INSERT INTO a SELECT * FROM b WHERE rowid<=3;
604e08341c6Sdan          INSERT INTO b SELECT * FROM a WHERE rowid<=3;
605e08341c6Sdan        COMMIT;
606e08341c6Sdan      }
607e08341c6Sdan    } {}
608e08341c6Sdan    tv filter {}
609e08341c6Sdan
610e08341c6Sdan    # Check that the transaction was committed successfully.
611e08341c6Sdan    #
612e08341c6Sdan    do_execsql_test pager1-4.4.$tn.2 {
613e08341c6Sdan      SELECT * FROM a
614e08341c6Sdan    } {double-you why zed won too free}
615e08341c6Sdan    do_execsql_test pager1-4.4.$tn.3 {
616e08341c6Sdan      SELECT * FROM b
617e08341c6Sdan    } {won too free double-you why zed}
618e08341c6Sdan
619e08341c6Sdan    # Restore the file-system and reopen the databases. Check that it now
620e08341c6Sdan    # appears that the transaction was not committed (because the file-system
621e08341c6Sdan    # was restored to the state where it had not been).
622e08341c6Sdan    #
623e08341c6Sdan    do_test pager1-4.4.$tn.4 {
624e08341c6Sdan      faultsim_restore_and_reopen $prefix
625e08341c6Sdan      execsql "ATTACH '${prefix}2' AS aux"
626e08341c6Sdan    } {}
627e08341c6Sdan    do_execsql_test pager1-4.4.$tn.5 {SELECT * FROM a} {double-you why zed}
628e08341c6Sdan    do_execsql_test pager1-4.4.$tn.6 {SELECT * FROM b} {won too free}
629e08341c6Sdan
630e08341c6Sdan    # Restore the file-system again. This time, before reopening the databases,
631e08341c6Sdan    # delete the master-journal file from the file-system. It now appears that
632e08341c6Sdan    # the transaction was committed (no master-journal file == no rollback).
633e08341c6Sdan    #
634e08341c6Sdan    do_test pager1-4.4.$tn.7 {
635e08341c6Sdan      faultsim_restore_and_reopen $prefix
636e08341c6Sdan      foreach f [glob ${prefix}-mj*] { file delete -force $f }
637e08341c6Sdan      execsql "ATTACH '${prefix}2' AS aux"
638e08341c6Sdan    } {}
639e08341c6Sdan    do_execsql_test pager1-4.4.$tn.8 {
640e08341c6Sdan      SELECT * FROM a
641e08341c6Sdan    } {double-you why zed won too free}
642e08341c6Sdan    do_execsql_test pager1-4.4.$tn.9 {
643e08341c6Sdan      SELECT * FROM b
644e08341c6Sdan    } {won too free double-you why zed}
645e08341c6Sdan  }
646e08341c6Sdan
647e08341c6Sdan  cd $pwd
648e08341c6Sdan}
649e08341c6Sdandb close
650e08341c6Sdantv delete
6510e986f51Sdanfile delete -force $dirname
6520e986f51Sdan
6530e986f51Sdan
6540e986f51Sdan# Set up a VFS to make a copy of the file-system just before deleting a
6550e986f51Sdan# journal file to commit a transaction. The transaction modifies exactly
6560e986f51Sdan# two database pages (and page 1 - the change counter).
6570e986f51Sdan#
6580e986f51Sdantestvfs tv -default 1
6590e986f51Sdantv sectorsize 512
6600e986f51Sdantv script copy_on_journal_delete
6610e986f51Sdantv filter xDelete
6620e986f51Sdanproc copy_on_journal_delete {method filename args} {
6630e986f51Sdan  if {[string match *journal $filename]} faultsim_save
6640e986f51Sdan  return SQLITE_OK
6650e986f51Sdan}
6660e986f51Sdanfaultsim_delete_and_reopen
6670e986f51Sdando_execsql_test pager1.4.5.1 {
6680e986f51Sdan  PRAGMA page_size = 1024;
6690e986f51Sdan  CREATE TABLE t1(a, b);
6700e986f51Sdan  CREATE TABLE t2(a, b);
6710e986f51Sdan  INSERT INTO t1 VALUES('I', 'II');
6720e986f51Sdan  INSERT INTO t2 VALUES('III', 'IV');
6730e986f51Sdan  BEGIN;
6740e986f51Sdan    INSERT INTO t1 VALUES(1, 2);
6750e986f51Sdan    INSERT INTO t2 VALUES(3, 4);
6760e986f51Sdan  COMMIT;
6770e986f51Sdan} {}
6780e986f51Sdantv filter {}
6790e986f51Sdan
6800e986f51Sdan# Check the transaction was committed:
6810e986f51Sdan#
6820e986f51Sdando_execsql_test pager1.4.5.2 {
6830e986f51Sdan  SELECT * FROM t1;
6840e986f51Sdan  SELECT * FROM t2;
6850e986f51Sdan} {I II 1 2 III IV 3 4}
6860e986f51Sdan
687ec6ffc1aSdan# Now try four tests:
6880e986f51Sdan#
6890e986f51Sdan#  pager1-4.5.3: Restore the file-system. Check that the whole transaction
6900e986f51Sdan#                is rolled back.
6910e986f51Sdan#
6920e986f51Sdan#  pager1-4.5.4: Restore the file-system. Corrupt the first record in the
6930e986f51Sdan#                journal. Check the transaction is not rolled back.
6940e986f51Sdan#
6950e986f51Sdan#  pager1-4.5.5: Restore the file-system. Corrupt the second record in the
6960e986f51Sdan#                journal. Check that the first record in the transaction is
6970e986f51Sdan#                played back, but not the second.
6980e986f51Sdan#
69910f5a50eSdan#  pager1-4.5.6: Restore the file-system. Try to open the database with a
70010f5a50eSdan#                readonly connection. This should fail, as a read-only
70110f5a50eSdan#                connection cannot roll back the database file.
70210f5a50eSdan#
7030e986f51Sdanfaultsim_restore_and_reopen
7040e986f51Sdando_execsql_test pager1.4.5.3 {
7050e986f51Sdan  SELECT * FROM t1;
7060e986f51Sdan  SELECT * FROM t2;
7070e986f51Sdan} {I II III IV}
7080e986f51Sdanfaultsim_restore_and_reopen
7090e986f51Sdanhexio_write test.db-journal [expr 512+4+1024 - 202] 0123456789ABCDEF
7100e986f51Sdando_execsql_test pager1.4.5.4 {
7110e986f51Sdan  SELECT * FROM t1;
7120e986f51Sdan  SELECT * FROM t2;
7130e986f51Sdan} {I II 1 2 III IV 3 4}
7140e986f51Sdanfaultsim_restore_and_reopen
7150e986f51Sdanhexio_write test.db-journal [expr 512+4+1024+4+4+1024 - 202] 0123456789ABCDEF
7160e986f51Sdando_execsql_test pager1.4.5.5 {
7170e986f51Sdan  SELECT * FROM t1;
7180e986f51Sdan  SELECT * FROM t2;
7190e986f51Sdan} {I II III IV 3 4}
7200e986f51Sdan
72110f5a50eSdanfaultsim_restore_and_reopen
72210f5a50eSdandb close
72310f5a50eSdansqlite3 db test.db -readonly 1
72410f5a50eSdando_catchsql_test pager1.4.5.6 {
72510f5a50eSdan  SELECT * FROM t1;
72610f5a50eSdan  SELECT * FROM t2;
72710f5a50eSdan} {1 {disk I/O error}}
728ec6ffc1aSdandb close
729ec6ffc1aSdan
730ec6ffc1aSdan# Snapshot the file-system just before multi-file commit. Save the name
731ec6ffc1aSdan# of the master journal file in $::mj_filename.
732ec6ffc1aSdan#
733ec6ffc1aSdantv script copy_on_mj_delete
734ec6ffc1aSdantv filter xDelete
735ec6ffc1aSdanproc copy_on_mj_delete {method filename args} {
736ec6ffc1aSdan  if {[string match *mj* [file tail $filename]]} {
737ec6ffc1aSdan    set ::mj_filename $filename
738ec6ffc1aSdan    faultsim_save
739ec6ffc1aSdan  }
740ec6ffc1aSdan  return SQLITE_OK
741ec6ffc1aSdan}
742ec6ffc1aSdando_test pager1.4.6.1 {
743ec6ffc1aSdan  faultsim_delete_and_reopen
744ec6ffc1aSdan  execsql {
745ec6ffc1aSdan    ATTACH 'test.db2' AS two;
746ec6ffc1aSdan    CREATE TABLE t1(a, b);
747ec6ffc1aSdan    CREATE TABLE two.t2(a, b);
748ec6ffc1aSdan    INSERT INTO t1 VALUES(1, 't1.1');
749ec6ffc1aSdan    INSERT INTO t2 VALUES(1, 't2.1');
750ec6ffc1aSdan    BEGIN;
751ec6ffc1aSdan      UPDATE t1 SET b = 't1.2';
752ec6ffc1aSdan      UPDATE t2 SET b = 't2.2';
753ec6ffc1aSdan    COMMIT;
754ec6ffc1aSdan  }
755ec6ffc1aSdan  tv filter {}
756ec6ffc1aSdan  db close
757ec6ffc1aSdan} {}
758ec6ffc1aSdan
759ec6ffc1aSdanfaultsim_restore_and_reopen
760ec6ffc1aSdando_execsql_test pager1.4.6.2 { SELECT * FROM t1 }           {1 t1.1}
761ec6ffc1aSdando_test         pager1.4.6.3 { file exists $::mj_filename } {1}
762ec6ffc1aSdando_execsql_test pager1.4.6.4 {
763ec6ffc1aSdan  ATTACH 'test.db2' AS two;
764ec6ffc1aSdan  SELECT * FROM t2;
765ec6ffc1aSdan} {1 t2.1}
766ec6ffc1aSdando_test pager1.4.6.5 { file exists $::mj_filename } {0}
767ec6ffc1aSdan
768ec6ffc1aSdanfaultsim_restore_and_reopen
769ec6ffc1aSdandb close
770ec6ffc1aSdando_test pager1.4.6.8 {
771ec6ffc1aSdan  set ::mj_filename1 $::mj_filename
772ec6ffc1aSdan  tv filter xDelete
773ec6ffc1aSdan  sqlite3 db test.db2
774ec6ffc1aSdan  execsql {
775ec6ffc1aSdan    ATTACH 'test.db3' AS three;
776ec6ffc1aSdan    CREATE TABLE three.t3(a, b);
777ec6ffc1aSdan    INSERT INTO t3 VALUES(1, 't3.1');
778ec6ffc1aSdan    BEGIN;
779ec6ffc1aSdan      UPDATE t2 SET b = 't2.3';
780ec6ffc1aSdan      UPDATE t3 SET b = 't3.3';
781ec6ffc1aSdan    COMMIT;
782ec6ffc1aSdan  }
783ec6ffc1aSdan  expr {$::mj_filename1 != $::mj_filename}
784ec6ffc1aSdan} {1}
785ec6ffc1aSdanfaultsim_restore_and_reopen
786ec6ffc1aSdantv filter {}
787ec6ffc1aSdan
788ec6ffc1aSdan# The file-system now contains:
789ec6ffc1aSdan#
790ec6ffc1aSdan#   * three databases
791ec6ffc1aSdan#   * three hot-journal files
792ec6ffc1aSdan#   * two master-journal files.
793ec6ffc1aSdan#
794ec6ffc1aSdan# The hot-journals associated with test.db2 and test.db3 point to
795ec6ffc1aSdan# master journal $::mj_filename. The hot-journal file associated with
796ec6ffc1aSdan# test.db points to master journal $::mj_filename1. So reading from
797ec6ffc1aSdan# test.db should delete $::mj_filename1.
798ec6ffc1aSdan#
799ec6ffc1aSdando_test pager1.4.6.9 {
800ec6ffc1aSdan  lsort [glob test.db*]
801ec6ffc1aSdan} [lsort [list                                           \
802ec6ffc1aSdan  test.db test.db2 test.db3                              \
803ec6ffc1aSdan  test.db-journal test.db2-journal test.db3-journal      \
804ec6ffc1aSdan  [file tail $::mj_filename] [file tail $::mj_filename1]
805ec6ffc1aSdan]]
806ec6ffc1aSdan
807ec6ffc1aSdan# The master-journal $::mj_filename1 contains pointers to test.db and
808ec6ffc1aSdan# test.db2. However the hot-journal associated with test.db2 points to
809ec6ffc1aSdan# a different master-journal. Therefore, reading from test.db only should
810ec6ffc1aSdan# be enough to cause SQLite to delete $::mj_filename1.
811ec6ffc1aSdan#
812ec6ffc1aSdando_test         pager1.4.6.10 { file exists $::mj_filename  } {1}
813ec6ffc1aSdando_test         pager1.4.6.11 { file exists $::mj_filename1 } {1}
814ec6ffc1aSdando_execsql_test pager1.4.6.12 { SELECT * FROM t1 } {1 t1.1}
815ec6ffc1aSdando_test         pager1.4.6.13 { file exists $::mj_filename  } {1}
816ec6ffc1aSdando_test         pager1.4.6.14 { file exists $::mj_filename1 } {0}
817ec6ffc1aSdan
818ec6ffc1aSdando_execsql_test pager1.4.6.12 {
819ec6ffc1aSdan  ATTACH 'test.db2' AS two;
820ec6ffc1aSdan  SELECT * FROM t2;
821ec6ffc1aSdan} {1 t2.1}
822ec6ffc1aSdando_test         pager1.4.6.13 { file exists $::mj_filename }  {1}
823ec6ffc1aSdando_execsql_test pager1.4.6.14 {
824ec6ffc1aSdan  ATTACH 'test.db3' AS three;
825ec6ffc1aSdan  SELECT * FROM t3;
826ec6ffc1aSdan} {1 t3.1}
827ec6ffc1aSdando_test         pager1.4.6.15 { file exists $::mj_filename }  {0}
82810f5a50eSdan
8290e986f51Sdandb close
8300e986f51Sdantv delete
831e08341c6Sdan
832c8ce3972Sdantestvfs tv -default 1
833c8ce3972Sdantv sectorsize 512
834c8ce3972Sdantv script copy_on_journal_delete
835c8ce3972Sdantv filter xDelete
836c8ce3972Sdanproc copy_on_journal_delete {method filename args} {
837c8ce3972Sdan  if {[string match *journal $filename]} faultsim_save
838c8ce3972Sdan  return SQLITE_OK
839c8ce3972Sdan}
840c8ce3972Sdanfaultsim_delete_and_reopen
841c8ce3972Sdando_execsql_test pager1.4.7.1 {
842c8ce3972Sdan  CREATE TABLE t1(x PRIMARY KEY, y);
843c8ce3972Sdan  CREATE INDEX i1 ON t1(y);
844c8ce3972Sdan  INSERT INTO t1 VALUES('I',   'one');
845c8ce3972Sdan  INSERT INTO t1 VALUES('II',  'four');
846c8ce3972Sdan  INSERT INTO t1 VALUES('III', 'nine');
847c8ce3972Sdan  BEGIN;
848c8ce3972Sdan    INSERT INTO t1 VALUES('IV', 'sixteen');
849c8ce3972Sdan    INSERT INTO t1 VALUES('V' , 'twentyfive');
850c8ce3972Sdan  COMMIT;
851c8ce3972Sdan} {}
852c8ce3972Sdantv filter {}
853c8ce3972Sdandb close
854c8ce3972Sdantv delete
855c8ce3972Sdando_test pager1.4.7.2 {
856c8ce3972Sdan  faultsim_restore_and_reopen
857c8ce3972Sdan  catch {file attributes test.db-journal -permissions r--------}
858c8ce3972Sdan  catch {file attributes test.db-journal -readonly 1}
859c8ce3972Sdan  catchsql { SELECT * FROM t1 }
860c8ce3972Sdan} {1 {unable to open database file}}
861c8ce3972Sdando_test pager1.4.7.3 {
862c8ce3972Sdan  db close
863c8ce3972Sdan  catch {file attributes test.db-journal -permissions rw-rw-rw-}
864c8ce3972Sdan  catch {file attributes test.db-journal -readonly 0}
865c8ce3972Sdan  file delete test.db-journal
866c8ce3972Sdan  file exists test.db-journal
867c8ce3972Sdan} {0}
868c8ce3972Sdan
869de4996e2Sdan#-------------------------------------------------------------------------
870146ed78bSdan# The following tests deal with multi-file commits.
871de4996e2Sdan#
872146ed78bSdan# pager1-5.1.*: The case where a multi-file cannot be committed because
873146ed78bSdan#               another connection is holding a SHARED lock on one of the
874146ed78bSdan#               files. After the SHARED lock is removed, the COMMIT succeeds.
875146ed78bSdan#
876146ed78bSdan# pager1-5.2.*: Multi-file commits with journal_mode=memory.
877146ed78bSdan#
878146ed78bSdan# pager1-5.3.*: Multi-file commits with journal_mode=memory.
879146ed78bSdan#
880146ed78bSdan# pager1-5.4.*: Check that with synchronous=normal, the master-journal file
881146ed78bSdan#               name is added to a journal file immediately after the last
882146ed78bSdan#               journal record. But with synchronous=full, extra unused space
883146ed78bSdan#               is allocated between the last journal record and the
884146ed78bSdan#               master-journal file name so that the master-journal file
885146ed78bSdan#               name does not lie on the same sector as the last journal file
886146ed78bSdan#               record.
887146ed78bSdan#
888e08341c6Sdan# pager1-5.5.*: Check that in journal_mode=PERSIST mode, a journal file is
889e08341c6Sdan#               truncated to zero bytes when a multi-file transaction is
890e08341c6Sdan#               committed (instead of the first couple of bytes being zeroed).
891e08341c6Sdan#
892146ed78bSdan#
893146ed78bSdando_test pager1-5.1.1 {
894146ed78bSdan  faultsim_delete_and_reopen
895146ed78bSdan  execsql {
896146ed78bSdan    ATTACH 'test.db2' AS aux;
897146ed78bSdan    CREATE TABLE t1(a, b);
898146ed78bSdan    CREATE TABLE aux.t2(a, b);
899146ed78bSdan    INSERT INTO t1 VALUES(17, 'Lenin');
900146ed78bSdan    INSERT INTO t1 VALUES(22, 'Stalin');
901146ed78bSdan    INSERT INTO t1 VALUES(53, 'Khrushchev');
902146ed78bSdan  }
903146ed78bSdan} {}
904146ed78bSdando_test pager1-5.1.2 {
905146ed78bSdan  execsql {
906146ed78bSdan    BEGIN;
907146ed78bSdan      INSERT INTO t1 VALUES(64, 'Brezhnev');
908146ed78bSdan      INSERT INTO t2 SELECT * FROM t1;
909146ed78bSdan  }
910146ed78bSdan  sqlite3 db2 test.db2
911146ed78bSdan  execsql {
912146ed78bSdan    BEGIN;
913146ed78bSdan      SELECT * FROM t2;
914146ed78bSdan  } db2
915146ed78bSdan} {}
916146ed78bSdando_test pager1-5.1.3 {
917146ed78bSdan  catchsql COMMIT
918146ed78bSdan} {1 {database is locked}}
919146ed78bSdando_test pager1-5.1.4 {
920146ed78bSdan  execsql COMMIT db2
921146ed78bSdan  execsql COMMIT
922146ed78bSdan  execsql { SELECT * FROM t2 } db2
923146ed78bSdan} {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev}
924146ed78bSdando_test pager1-5.1.5 {
925146ed78bSdan  db2 close
926146ed78bSdan} {}
927146ed78bSdan
928146ed78bSdando_test pager1-5.2.1 {
929146ed78bSdan  execsql {
930146ed78bSdan    PRAGMA journal_mode = memory;
931146ed78bSdan    BEGIN;
932146ed78bSdan      INSERT INTO t1 VALUES(84, 'Andropov');
933146ed78bSdan      INSERT INTO t2 VALUES(84, 'Andropov');
934146ed78bSdan    COMMIT;
935146ed78bSdan  }
936146ed78bSdan} {memory}
937146ed78bSdando_test pager1-5.3.1 {
938146ed78bSdan  execsql {
939146ed78bSdan    PRAGMA journal_mode = off;
940146ed78bSdan    BEGIN;
941146ed78bSdan      INSERT INTO t1 VALUES(85, 'Gorbachev');
942146ed78bSdan      INSERT INTO t2 VALUES(85, 'Gorbachev');
943146ed78bSdan    COMMIT;
944146ed78bSdan  }
945146ed78bSdan} {off}
946146ed78bSdan
947146ed78bSdando_test pager1-5.4.1 {
948146ed78bSdan  db close
949146ed78bSdan  testvfs tv
950146ed78bSdan  sqlite3 db test.db -vfs tv
951146ed78bSdan  execsql { ATTACH 'test.db2' AS aux }
952146ed78bSdan
953146ed78bSdan  tv filter xDelete
954146ed78bSdan  tv script max_journal_size
955146ed78bSdan  tv sectorsize 512
956146ed78bSdan  set ::max_journal 0
957146ed78bSdan  proc max_journal_size {method args} {
958146ed78bSdan    set sz 0
959146ed78bSdan    catch { set sz [file size test.db-journal] }
960146ed78bSdan    if {$sz > $::max_journal} {
961146ed78bSdan      set ::max_journal $sz
962146ed78bSdan    }
963146ed78bSdan    return SQLITE_OK
964146ed78bSdan  }
965146ed78bSdan  execsql {
966146ed78bSdan    PRAGMA journal_mode = DELETE;
967146ed78bSdan    PRAGMA synchronous = NORMAL;
968146ed78bSdan    BEGIN;
969146ed78bSdan      INSERT INTO t1 VALUES(85, 'Gorbachev');
970146ed78bSdan      INSERT INTO t2 VALUES(85, 'Gorbachev');
971146ed78bSdan    COMMIT;
972146ed78bSdan  }
973146ed78bSdan  set ::max_journal
974146ed78bSdan} [expr 2615+[string length [pwd]]]
975146ed78bSdando_test pager1-5.4.2 {
976146ed78bSdan  set ::max_journal 0
977146ed78bSdan  execsql {
978146ed78bSdan    PRAGMA synchronous = full;
979146ed78bSdan    BEGIN;
980146ed78bSdan      DELETE FROM t1 WHERE b = 'Lenin';
981146ed78bSdan      DELETE FROM t2 WHERE b = 'Lenin';
982146ed78bSdan    COMMIT;
983146ed78bSdan  }
984146ed78bSdan  set ::max_journal
985146ed78bSdan} [expr 3111+[string length [pwd]]]
986146ed78bSdandb close
987146ed78bSdantv delete
988146ed78bSdan
989146ed78bSdando_test pager1-5.5.1 {
990146ed78bSdan  sqlite3 db test.db
991146ed78bSdan  execsql {
992146ed78bSdan    ATTACH 'test.db2' AS aux;
993146ed78bSdan    PRAGMA journal_mode = PERSIST;
994146ed78bSdan    CREATE TABLE t3(a, b);
995146ed78bSdan    INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1;
996146ed78bSdan    UPDATE t3 SET b = randomblob(1500);
997146ed78bSdan  }
998146ed78bSdan  expr [file size test.db-journal] > 15000
999146ed78bSdan} {1}
1000146ed78bSdando_test pager1-5.5.2 {
1001146ed78bSdan  execsql {
1002146ed78bSdan    PRAGMA synchronous = full;
1003146ed78bSdan    BEGIN;
1004146ed78bSdan      DELETE FROM t1 WHERE b = 'Stalin';
1005146ed78bSdan      DELETE FROM t2 WHERE b = 'Stalin';
1006146ed78bSdan    COMMIT;
1007146ed78bSdan  }
1008146ed78bSdan  file size test.db-journal
1009146ed78bSdan} {0}
1010146ed78bSdan
1011146ed78bSdan
1012146ed78bSdan#-------------------------------------------------------------------------
1013146ed78bSdan# The following tests work with "PRAGMA max_page_count"
1014146ed78bSdan#
1015146ed78bSdando_test pager1-6.1 {
1016146ed78bSdan  faultsim_delete_and_reopen
1017146ed78bSdan  execsql {
1018146ed78bSdan    PRAGMA max_page_count = 10;
1019146ed78bSdan    CREATE TABLE t2(a, b);
1020146ed78bSdan    CREATE TABLE t3(a, b);
1021146ed78bSdan    CREATE TABLE t4(a, b);
1022146ed78bSdan    CREATE TABLE t5(a, b);
1023146ed78bSdan    CREATE TABLE t6(a, b);
1024146ed78bSdan    CREATE TABLE t7(a, b);
1025146ed78bSdan    CREATE TABLE t8(a, b);
1026146ed78bSdan    CREATE TABLE t9(a, b);
1027146ed78bSdan    CREATE TABLE t10(a, b);
1028146ed78bSdan  }
1029146ed78bSdan} {10}
1030d353331aSdando_catchsql_test pager1-6.2 {
1031d353331aSdan  CREATE TABLE t11(a, b)
1032146ed78bSdan} {1 {database or disk is full}}
1033d353331aSdando_execsql_test pager1-6.4 { PRAGMA max_page_count      } {10}
1034d353331aSdando_execsql_test pager1-6.5 { PRAGMA max_page_count = 15 } {15}
1035d353331aSdando_execsql_test pager1-6.6 { CREATE TABLE t11(a, b)     } {}
1036d353331aSdando_execsql_test pager1-6.7 {
1037d353331aSdan  BEGIN;
1038d353331aSdan    INSERT INTO t11 VALUES(1, 2);
1039d353331aSdan    PRAGMA max_page_count = 13;
1040d353331aSdan} {13}
1041d353331aSdando_execsql_test pager1-6.8 {
1042d353331aSdan    INSERT INTO t11 VALUES(3, 4);
1043d353331aSdan    PRAGMA max_page_count = 10;
1044d353331aSdan} {11}
1045d353331aSdando_execsql_test pager1-6.9 { COMMIT } {}
1046de4996e2Sdan
1047153eda0aSdan
1048153eda0aSdan#-------------------------------------------------------------------------
1049153eda0aSdan# The following tests work with "PRAGMA journal_mode=TRUNCATE" and
1050153eda0aSdan# "PRAGMA locking_mode=EXCLUSIVE".
1051153eda0aSdan#
1052153eda0aSdan# Each test is specified with 5 variables. As follows:
1053153eda0aSdan#
1054153eda0aSdan#   $tn:  Test Number. Used as part of the [do_test] test names.
1055153eda0aSdan#   $sql: SQL to execute.
1056153eda0aSdan#   $res: Expected result of executing $sql.
1057153eda0aSdan#   $js:  The expected size of the journal file, in bytes, after executing
1058153eda0aSdan#         the SQL script. Or -1 if the journal is not expected to exist.
1059153eda0aSdan#   $ws:  The expected size of the WAL file, in bytes, after executing
1060153eda0aSdan#         the SQL script. Or -1 if the WAL is not expected to exist.
1061153eda0aSdan#
106238e1a279Sdanifcapable wal {
1063153eda0aSdan  faultsim_delete_and_reopen
1064153eda0aSdan  foreach {tn sql res js ws} [subst {
1065153eda0aSdan
1066153eda0aSdan    1  {
1067153eda0aSdan      CREATE TABLE t1(a, b);
1068153eda0aSdan      PRAGMA auto_vacuum=OFF;
1069153eda0aSdan      PRAGMA synchronous=NORMAL;
1070153eda0aSdan      PRAGMA page_size=1024;
1071153eda0aSdan      PRAGMA locking_mode=EXCLUSIVE;
1072153eda0aSdan      PRAGMA journal_mode=TRUNCATE;
1073153eda0aSdan      INSERT INTO t1 VALUES(1, 2);
1074153eda0aSdan    } {exclusive truncate} 0 -1
1075153eda0aSdan
1076153eda0aSdan    2  {
1077153eda0aSdan      BEGIN IMMEDIATE;
1078153eda0aSdan        SELECT * FROM t1;
1079153eda0aSdan      COMMIT;
1080153eda0aSdan    } {1 2} 0 -1
1081153eda0aSdan
1082153eda0aSdan    3  {
1083153eda0aSdan      BEGIN;
1084153eda0aSdan        SELECT * FROM t1;
1085153eda0aSdan      COMMIT;
1086153eda0aSdan    } {1 2} 0 -1
1087153eda0aSdan
1088153eda0aSdan    4  { PRAGMA journal_mode = WAL }    wal    -1 -1
1089153eda0aSdan    5  { INSERT INTO t1 VALUES(3, 4) }  {}     -1 [wal_file_size 1 1024]
1090153eda0aSdan    6  { PRAGMA locking_mode = NORMAL } normal -1 [wal_file_size 1 1024]
1091153eda0aSdan    7  { INSERT INTO t1 VALUES(5, 6); } {}     -1 [wal_file_size 2 1024]
1092153eda0aSdan
1093153eda0aSdan    8  { PRAGMA journal_mode = TRUNCATE } truncate          0 -1
1094153eda0aSdan    9  { INSERT INTO t1 VALUES(7, 8) }    {}                0 -1
1095153eda0aSdan    10 { SELECT * FROM t1 }               {1 2 3 4 5 6 7 8} 0 -1
1096153eda0aSdan
1097153eda0aSdan  }] {
1098153eda0aSdan    do_execsql_test pager1-7.1.$tn.1 $sql $res
1099153eda0aSdan    catch { set J -1 ; set J [file size test.db-journal] }
1100153eda0aSdan    catch { set W -1 ; set W [file size test.db-wal] }
1101153eda0aSdan    do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws]
1102153eda0aSdan  }
110338e1a279Sdan}
1104153eda0aSdan
110589ccf448Sdando_test pager1-7.2.1 {
110689ccf448Sdan  faultsim_delete_and_reopen
110789ccf448Sdan  execsql {
110889ccf448Sdan    PRAGMA locking_mode = EXCLUSIVE;
110989ccf448Sdan    CREATE TABLE t1(a, b);
111089ccf448Sdan    BEGIN;
111189ccf448Sdan      PRAGMA journal_mode = delete;
111289ccf448Sdan      PRAGMA journal_mode = truncate;
111389ccf448Sdan  }
111489ccf448Sdan} {exclusive delete truncate}
111589ccf448Sdando_test pager1-7.2.2 {
111689ccf448Sdan  execsql { INSERT INTO t1 VALUES(1, 2) }
111789ccf448Sdan  execsql { PRAGMA journal_mode = persist }
111889ccf448Sdan} {truncate}
111989ccf448Sdando_test pager1-7.2.3 {
112089ccf448Sdan  execsql { COMMIT }
112189ccf448Sdan  execsql {
112289ccf448Sdan    PRAGMA journal_mode = persist;
112389ccf448Sdan    PRAGMA journal_size_limit;
112489ccf448Sdan  }
112589ccf448Sdan} {persist -1}
112689ccf448Sdan
1127d353331aSdan#-------------------------------------------------------------------------
1128d353331aSdan# The following tests, pager1-8.*, test that the special filenames
1129d353331aSdan# ":memory:" and "" open temporary databases.
1130d353331aSdan#
11310e986f51Sdanforeach {tn filename} {
11320e986f51Sdan  1 :memory:
11330e986f51Sdan  2 ""
11340e986f51Sdan} {
11350e986f51Sdan  do_test pager1-8.$tn.1 {
1136153eda0aSdan    faultsim_delete_and_reopen
1137153eda0aSdan    db close
11380e986f51Sdan    sqlite3 db $filename
1139153eda0aSdan    execsql {
1140c8ce3972Sdan      PRAGMA auto_vacuum = 1;
1141153eda0aSdan      CREATE TABLE x1(x);
1142153eda0aSdan      INSERT INTO x1 VALUES('Charles');
1143153eda0aSdan      INSERT INTO x1 VALUES('James');
1144153eda0aSdan      INSERT INTO x1 VALUES('Mary');
1145153eda0aSdan      SELECT * FROM x1;
1146153eda0aSdan    }
1147153eda0aSdan  } {Charles James Mary}
11480e986f51Sdan
11490e986f51Sdan  do_test pager1-8.$tn.2 {
11500e986f51Sdan    sqlite3 db2 $filename
11510e986f51Sdan    catchsql { SELECT * FROM x1 } db2
1152153eda0aSdan  } {1 {no such table: x1}}
1153153eda0aSdan
11540e986f51Sdan  do_execsql_test pager1-8.$tn.3 {
11550e986f51Sdan    BEGIN;
11560e986f51Sdan      INSERT INTO x1 VALUES('William');
11570e986f51Sdan      INSERT INTO x1 VALUES('Anne');
11580e986f51Sdan    ROLLBACK;
11590e986f51Sdan  } {}
11600e986f51Sdan}
11610e986f51Sdan
1162dca321aeSdan#-------------------------------------------------------------------------
1163dca321aeSdan# The next block of tests - pager1-9.* - deal with interactions between
1164dca321aeSdan# the pager and the backup API. Test cases:
1165dca321aeSdan#
1166dca321aeSdan#   pager1-9.1.*: Test that a backup completes successfully even if the
1167dca321aeSdan#                 source db is written to during the backup op.
1168dca321aeSdan#
1169dca321aeSdan#   pager1-9.2.*: Test that a backup completes successfully even if the
1170dca321aeSdan#                 source db is written to and then rolled back during a
1171dca321aeSdan#                 backup operation.
1172dca321aeSdan#
1173dca321aeSdando_test pager1-9.0.1 {
1174dca321aeSdan  faultsim_delete_and_reopen
1175dca321aeSdan  db func a_string a_string
1176dca321aeSdan  execsql {
1177dca321aeSdan    PRAGMA cache_size = 10;
1178dca321aeSdan    BEGIN;
1179dca321aeSdan      CREATE TABLE ab(a, b, UNIQUE(a, b));
1180dca321aeSdan      INSERT INTO ab VALUES( a_string(200), a_string(300) );
1181dca321aeSdan      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
1182dca321aeSdan      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
1183dca321aeSdan      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
1184dca321aeSdan      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
1185dca321aeSdan      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
1186dca321aeSdan      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
1187dca321aeSdan      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
1188dca321aeSdan    COMMIT;
1189dca321aeSdan  }
1190dca321aeSdan} {}
1191dca321aeSdando_test pager1-9.0.2 {
1192dca321aeSdan  sqlite3 db2 test.db2
1193dca321aeSdan  db2 eval { PRAGMA cache_size = 10 }
1194dca321aeSdan  sqlite3_backup B db2 main db main
1195dca321aeSdan  list [B step 10000] [B finish]
1196dca321aeSdan} {SQLITE_DONE SQLITE_OK}
1197dca321aeSdando_test pager1-9.0.3 {
1198dca321aeSdan db one {SELECT md5sum(a, b) FROM ab}
1199dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}]
1200dca321aeSdan
1201dca321aeSdando_test pager1-9.1.1 {
1202dca321aeSdan  execsql { UPDATE ab SET a = a_string(201) }
1203dca321aeSdan  sqlite3_backup B db2 main db main
1204dca321aeSdan  B step 30
1205dca321aeSdan} {SQLITE_OK}
1206dca321aeSdando_test pager1-9.1.2 {
1207dca321aeSdan  execsql { UPDATE ab SET b = a_string(301) }
1208dca321aeSdan  list [B step 10000] [B finish]
1209dca321aeSdan} {SQLITE_DONE SQLITE_OK}
1210dca321aeSdando_test pager1-9.1.3 {
1211dca321aeSdan db one {SELECT md5sum(a, b) FROM ab}
1212dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}]
1213dca321aeSdando_test pager1-9.1.4 { execsql { SELECT count(*) FROM ab } } {128}
1214dca321aeSdan
1215dca321aeSdando_test pager1-9.2.1 {
1216dca321aeSdan  execsql { UPDATE ab SET a = a_string(202) }
1217dca321aeSdan  sqlite3_backup B db2 main db main
1218dca321aeSdan  B step 30
1219dca321aeSdan} {SQLITE_OK}
1220dca321aeSdando_test pager1-9.2.2 {
1221dca321aeSdan  execsql {
1222dca321aeSdan    BEGIN;
1223dca321aeSdan      UPDATE ab SET b = a_string(301);
1224dca321aeSdan    ROLLBACK;
1225dca321aeSdan  }
1226dca321aeSdan  list [B step 10000] [B finish]
1227dca321aeSdan} {SQLITE_DONE SQLITE_OK}
1228dca321aeSdando_test pager1-9.2.3 {
1229dca321aeSdan db one {SELECT md5sum(a, b) FROM ab}
1230dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}]
1231dca321aeSdando_test pager1-9.2.4 { execsql { SELECT count(*) FROM ab } } {128}
1232ec6ffc1aSdandb close
1233ec6ffc1aSdandb2 close
1234ec6ffc1aSdan
1235*c396d4afSdando_test pager1-9.3.1 {
1236*c396d4afSdan  testvfs tv -default 1
1237*c396d4afSdan  tv sectorsize 4096
1238*c396d4afSdan  faultsim_delete_and_reopen
1239*c396d4afSdan
1240*c396d4afSdan  execsql { PRAGMA page_size = 1024 }
1241*c396d4afSdan  for {set ii 0} {$ii < 4} {incr ii} { execsql "CREATE TABLE t${ii}(a, b)" }
1242*c396d4afSdan} {}
1243*c396d4afSdando_test pager1-9.3.2 {
1244*c396d4afSdan  sqlite3 db2 test.db2
1245*c396d4afSdan  execsql {
1246*c396d4afSdan    PRAGMA page_size = 4096;
1247*c396d4afSdan    PRAGMA synchronous = OFF;
1248*c396d4afSdan    CREATE TABLE t1(a, b);
1249*c396d4afSdan    CREATE TABLE t2(a, b);
1250*c396d4afSdan  } db2
1251*c396d4afSdan
1252*c396d4afSdan  sqlite3_backup B db2 main db main
1253*c396d4afSdan  B step 30
1254*c396d4afSdan  list [B step 10000] [B finish]
1255*c396d4afSdan} {SQLITE_DONE SQLITE_OK}
1256*c396d4afSdando_test pager1-9.3.3 {
1257*c396d4afSdan  db2 close
1258*c396d4afSdan  db close
1259*c396d4afSdan  tv delete
1260*c396d4afSdan  file size test.db2
1261*c396d4afSdan} [file size test.db]
1262*c396d4afSdan
1263*c396d4afSdan
1264d0b0d4dcSdan
1265ec6ffc1aSdan#-------------------------------------------------------------------------
1266ec6ffc1aSdan# Test that regardless of the value returned by xSectorSize(), the
1267ec6ffc1aSdan# minimum effective sector-size is 512 and the maximum 65536 bytes.
1268ec6ffc1aSdan#
1269ec6ffc1aSdantestvfs tv -default 1
1270ec6ffc1aSdanforeach sectorsize {
1271ec6ffc1aSdan    32   64   128   256   512   1024   2048
1272ec6ffc1aSdan    4096 8192 16384 32768 65536 131072 262144
1273ec6ffc1aSdan} {
1274ec6ffc1aSdan  tv sectorsize $sectorsize
1275ec6ffc1aSdan  set eff $sectorsize
1276ec6ffc1aSdan  if {$sectorsize < 512}   { set eff 512 }
1277ec6ffc1aSdan  if {$sectorsize > 65536} { set eff 65536 }
1278ec6ffc1aSdan
1279d0b0d4dcSdan  do_test pager1-10.$sectorsize.1 {
1280ec6ffc1aSdan    faultsim_delete_and_reopen
1281d0b0d4dcSdan    db func a_string a_string
1282ec6ffc1aSdan    execsql {
1283ec6ffc1aSdan      PRAGMA journal_mode = PERSIST;
1284ec6ffc1aSdan      PRAGMA page_size = 1024;
1285d0b0d4dcSdan      BEGIN;
1286ec6ffc1aSdan        CREATE TABLE t1(a, b);
1287d0b0d4dcSdan        CREATE TABLE t2(a, b);
1288d0b0d4dcSdan        CREATE TABLE t3(a, b);
1289d0b0d4dcSdan      COMMIT;
1290ec6ffc1aSdan    }
1291ec6ffc1aSdan    file size test.db-journal
1292ec6ffc1aSdan  } [expr $sectorsize > 65536 ? 65536 : $sectorsize]
1293d0b0d4dcSdan
1294d0b0d4dcSdan  do_test pager1-10.$sectorsize.2 {
1295d0b0d4dcSdan    execsql {
1296d0b0d4dcSdan      INSERT INTO t3 VALUES(a_string(300), a_string(300));
1297d0b0d4dcSdan      INSERT INTO t3 SELECT * FROM t3;        /*  2 */
1298d0b0d4dcSdan      INSERT INTO t3 SELECT * FROM t3;        /*  4 */
1299d0b0d4dcSdan      INSERT INTO t3 SELECT * FROM t3;        /*  8 */
1300d0b0d4dcSdan      INSERT INTO t3 SELECT * FROM t3;        /* 16 */
1301d0b0d4dcSdan      INSERT INTO t3 SELECT * FROM t3;        /* 32 */
1302ec6ffc1aSdan    }
1303d0b0d4dcSdan  } {}
1304d0b0d4dcSdan
1305d0b0d4dcSdan  do_test pager1-10.$sectorsize.3 {
1306d0b0d4dcSdan    db close
1307d0b0d4dcSdan    sqlite3 db test.db
1308d0b0d4dcSdan    execsql {
1309d0b0d4dcSdan      PRAGMA cache_size = 10;
1310d0b0d4dcSdan      BEGIN;
1311d0b0d4dcSdan    }
1312d0b0d4dcSdan    recursive_select 32 t3 {db eval "INSERT INTO t2 VALUES(1, 2)"}
1313d0b0d4dcSdan    execsql {
1314d0b0d4dcSdan      COMMIT;
1315d0b0d4dcSdan      SELECT * FROM t2;
1316d0b0d4dcSdan    }
1317d0b0d4dcSdan  } {1 2}
1318d0b0d4dcSdan
1319d0b0d4dcSdan  do_test pager1-10.$sectorsize.4 {
1320d0b0d4dcSdan    execsql {
1321d0b0d4dcSdan      CREATE TABLE t6(a, b);
1322d0b0d4dcSdan      CREATE TABLE t7(a, b);
1323d0b0d4dcSdan      CREATE TABLE t5(a, b);
1324d0b0d4dcSdan      DROP TABLE t6;
1325d0b0d4dcSdan      DROP TABLE t7;
1326d0b0d4dcSdan    }
1327d0b0d4dcSdan    if {$eff==65536} breakpoint
1328d0b0d4dcSdan    execsql {
1329d0b0d4dcSdan      BEGIN;
1330d0b0d4dcSdan        CREATE TABLE t6(a, b);
1331d0b0d4dcSdan    }
1332d0b0d4dcSdan    recursive_select 32 t3 {db eval "INSERT INTO t5 VALUES(1, 2)"}
1333d0b0d4dcSdan    execsql {
1334d0b0d4dcSdan      COMMIT;
1335d0b0d4dcSdan      SELECT * FROM t5;
1336d0b0d4dcSdan    }
1337d0b0d4dcSdan  } {1 2}
1338d0b0d4dcSdan
1339d0b0d4dcSdan}
1340d0b0d4dcSdandb close
1341d0b0d4dcSdan
1342d0b0d4dcSdantv sectorsize 4096
1343d0b0d4dcSdando_test pager1.10.x.1 {
1344d0b0d4dcSdan  faultsim_delete_and_reopen
1345d0b0d4dcSdan  execsql {
1346d0b0d4dcSdan    PRAGMA page_size = 1024;
1347d0b0d4dcSdan    CREATE TABLE t1(x);
1348d0b0d4dcSdan  }
1349d0b0d4dcSdan  for {set i 0} {$i<30} {incr i} {
1350d0b0d4dcSdan    execsql { INSERT INTO t1 VALUES(zeroblob(900)) }
1351d0b0d4dcSdan  }
1352d0b0d4dcSdan  file size test.db
1353d0b0d4dcSdan} {32768}
1354d0b0d4dcSdando_test pager1.10.x.2 {
1355d0b0d4dcSdan  execsql {
1356d0b0d4dcSdan    CREATE TABLE t2(x);
1357d0b0d4dcSdan    DROP TABLE t2;
1358d0b0d4dcSdan  }
1359d0b0d4dcSdan  file size test.db
1360d0b0d4dcSdan} {33792}
1361d0b0d4dcSdando_test pager1.10.x.3 {
1362d0b0d4dcSdan  execsql {
1363d0b0d4dcSdan    BEGIN;
1364d0b0d4dcSdan    CREATE TABLE t2(x);
1365d0b0d4dcSdan  }
1366d0b0d4dcSdan  recursive_select 30 t1
1367d0b0d4dcSdan  execsql {
1368d0b0d4dcSdan    CREATE TABLE t3(x);
1369d0b0d4dcSdan    COMMIT;
1370d0b0d4dcSdan  }
1371d0b0d4dcSdan} {}
1372d0b0d4dcSdan
1373ec6ffc1aSdandb close
1374ec6ffc1aSdantv delete
1375ec6ffc1aSdan
1376ec6ffc1aSdantestvfs tv -default 1
1377ec6ffc1aSdanfaultsim_delete_and_reopen
1378ec6ffc1aSdandb func a_string a_string
1379ec6ffc1aSdando_execsql_test pager1-11.1 {
1380ec6ffc1aSdan  PRAGMA cache_size = 10;
1381ec6ffc1aSdan  BEGIN;
1382ec6ffc1aSdan    CREATE TABLE zz(top PRIMARY KEY);
1383ec6ffc1aSdan    INSERT INTO zz VALUES(a_string(222));
1384ec6ffc1aSdan    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
1385ec6ffc1aSdan    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
1386ec6ffc1aSdan    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
1387ec6ffc1aSdan    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
1388ec6ffc1aSdan    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
1389ec6ffc1aSdan  COMMIT;
1390ec6ffc1aSdan  BEGIN;
1391ec6ffc1aSdan    UPDATE zz SET top = a_string(345);
1392ec6ffc1aSdan} {}
1393ec6ffc1aSdan
1394ec6ffc1aSdanproc lockout {method args} { return SQLITE_IOERR }
1395ec6ffc1aSdantv script lockout
1396ec6ffc1aSdantv filter {xWrite xTruncate xSync}
1397ec6ffc1aSdando_catchsql_test pager1-11.2 { COMMIT } {1 {disk I/O error}}
1398ec6ffc1aSdan
1399ec6ffc1aSdantv script {}
1400ec6ffc1aSdando_test pager1-11.3 {
1401ec6ffc1aSdan  sqlite3 db2 test.db
1402ec6ffc1aSdan  execsql {
1403ec6ffc1aSdan    PRAGMA journal_mode = TRUNCATE;
1404ec6ffc1aSdan    PRAGMA integrity_check;
1405ec6ffc1aSdan  } db2
1406ec6ffc1aSdan} {truncate ok}
1407ec6ffc1aSdando_test pager1-11.4 {
1408ec6ffc1aSdan  db2 close
1409ec6ffc1aSdan  file size test.db-journal
1410ec6ffc1aSdan} {0}
1411ec6ffc1aSdando_execsql_test pager1-11.5 { SELECT count(*) FROM zz } {32}
1412f9b4419dSdandb close
1413f9b4419dSdantv delete
1414ec6ffc1aSdan
1415f9b4419dSdan#-------------------------------------------------------------------------
1416f9b4419dSdan# Test "PRAGMA page_size"
1417f9b4419dSdan#
1418f9b4419dSdanforeach pagesize {
1419f9b4419dSdan    512   1024   2048 4096 8192 16384 32768
1420f9b4419dSdan} {
1421f9b4419dSdan  faultsim_delete_and_reopen
1422f9b4419dSdan
1423f9b4419dSdan  do_test pager1-12.$pagesize.1 {
1424f9b4419dSdan    sqlite3 db2 test.db
1425f9b4419dSdan    execsql "
1426f9b4419dSdan      PRAGMA page_size = $pagesize;
1427f9b4419dSdan      CREATE VIEW v AS SELECT * FROM sqlite_master;
1428f9b4419dSdan    " db2
1429f9b4419dSdan    file size test.db
1430f9b4419dSdan  } $pagesize
1431f9b4419dSdan  do_test pager1-12.$pagesize.2 {
1432f9b4419dSdan    sqlite3 db2 test.db
1433f9b4419dSdan    execsql {
1434f9b4419dSdan      SELECT count(*) FROM v;
1435f9b4419dSdan      PRAGMA main.page_size;
1436f9b4419dSdan    } db2
1437f9b4419dSdan  } [list 1 $pagesize]
1438f9b4419dSdan  do_test pager1-12.$pagesize.3 {
1439f9b4419dSdan    execsql {
1440f9b4419dSdan      SELECT count(*) FROM v;
1441f9b4419dSdan      PRAGMA main.page_size;
1442f9b4419dSdan    }
1443f9b4419dSdan  } [list 1 $pagesize]
1444f9b4419dSdan  db2 close
1445f9b4419dSdan}
1446dca321aeSdan
1447d353331aSdan#-------------------------------------------------------------------------
1448d353331aSdan# Test specal "PRAGMA journal_mode=PERSIST" test cases.
1449d353331aSdan#
1450d353331aSdan# pager1-13.1.*: This tests a special case encountered in persistent
1451d353331aSdan#                journal mode: If the journal associated with a transaction
1452d353331aSdan#                is smaller than the journal file (because a previous
1453d353331aSdan#                transaction left a very large non-hot journal file in the
1454d353331aSdan#                file-system), then SQLite has to be careful that there is
1455d353331aSdan#                not a journal-header left over from a previous transaction
1456d353331aSdan#                immediately following the journal content just written.
1457d353331aSdan#                If there is, and the process crashes so that the journal
1458d353331aSdan#                becomes a hot-journal and must be rolled back by another
1459d353331aSdan#                process, there is a danger that the other process may roll
1460d353331aSdan#                back the aborted transaction, then continue copying data
1461d353331aSdan#                from an older transaction from the remainder of the journal.
1462d353331aSdan#                See the syncJournal() function for details.
1463d353331aSdan#
1464d353331aSdan# pager1-13.2.*: Same test as the previous. This time, throw an index into
1465d353331aSdan#                the mix to make the integrity-check more likely to catch
1466d353331aSdan#                errors.
1467d353331aSdan#
1468d353331aSdantestvfs tv -default 1
1469d353331aSdantv script xSyncCb
1470d353331aSdantv filter xSync
1471d353331aSdanproc xSyncCb {method filename args} {
1472d353331aSdan  set t [file tail $filename]
1473d353331aSdan  if {$t == "test.db"} faultsim_save
1474d353331aSdan  return SQLITE_OK
1475d353331aSdan}
1476d353331aSdanfaultsim_delete_and_reopen
1477d353331aSdandb func a_string a_string
1478e91a54e1Sdan
1479d353331aSdan# The UPDATE statement at the end of this test case creates a really big
1480d353331aSdan# journal. Since the cache-size is only 10 pages, the journal contains
1481d353331aSdan# frequent journal headers.
1482d353331aSdan#
1483d353331aSdando_execsql_test pager1-13.1.1 {
1484d353331aSdan  PRAGMA page_size = 1024;
1485d353331aSdan  PRAGMA journal_mode = PERSIST;
1486d353331aSdan  PRAGMA cache_size = 10;
1487d353331aSdan  BEGIN;
1488d353331aSdan    CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB);
1489d353331aSdan    INSERT INTO t1 VALUES(NULL, a_string(400));
1490d353331aSdan    INSERT INTO t1 SELECT NULL, a_string(400) FROM t1;          /*   2 */
1491d353331aSdan    INSERT INTO t1 SELECT NULL, a_string(400) FROM t1;          /*   4 */
1492d353331aSdan    INSERT INTO t1 SELECT NULL, a_string(400) FROM t1;          /*   8 */
1493d353331aSdan    INSERT INTO t1 SELECT NULL, a_string(400) FROM t1;          /*  16 */
1494d353331aSdan    INSERT INTO t1 SELECT NULL, a_string(400) FROM t1;          /*  32 */
1495d353331aSdan    INSERT INTO t1 SELECT NULL, a_string(400) FROM t1;          /*  64 */
1496d353331aSdan    INSERT INTO t1 SELECT NULL, a_string(400) FROM t1;          /* 128 */
1497d353331aSdan  COMMIT;
1498d353331aSdan  UPDATE t1 SET b = a_string(400);
1499d353331aSdan} {persist}
1500d353331aSdan
1501d353331aSdan# Run transactions of increasing sizes. Eventually, one (or more than one)
1502d353331aSdan# of these will write just enough content that one of the old headers created
1503d353331aSdan# by the transaction in the block above lies immediately after the content
1504d353331aSdan# journalled by the current transaction.
1505d353331aSdan#
1506d353331aSdanfor {set nUp 1} {$nUp<64} {incr nUp} {
1507d353331aSdan  do_execsql_test pager1-13.1.2.$nUp.1 {
1508d353331aSdan    UPDATE t1 SET b = a_string(399) WHERE a <= $nUp
1509d353331aSdan  } {}
1510d353331aSdan  do_execsql_test pager1-13.1.2.$nUp.2 { PRAGMA integrity_check } {ok}
1511d353331aSdan
1512d353331aSdan  # Try to access the snapshot of the file-system.
1513d353331aSdan  #
1514d353331aSdan  sqlite3 db2 sv_test.db
1515d353331aSdan  do_test pager1-13.1.2.$nUp.3 {
1516d353331aSdan    execsql { SELECT sum(length(b)) FROM t1 } db2
1517d353331aSdan  } [expr {128*400 - ($nUp-1)}]
1518d353331aSdan  do_test pager1-13.1.2.$nUp.4 {
1519d353331aSdan    execsql { PRAGMA integrity_check } db2
1520d353331aSdan  } {ok}
1521d353331aSdan  db2 close
1522d353331aSdan}
1523d353331aSdan
1524d353331aSdan# Same test as above. But this time with an index on the table.
1525d353331aSdan#
1526d353331aSdando_execsql_test pager1-13.2.1 {
1527d353331aSdan  CREATE INDEX i1 ON t1(b);
1528d353331aSdan  UPDATE t1 SET b = a_string(400);
1529d353331aSdan} {}
1530d353331aSdanfor {set nUp 1} {$nUp<64} {incr nUp} {
1531d353331aSdan  do_execsql_test pager1-13.2.2.$nUp.1 {
1532d353331aSdan    UPDATE t1 SET b = a_string(399) WHERE a <= $nUp
1533d353331aSdan  } {}
1534d353331aSdan  do_execsql_test pager1-13.2.2.$nUp.2 { PRAGMA integrity_check } {ok}
1535d353331aSdan  sqlite3 db2 sv_test.db
1536d353331aSdan  do_test pager1-13.2.2.$nUp.3 {
1537d353331aSdan    execsql { SELECT sum(length(b)) FROM t1 } db2
1538d353331aSdan  } [expr {128*400 - ($nUp-1)}]
1539d353331aSdan  do_test pager1-13.2.2.$nUp.4 {
1540d353331aSdan    execsql { PRAGMA integrity_check } db2
1541d353331aSdan  } {ok}
1542d353331aSdan  db2 close
1543d353331aSdan}
1544d353331aSdan
1545d353331aSdandb close
1546d353331aSdantv delete
1547d353331aSdan
1548d353331aSdan#-------------------------------------------------------------------------
1549d353331aSdan# Test specal "PRAGMA journal_mode=OFF" test cases.
1550d353331aSdan#
1551d353331aSdanfaultsim_delete_and_reopen
1552d353331aSdando_execsql_test pager1-14.1.1 {
1553d353331aSdan  PRAGMA journal_mode = OFF;
1554d353331aSdan  CREATE TABLE t1(a, b);
1555d353331aSdan  BEGIN;
1556d353331aSdan    INSERT INTO t1 VALUES(1, 2);
1557d353331aSdan  COMMIT;
1558d353331aSdan  SELECT * FROM t1;
1559d353331aSdan} {off 1 2}
1560d353331aSdando_catchsql_test pager1-14.1.2 {
1561d353331aSdan  BEGIN;
1562d353331aSdan    INSERT INTO t1 VALUES(3, 4);
1563d353331aSdan  ROLLBACK;
1564d353331aSdan} {0 {}}
1565d353331aSdando_execsql_test pager1-14.1.3 {
1566d353331aSdan  SELECT * FROM t1;
1567d353331aSdan} {1 2 3 4}
1568d353331aSdando_catchsql_test pager1-14.1.4 {
1569d353331aSdan  BEGIN;
1570d353331aSdan    INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
1571d353331aSdan    INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
1572d353331aSdan} {1 {PRIMARY KEY must be unique}}
1573d353331aSdando_execsql_test pager1-14.1.5 {
1574d353331aSdan  COMMIT;
1575d353331aSdan  SELECT * FROM t1;
1576d353331aSdan} {1 2 3 4 2 2 4 4}
1577d353331aSdan
1578c8ce3972Sdan#-------------------------------------------------------------------------
1579c8ce3972Sdan# Test opening and closing the pager sub-system with different values
1580c8ce3972Sdan# for the sqlite3_vfs.szOsFile variable.
1581c8ce3972Sdan#
1582c8ce3972Sdanfaultsim_delete_and_reopen
1583c8ce3972Sdando_execsql_test pager1-15.0 {
1584c8ce3972Sdan  CREATE TABLE tx(y, z);
1585c8ce3972Sdan  INSERT INTO tx VALUES('Ayutthaya', 'Beijing');
1586c8ce3972Sdan  INSERT INTO tx VALUES('London', 'Tokyo');
1587c8ce3972Sdan} {}
1588c8ce3972Sdandb close
1589c8ce3972Sdanfor {set i 0} {$i<513} {incr i 3} {
1590c8ce3972Sdan  testvfs tv -default 1 -szosfile $i
1591c8ce3972Sdan  sqlite3 db test.db
1592c8ce3972Sdan  do_execsql_test pager1-15.$i.1 {
1593c8ce3972Sdan    SELECT * FROM tx;
1594c8ce3972Sdan  } {Ayutthaya Beijing London Tokyo}
1595c8ce3972Sdan  db close
1596c8ce3972Sdan  tv delete
1597c8ce3972Sdan}
1598c8ce3972Sdan
1599c8ce3972Sdan#-------------------------------------------------------------------------
1600c8ce3972Sdan# Check that it is not possible to open a database file if the full path
1601c8ce3972Sdan# to the associated journal file will be longer than sqlite3_vfs.mxPathname.
1602c8ce3972Sdan#
1603c8ce3972Sdantestvfs tv -default 1
1604c8ce3972Sdantv script xOpenCb
1605c8ce3972Sdantv filter xOpen
1606c8ce3972Sdanproc xOpenCb {method filename} {
1607c8ce3972Sdan  set ::file_len [string length $filename]
1608c8ce3972Sdan}
1609c8ce3972Sdansqlite3 db test.db
1610c8ce3972Sdandb close
1611c8ce3972Sdantv delete
1612c8ce3972Sdan
1613c8ce3972Sdanfor {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} {
1614c8ce3972Sdan  testvfs tv -default 1 -mxpathname $ii
1615c8ce3972Sdan
1616c8ce3972Sdan  # The length of the full path to file "test.db-journal" is ($::file_len+8).
1617c8ce3972Sdan  # If the configured sqlite3_vfs.mxPathname value greater than or equal to
1618c8ce3972Sdan  # this, then the file can be opened. Otherwise, it cannot.
1619c8ce3972Sdan  #
1620c8ce3972Sdan  if {$ii >= [expr $::file_len+8]} {
1621c8ce3972Sdan    set res {0 {}}
1622c8ce3972Sdan  } else {
1623c8ce3972Sdan    set res {1 {unable to open database file}}
1624c8ce3972Sdan  }
1625c8ce3972Sdan
1626c8ce3972Sdan  do_test pager1-16.1.$ii {
1627c8ce3972Sdan    list [catch { sqlite3 db test.db } msg] $msg
1628c8ce3972Sdan  } $res
1629c8ce3972Sdan
1630c8ce3972Sdan  catch {db close}
1631c8ce3972Sdan  tv delete
1632c8ce3972Sdan}
1633c8ce3972Sdan
1634c8ce3972Sdan#-------------------------------------------------------------------------
1635c8ce3972Sdan# Test "PRAGMA omit_readlock".
1636c8ce3972Sdan#
1637c8ce3972Sdan#   pager1-17.$tn.1.*: Test that if a second connection has an open
1638c8ce3972Sdan#                      read-transaction, it is not usually possible to write
1639c8ce3972Sdan#                      the database.
1640c8ce3972Sdan#
1641c8ce3972Sdan#   pager1-17.$tn.2.*: Test that if the second connection was opened with
1642c8ce3972Sdan#                      the SQLITE_OPEN_READONLY flag, and
1643c8ce3972Sdan#                      "PRAGMA omit_readlock = 1" is executed before attaching
1644c8ce3972Sdan#                      the database and opening a read-transaction on it, it is
1645c8ce3972Sdan#                      possible to write the db.
1646c8ce3972Sdan#
1647c8ce3972Sdan#   pager1-17.$tn.3.*: Test that if the second connection was *not* opened with
1648c8ce3972Sdan#                      the SQLITE_OPEN_READONLY flag, executing
1649c8ce3972Sdan#                      "PRAGMA omit_readlock = 1" has no effect.
1650c8ce3972Sdan#
1651c8ce3972Sdando_multiclient_test tn {
1652c8ce3972Sdan  do_test pager1-17.$tn.1.1 {
1653c8ce3972Sdan    sql1 {
1654c8ce3972Sdan      CREATE TABLE t1(a, b);
1655c8ce3972Sdan      INSERT INTO t1 VALUES(1, 2);
1656c8ce3972Sdan    }
1657c8ce3972Sdan    sql2 {
1658c8ce3972Sdan      BEGIN;
1659c8ce3972Sdan      SELECT * FROM t1;
1660c8ce3972Sdan    }
1661c8ce3972Sdan  } {1 2}
1662c8ce3972Sdan  do_test pager1-17.$tn.1.2 {
1663c8ce3972Sdan    csql1 { INSERT INTO t1 VALUES(3, 4) }
1664c8ce3972Sdan  } {1 {database is locked}}
1665c8ce3972Sdan  do_test pager1-17.$tn.1.3 {
1666c8ce3972Sdan    sql2 { COMMIT }
1667c8ce3972Sdan    sql1 { INSERT INTO t1 VALUES(3, 4) }
1668c8ce3972Sdan  } {}
1669c8ce3972Sdan
1670c8ce3972Sdan  do_test pager1-17.$tn.2.1 {
1671c8ce3972Sdan    code2 {
1672c8ce3972Sdan      db2 close
1673c8ce3972Sdan      sqlite3 db2 :memory: -readonly 1
1674c8ce3972Sdan    }
1675c8ce3972Sdan    sql2 {
1676c8ce3972Sdan      PRAGMA omit_readlock = 1;
1677c8ce3972Sdan      ATTACH 'test.db' AS two;
1678c8ce3972Sdan      BEGIN;
1679c8ce3972Sdan      SELECT * FROM t1;
1680c8ce3972Sdan    }
1681c8ce3972Sdan  } {1 2 3 4}
1682c8ce3972Sdan  do_test pager1-17.$tn.2.2 { sql1 "INSERT INTO t1 VALUES(5, 6)" } {}
1683c8ce3972Sdan  do_test pager1-17.$tn.2.3 { sql2 "SELECT * FROM t1" }            {1 2 3 4}
1684c8ce3972Sdan  do_test pager1-17.$tn.2.4 { sql2 "COMMIT ; SELECT * FROM t1" }   {1 2 3 4 5 6}
1685c8ce3972Sdan
1686c8ce3972Sdan  do_test pager1-17.$tn.3.1 {
1687c8ce3972Sdan    code2 {
1688c8ce3972Sdan      db2 close
1689c8ce3972Sdan      sqlite3 db2 :memory:
1690c8ce3972Sdan    }
1691c8ce3972Sdan    sql2 {
1692c8ce3972Sdan      PRAGMA omit_readlock = 1;
1693c8ce3972Sdan      ATTACH 'test.db' AS two;
1694c8ce3972Sdan      BEGIN;
1695c8ce3972Sdan      SELECT * FROM t1;
1696c8ce3972Sdan    }
1697c8ce3972Sdan  } {1 2 3 4 5 6}
1698c8ce3972Sdan  do_test pager1-17.$tn.3.2 {
1699c8ce3972Sdan    csql1 { INSERT INTO t1 VALUES(3, 4) }
1700c8ce3972Sdan  } {1 {database is locked}}
1701c8ce3972Sdan  do_test pager1-17.$tn.3.3 { sql2 COMMIT } {}
1702c8ce3972Sdan}
1703c8ce3972Sdan
1704c8ce3972Sdan#-------------------------------------------------------------------------
1705c8ce3972Sdan# Test the pagers response to the b-tree layer requesting illegal page
1706c8ce3972Sdan# numbers:
1707c8ce3972Sdan#
1708c8ce3972Sdan#   + The locking page,
1709c8ce3972Sdan#   + Page 0,
1710c8ce3972Sdan#   + A page with a page number greater than (2^31-1).
1711c8ce3972Sdan#
1712c8ce3972Sdando_test pager1-18.1 {
1713c8ce3972Sdan  faultsim_delete_and_reopen
1714c8ce3972Sdan  db func a_string a_string
1715c8ce3972Sdan  execsql {
1716c8ce3972Sdan    PRAGMA page_size = 1024;
1717c8ce3972Sdan    CREATE TABLE t1(a, b);
1718c8ce3972Sdan    INSERT INTO t1 VALUES(a_string(500), a_string(200));
1719c8ce3972Sdan    INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
1720c8ce3972Sdan    INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
1721c8ce3972Sdan    INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
1722c8ce3972Sdan    INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
1723c8ce3972Sdan    INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
1724c8ce3972Sdan    INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
1725c8ce3972Sdan    INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1;
1726c8ce3972Sdan  }
1727c8ce3972Sdan} {}
1728c8ce3972Sdando_test pager1-18.2 {
1729c8ce3972Sdan  set root [db one "SELECT rootpage FROM sqlite_master"]
1730c8ce3972Sdan  set lockingpage [expr (0x10000/1024) + 1]
1731c8ce3972Sdan  execsql {
1732c8ce3972Sdan    PRAGMA writable_schema = 1;
1733c8ce3972Sdan    UPDATE sqlite_master SET rootpage = $lockingpage;
1734c8ce3972Sdan  }
1735c8ce3972Sdan  sqlite3 db2 test.db
1736c8ce3972Sdan  catchsql { SELECT count(*) FROM t1 } db2
1737c8ce3972Sdan} {1 {database disk image is malformed}}
1738c8ce3972Sdandb2 close
1739c8ce3972Sdando_test pager1-18.3 {
1740c8ce3972Sdan  execsql {
1741c8ce3972Sdan    CREATE TABLE t2(x);
1742c8ce3972Sdan    INSERT INTO t2 VALUES(a_string(5000));
1743c8ce3972Sdan  }
1744c8ce3972Sdan  set pgno [expr ([file size test.db] / 1024)-2]
1745c8ce3972Sdan  hexio_write test.db [expr ($pgno-1)*1024] 00000000
1746c8ce3972Sdan  sqlite3 db2 test.db
1747c8ce3972Sdan  catchsql { SELECT length(x) FROM t2 } db2
1748c8ce3972Sdan} {1 {database disk image is malformed}}
1749c8ce3972Sdandb2 close
1750c8ce3972Sdando_test pager1-18.4 {
1751c8ce3972Sdan  hexio_write test.db [expr ($pgno-1)*1024] 90000000
1752c8ce3972Sdan  sqlite3 db2 test.db
1753c8ce3972Sdan  catchsql { SELECT length(x) FROM t2 } db2
1754c8ce3972Sdan} {1 {database disk image is malformed}}
1755c8ce3972Sdandb2 close
1756c8ce3972Sdando_test pager1-18.5 {
1757c8ce3972Sdan  sqlite3 db ""
1758c8ce3972Sdan  execsql {
1759c8ce3972Sdan    CREATE TABLE t1(a, b);
1760c8ce3972Sdan    CREATE TABLE t2(a, b);
1761c8ce3972Sdan    PRAGMA writable_schema = 1;
1762c8ce3972Sdan    UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1';
1763c8ce3972Sdan    PRAGMA writable_schema = 0;
1764c8ce3972Sdan    ALTER TABLE t1 RENAME TO x1;
1765c8ce3972Sdan  }
1766c8ce3972Sdan  catchsql { SELECT * FROM x1 }
1767ba3cbf3dSdan} {1 {database disk image is malformed}}
1768c8ce3972Sdandb close
1769c8ce3972Sdan
1770ba3cbf3dSdando_test pager1-18.6 {
1771ba3cbf3dSdan  faultsim_delete_and_reopen
1772ba3cbf3dSdan  db func a_string a_string
1773ba3cbf3dSdan  execsql {
1774ba3cbf3dSdan    PRAGMA page_size = 1024;
1775ba3cbf3dSdan    CREATE TABLE t1(x);
1776ba3cbf3dSdan    INSERT INTO t1 VALUES(a_string(800));
1777ba3cbf3dSdan    INSERT INTO t1 VALUES(a_string(800));
1778ba3cbf3dSdan  }
1779ba3cbf3dSdan
1780ba3cbf3dSdan  set root [db one "SELECT rootpage FROM sqlite_master"]
1781ba3cbf3dSdan  db close
1782ba3cbf3dSdan
1783ba3cbf3dSdan  hexio_write test.db [expr ($root-1)*1024 + 8] 00000000
1784ba3cbf3dSdan  sqlite3 db test.db
1785ba3cbf3dSdan  catchsql { SELECT length(x) FROM t1 }
1786ba3cbf3dSdan} {1 {database disk image is malformed}}
1787ba3cbf3dSdan
1788ba3cbf3dSdando_test pager1-19.1 {
1789ba3cbf3dSdan  sqlite3 db ""
1790ba3cbf3dSdan  db func a_string a_string
1791ba3cbf3dSdan  execsql {
1792ba3cbf3dSdan    PRAGMA page_size = 512;
1793ba3cbf3dSdan    PRAGMA auto_vacuum = 1;
1794ba3cbf3dSdan    CREATE TABLE t1(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an,
1795ba3cbf3dSdan                    ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn,
1796ba3cbf3dSdan                    ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn,
1797ba3cbf3dSdan                    da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn,
1798ba3cbf3dSdan                    ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en,
1799ba3cbf3dSdan                    fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn,
1800ba3cbf3dSdan                    ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn,
1801ba3cbf3dSdan                    ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn,
1802ba3cbf3dSdan                    ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix,
1803ba3cbf3dSdan                    ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn,
1804ba3cbf3dSdan                    ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn,
1805ba3cbf3dSdan                    la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln,
1806ba3cbf3dSdan                    ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn
1807ba3cbf3dSdan    );
1808ba3cbf3dSdan    CREATE TABLE t2(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an,
1809ba3cbf3dSdan                    ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn,
1810ba3cbf3dSdan                    ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn,
1811ba3cbf3dSdan                    da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn,
1812ba3cbf3dSdan                    ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en,
1813ba3cbf3dSdan                    fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn,
1814ba3cbf3dSdan                    ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn,
1815ba3cbf3dSdan                    ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn,
1816ba3cbf3dSdan                    ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix,
1817ba3cbf3dSdan                    ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn,
1818ba3cbf3dSdan                    ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn,
1819ba3cbf3dSdan                    la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln,
1820ba3cbf3dSdan                    ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn
1821ba3cbf3dSdan    );
1822ba3cbf3dSdan    INSERT INTO t1(aa) VALUES( a_string(100000) );
1823ba3cbf3dSdan    INSERT INTO t2(aa) VALUES( a_string(100000) );
1824ba3cbf3dSdan    VACUUM;
1825ba3cbf3dSdan  }
1826ba3cbf3dSdan} {}
1827ba3cbf3dSdan
18286b63ab47Sdan#-------------------------------------------------------------------------
18296b63ab47Sdan# Test a couple of special cases that come up while committing
18306b63ab47Sdan# transactions:
18316b63ab47Sdan#
18326b63ab47Sdan#   pager1-20.1.*: Committing an in-memory database transaction when the
18336b63ab47Sdan#                  database has not been modified at all.
18346b63ab47Sdan#
18356b63ab47Sdan#   pager1-20.2.*: As above, but with a normal db in exclusive-locking mode.
18366b63ab47Sdan#
18376b63ab47Sdan#   pager1-20.3.*: Committing a transaction in WAL mode where the database has
18386b63ab47Sdan#                  been modified, but all dirty pages have been flushed to
18396b63ab47Sdan#                  disk before the commit.
18406b63ab47Sdan#
18416b63ab47Sdando_test pager1-20.1.1 {
18426b63ab47Sdan  catch {db close}
18436b63ab47Sdan  sqlite3 db :memory:
18446b63ab47Sdan  execsql {
18456b63ab47Sdan    CREATE TABLE one(two, three);
18466b63ab47Sdan    INSERT INTO one VALUES('a', 'b');
18476b63ab47Sdan  }
18486b63ab47Sdan} {}
18496b63ab47Sdando_test pager1-20.1.2 {
18506b63ab47Sdan  execsql {
18516b63ab47Sdan    BEGIN EXCLUSIVE;
18526b63ab47Sdan    COMMIT;
18536b63ab47Sdan  }
18546b63ab47Sdan} {}
18556b63ab47Sdan
18566b63ab47Sdando_test pager1-20.2.1 {
18576b63ab47Sdan  faultsim_delete_and_reopen
18586b63ab47Sdan  execsql {
18596b63ab47Sdan    PRAGMA locking_mode = exclusive;
18606b63ab47Sdan    PRAGMA journal_mode = persist;
18616b63ab47Sdan    CREATE TABLE one(two, three);
18626b63ab47Sdan    INSERT INTO one VALUES('a', 'b');
18636b63ab47Sdan  }
18646b63ab47Sdan} {exclusive persist}
18656b63ab47Sdando_test pager1-20.2.2 {
18666b63ab47Sdan  execsql {
18676b63ab47Sdan    BEGIN EXCLUSIVE;
18686b63ab47Sdan    COMMIT;
18696b63ab47Sdan  }
18706b63ab47Sdan} {}
18716b63ab47Sdan
18726b63ab47Sdando_test pager1-20.3.1 {
18736b63ab47Sdan  faultsim_delete_and_reopen
18746b63ab47Sdan  db func a_string a_string
18756b63ab47Sdan  execsql {
18766b63ab47Sdan    PRAGMA cache_size = 10;
18776b63ab47Sdan    PRAGMA journal_mode = wal;
18786b63ab47Sdan    BEGIN;
18796b63ab47Sdan      CREATE TABLE t1(x);
18806b63ab47Sdan      CREATE TABLE t2(y);
18816b63ab47Sdan      INSERT INTO t1 VALUES(a_string(800));
18826b63ab47Sdan      INSERT INTO t1 SELECT a_string(800) FROM t1;         /*   2 */
18836b63ab47Sdan      INSERT INTO t1 SELECT a_string(800) FROM t1;         /*   4 */
18846b63ab47Sdan      INSERT INTO t1 SELECT a_string(800) FROM t1;         /*   8 */
18856b63ab47Sdan      INSERT INTO t1 SELECT a_string(800) FROM t1;         /*  16 */
18866b63ab47Sdan      INSERT INTO t1 SELECT a_string(800) FROM t1;         /*  32 */
18876b63ab47Sdan    COMMIT;
18886b63ab47Sdan  }
18896b63ab47Sdan} {wal}
18906b63ab47Sdando_test pager1-20.3.2 {
18916b63ab47Sdan  execsql {
18926b63ab47Sdan    BEGIN;
18936b63ab47Sdan    INSERT INTO t2 VALUES('xxxx');
18946b63ab47Sdan  }
1895*c396d4afSdan  recursive_select 32 t1
18966b63ab47Sdan  execsql COMMIT
18976b63ab47Sdan} {}
18986b63ab47Sdan
189989ccf448Sdan#-------------------------------------------------------------------------
190089ccf448Sdan# Test that a WAL database may not be opened if:
190189ccf448Sdan#
190289ccf448Sdan#   pager1-21.1.*: The VFS has an iVersion less than 2, or
190389ccf448Sdan#   pager1-21.2.*: The VFS does not provide xShmXXX() methods.
190489ccf448Sdan#
190589ccf448Sdando_test pager1-21.0 {
190689ccf448Sdan  faultsim_delete_and_reopen
190789ccf448Sdan  execsql {
190889ccf448Sdan    PRAGMA journal_mode = WAL;
190989ccf448Sdan    CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def');
191089ccf448Sdan    INSERT INTO ko DEFAULT VALUES;
191189ccf448Sdan  }
191289ccf448Sdan} {wal}
191389ccf448Sdando_test pager1-21.1 {
191489ccf448Sdan  testvfs tv -noshm 1
191589ccf448Sdan  sqlite3 db2 test.db -vfs tv
191689ccf448Sdan  catchsql { SELECT * FROM ko } db2
191789ccf448Sdan} {1 {unable to open database file}}
191889ccf448Sdandb2 close
191989ccf448Sdantv delete
192089ccf448Sdando_test pager1-21.2 {
192189ccf448Sdan  testvfs tv -iversion 1
192289ccf448Sdan  sqlite3 db2 test.db -vfs tv
192389ccf448Sdan  catchsql { SELECT * FROM ko } db2
192489ccf448Sdan} {1 {unable to open database file}}
192589ccf448Sdandb2 close
192689ccf448Sdantv delete
192789ccf448Sdan
192889ccf448Sdan#-------------------------------------------------------------------------
192989ccf448Sdan# Test that a "PRAGMA wal_checkpoint":
193089ccf448Sdan#
193189ccf448Sdan#   pager1-22.1.*: is a no-op on a non-WAL db, and
193289ccf448Sdan#   pager1-22.2.*: does not cause xSync calls with a synchronous=off db.
193389ccf448Sdan#
193489ccf448Sdando_test pager1-22.1.1 {
193589ccf448Sdan  faultsim_delete_and_reopen
193689ccf448Sdan  execsql {
193789ccf448Sdan    CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def');
193889ccf448Sdan    INSERT INTO ko DEFAULT VALUES;
193989ccf448Sdan  }
194089ccf448Sdan  execsql { PRAGMA wal_checkpoint }
194189ccf448Sdan} {}
194289ccf448Sdando_test pager1-22.2.1 {
194389ccf448Sdan  testvfs tv -default 1
194489ccf448Sdan  tv filter xSync
194589ccf448Sdan  tv script xSyncCb
194689ccf448Sdan  proc xSyncCb {args} {incr ::synccount}
194789ccf448Sdan  set ::synccount 0
194889ccf448Sdan  sqlite3 db test.db
194989ccf448Sdan  execsql {
195089ccf448Sdan    PRAGMA synchronous = off;
195189ccf448Sdan    PRAGMA journal_mode = WAL;
195289ccf448Sdan    INSERT INTO ko DEFAULT VALUES;
195389ccf448Sdan  }
195489ccf448Sdan  execsql { PRAGMA wal_checkpoint }
195589ccf448Sdan  set synccount
195689ccf448Sdan} {0}
195789ccf448Sdandb close
195889ccf448Sdantv delete
195989ccf448Sdan
196089ccf448Sdan#-------------------------------------------------------------------------
196189ccf448Sdan# Tests for changing journal mode.
196289ccf448Sdan#
196389ccf448Sdan#   pager1-23.1.*: Test that when changing from PERSIST to DELETE mode,
196489ccf448Sdan#                  the journal file is deleted.
196589ccf448Sdan#
196689ccf448Sdan#   pager1-23.2.*: Same test as above, but while a shared lock is held
196789ccf448Sdan#                  on the database file.
196889ccf448Sdan#
196989ccf448Sdan#   pager1-23.3.*: Same test as above, but while a reserved lock is held
197089ccf448Sdan#                  on the database file.
197189ccf448Sdan#
197289ccf448Sdan#   pager1-23.4.*: And, for fun, while holding an exclusive lock.
197389ccf448Sdan#
197489ccf448Sdan#   pager1-23.5.*: Try to set various different journal modes with an
197589ccf448Sdan#                  in-memory database (only MEMORY and OFF should work).
197689ccf448Sdan#
1977d0b0d4dcSdan#   pager1-23.6.*: Try to set locking_mode=normal on an in-memory database
1978d0b0d4dcSdan#                  (doesn't work - in-memory databases always use
1979d0b0d4dcSdan#                  locking_mode=exclusive).
1980d0b0d4dcSdan#
198189ccf448Sdando_test pager1-23.1.1 {
198289ccf448Sdan  faultsim_delete_and_reopen
198389ccf448Sdan  execsql {
198489ccf448Sdan    PRAGMA journal_mode = PERSIST;
198589ccf448Sdan    CREATE TABLE t1(a, b);
198689ccf448Sdan  }
198789ccf448Sdan  file exists test.db-journal
198889ccf448Sdan} {1}
198989ccf448Sdando_test pager1-23.1.2 {
199089ccf448Sdan  execsql { PRAGMA journal_mode = DELETE }
199189ccf448Sdan  file exists test.db-journal
199289ccf448Sdan} {0}
199389ccf448Sdan
199489ccf448Sdando_test pager1-23.2.1 {
199589ccf448Sdan  execsql {
199689ccf448Sdan    PRAGMA journal_mode = PERSIST;
199789ccf448Sdan    INSERT INTO t1 VALUES('Canberra', 'ACT');
199889ccf448Sdan  }
199989ccf448Sdan  db eval { SELECT * FROM t1 } {
200089ccf448Sdan    db eval { PRAGMA journal_mode = DELETE }
200189ccf448Sdan  }
200289ccf448Sdan  execsql { PRAGMA journal_mode }
200389ccf448Sdan} {delete}
200489ccf448Sdando_test pager1-23.2.2 {
200589ccf448Sdan  file exists test.db-journal
200689ccf448Sdan} {0}
200789ccf448Sdan
200889ccf448Sdando_test pager1-23.3.1 {
200989ccf448Sdan  execsql {
201089ccf448Sdan    PRAGMA journal_mode = PERSIST;
201189ccf448Sdan    INSERT INTO t1 VALUES('Darwin', 'NT');
201289ccf448Sdan    BEGIN IMMEDIATE;
201389ccf448Sdan  }
201489ccf448Sdan  db eval { PRAGMA journal_mode = DELETE }
201589ccf448Sdan  execsql { PRAGMA journal_mode }
201689ccf448Sdan} {delete}
201789ccf448Sdando_test pager1-23.3.2 {
201889ccf448Sdan  file exists test.db-journal
201989ccf448Sdan} {0}
202089ccf448Sdando_test pager1-23.3.3 {
202189ccf448Sdan  execsql COMMIT
202289ccf448Sdan} {}
202389ccf448Sdan
202489ccf448Sdando_test pager1-23.4.1 {
202589ccf448Sdan  execsql {
202689ccf448Sdan    PRAGMA journal_mode = PERSIST;
202789ccf448Sdan    INSERT INTO t1 VALUES('Adelaide', 'SA');
202889ccf448Sdan    BEGIN EXCLUSIVE;
202989ccf448Sdan  }
203089ccf448Sdan  db eval { PRAGMA journal_mode = DELETE }
203189ccf448Sdan  execsql { PRAGMA journal_mode }
203289ccf448Sdan} {delete}
203389ccf448Sdando_test pager1-23.4.2 {
203489ccf448Sdan  file exists test.db-journal
203589ccf448Sdan} {0}
203689ccf448Sdando_test pager1-23.4.3 {
203789ccf448Sdan  execsql COMMIT
203889ccf448Sdan} {}
203989ccf448Sdan
204089ccf448Sdando_test pager1-23.5.1 {
204189ccf448Sdan  faultsim_delete_and_reopen
204289ccf448Sdan  sqlite3 db :memory:
204389ccf448Sdan} {}
204489ccf448Sdanforeach {tn mode possible} {
204589ccf448Sdan  2  off      1
204689ccf448Sdan  3  memory   1
204789ccf448Sdan  4  persist  0
204889ccf448Sdan  5  delete   0
204989ccf448Sdan  6  wal      0
205089ccf448Sdan  7  truncate 0
205189ccf448Sdan} {
205289ccf448Sdan  do_test pager1-23.5.$tn.1 {
205389ccf448Sdan    execsql "PRAGMA journal_mode = off"
205489ccf448Sdan    execsql "PRAGMA journal_mode = $mode"
205589ccf448Sdan  } [if $possible {list $mode} {list off}]
205689ccf448Sdan  do_test pager1-23.5.$tn.2 {
205789ccf448Sdan    execsql "PRAGMA journal_mode = memory"
205889ccf448Sdan    execsql "PRAGMA journal_mode = $mode"
205989ccf448Sdan  } [if $possible {list $mode} {list memory}]
206089ccf448Sdan}
2061d0b0d4dcSdando_test pager1-23.6.1 {
206289ccf448Sdan  execsql {PRAGMA locking_mode = normal}
206389ccf448Sdan} {exclusive}
2064d0b0d4dcSdando_test pager1-23.6.2 {
206589ccf448Sdan  execsql {PRAGMA locking_mode = exclusive}
206689ccf448Sdan} {exclusive}
2067d0b0d4dcSdando_test pager1-23.6.3 {
206889ccf448Sdan  execsql {PRAGMA locking_mode}
206989ccf448Sdan} {exclusive}
2070d0b0d4dcSdando_test pager1-23.6.4 {
207189ccf448Sdan  execsql {PRAGMA main.locking_mode}
207289ccf448Sdan} {exclusive}
20736b63ab47Sdan
2074d0b0d4dcSdan#-------------------------------------------------------------------------
2075d0b0d4dcSdan#
2076d0b0d4dcSdando_test pager1-24.1.1 {
2077d0b0d4dcSdan  faultsim_delete_and_reopen
2078d0b0d4dcSdan  db func a_string a_string
2079d0b0d4dcSdan  execsql {
2080d0b0d4dcSdan    PRAGMA cache_size = 10;
2081d0b0d4dcSdan    PRAGMA auto_vacuum = FULL;
2082d0b0d4dcSdan    CREATE TABLE x1(x, y, z, PRIMARY KEY(y, z));
2083d0b0d4dcSdan    CREATE TABLE x2(x, y, z, PRIMARY KEY(y, z));
2084d0b0d4dcSdan    INSERT INTO x2 VALUES(a_string(400), a_string(500), a_string(600));
2085d0b0d4dcSdan    INSERT INTO x2 SELECT a_string(600), a_string(400), a_string(500) FROM x2;
2086d0b0d4dcSdan    INSERT INTO x2 SELECT a_string(500), a_string(600), a_string(400) FROM x2;
2087d0b0d4dcSdan    INSERT INTO x2 SELECT a_string(400), a_string(500), a_string(600) FROM x2;
2088d0b0d4dcSdan    INSERT INTO x2 SELECT a_string(600), a_string(400), a_string(500) FROM x2;
2089d0b0d4dcSdan    INSERT INTO x2 SELECT a_string(500), a_string(600), a_string(400) FROM x2;
2090d0b0d4dcSdan    INSERT INTO x2 SELECT a_string(400), a_string(500), a_string(600) FROM x2;
2091d0b0d4dcSdan    INSERT INTO x1 SELECT * FROM x2;
2092d0b0d4dcSdan  }
2093d0b0d4dcSdan} {}
2094d0b0d4dcSdando_test pager1-24.1.2 {
2095d0b0d4dcSdan  execsql {
2096d0b0d4dcSdan    BEGIN;
2097d0b0d4dcSdan      DELETE FROM x1 WHERE rowid<32;
2098d0b0d4dcSdan  }
2099*c396d4afSdan  recursive_select 64 x2
2100d0b0d4dcSdan} {}
2101d0b0d4dcSdando_test pager1-24.1.3 {
2102d0b0d4dcSdan  execsql {
2103d0b0d4dcSdan      UPDATE x1 SET z = a_string(300) WHERE rowid>40;
2104d0b0d4dcSdan    COMMIT;
2105d0b0d4dcSdan    PRAGMA integrity_check;
2106d0b0d4dcSdan    SELECT count(*) FROM x1;
2107d0b0d4dcSdan  }
2108d0b0d4dcSdan} {ok 33}
2109d0b0d4dcSdan
2110d0b0d4dcSdando_test pager1-24.1.4 {
2111d0b0d4dcSdan  execsql {
2112d0b0d4dcSdan    DELETE FROM x1;
2113d0b0d4dcSdan    INSERT INTO x1 SELECT * FROM x2;
2114d0b0d4dcSdan    BEGIN;
2115d0b0d4dcSdan      DELETE FROM x1 WHERE rowid<32;
2116d0b0d4dcSdan      UPDATE x1 SET z = a_string(299) WHERE rowid>40;
2117d0b0d4dcSdan  }
2118*c396d4afSdan  recursive_select 64 x2 {db eval COMMIT}
2119d0b0d4dcSdan  execsql {
2120d0b0d4dcSdan    PRAGMA integrity_check;
2121d0b0d4dcSdan    SELECT count(*) FROM x1;
2122d0b0d4dcSdan  }
2123d0b0d4dcSdan} {ok 33}
2124d0b0d4dcSdan
2125d0b0d4dcSdando_test pager1-24.1.5 {
2126d0b0d4dcSdan  execsql {
2127d0b0d4dcSdan    DELETE FROM x1;
2128d0b0d4dcSdan    INSERT INTO x1 SELECT * FROM x2;
2129d0b0d4dcSdan  }
2130*c396d4afSdan  recursive_select 64 x2 { db eval {CREATE TABLE x3(x, y, z)} }
2131d0b0d4dcSdan  execsql { SELECT * FROM x3 }
2132d0b0d4dcSdan} {}
2133d0b0d4dcSdan
2134d0b0d4dcSdan#-------------------------------------------------------------------------
2135d0b0d4dcSdan#
2136d0b0d4dcSdando_test pager1-25-1 {
2137d0b0d4dcSdan  faultsim_delete_and_reopen
2138d0b0d4dcSdan  execsql {
2139d0b0d4dcSdan    BEGIN;
2140d0b0d4dcSdan      SAVEPOINT abc;
2141d0b0d4dcSdan        CREATE TABLE t1(a, b);
2142d0b0d4dcSdan      ROLLBACK TO abc;
2143d0b0d4dcSdan    COMMIT;
2144d0b0d4dcSdan  }
2145d0b0d4dcSdan  db close
2146d0b0d4dcSdan} {}
2147d0b0d4dcSdanbreakpoint
2148d0b0d4dcSdando_test pager1-25-2 {
2149d0b0d4dcSdan  faultsim_delete_and_reopen
2150d0b0d4dcSdan  execsql {
2151d0b0d4dcSdan    SAVEPOINT abc;
2152d0b0d4dcSdan      CREATE TABLE t1(a, b);
2153d0b0d4dcSdan    ROLLBACK TO abc;
2154d0b0d4dcSdan    COMMIT;
2155d0b0d4dcSdan  }
2156d0b0d4dcSdan  db close
2157d0b0d4dcSdan} {}
21586b63ab47Sdan
2159*c396d4afSdan#-------------------------------------------------------------------------
2160*c396d4afSdan# Sector-size tests.
2161*c396d4afSdan#
2162*c396d4afSdando_test pager1-26.1 {
2163*c396d4afSdan  testvfs tv -default 1
2164*c396d4afSdan  tv sectorsize 4096
2165*c396d4afSdan  faultsim_delete_and_reopen
2166*c396d4afSdan  db func a_string a_string
2167*c396d4afSdan  execsql {
2168*c396d4afSdan    PRAGMA page_size = 512;
2169*c396d4afSdan    CREATE TABLE tbl(a PRIMARY KEY, b UNIQUE);
2170*c396d4afSdan    BEGIN;
2171*c396d4afSdan      INSERT INTO tbl VALUES(a_string(25), a_string(600));
2172*c396d4afSdan      INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl;
2173*c396d4afSdan      INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl;
2174*c396d4afSdan      INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl;
2175*c396d4afSdan      INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl;
2176*c396d4afSdan      INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl;
2177*c396d4afSdan      INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl;
2178*c396d4afSdan      INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl;
2179*c396d4afSdan    COMMIT;
2180*c396d4afSdan  }
2181*c396d4afSdan} {}
2182*c396d4afSdando_execsql_test pager1-26.1 {
2183*c396d4afSdan  UPDATE tbl SET b = a_string(550);
2184*c396d4afSdan} {}
2185*c396d4afSdandb close
2186*c396d4afSdantv delete
2187*c396d4afSdan
2188*c396d4afSdan#-------------------------------------------------------------------------
2189*c396d4afSdando_test pager1.27.1 {
2190*c396d4afSdan  faultsim_delete_and_reopen
2191*c396d4afSdan  sqlite3_pager_refcounts db
2192*c396d4afSdan  execsql {
2193*c396d4afSdan    BEGIN;
2194*c396d4afSdan      CREATE TABLE t1(a, b);
2195*c396d4afSdan  }
2196*c396d4afSdan  sqlite3_pager_refcounts db
2197*c396d4afSdan  execsql COMMIT
2198*c396d4afSdan} {}
2199*c396d4afSdan
2200d353331aSdanfinish_test
2201