xref: /sqlite-3.40.0/test/pager1.test (revision 146ed78b)
1e91a54e1Sdan# 2010 June 15
2e91a54e1Sdan#
3e91a54e1Sdan# The author disclaims copyright to this source code.  In place of
4e91a54e1Sdan# a legal notice, here is a blessing:
5e91a54e1Sdan#
6e91a54e1Sdan#    May you do good and not evil.
7e91a54e1Sdan#    May you find forgiveness for yourself and forgive others.
8e91a54e1Sdan#    May you share freely, never taking more than you give.
9e91a54e1Sdan#
10e91a54e1Sdan#***********************************************************************
11e91a54e1Sdan#
12e91a54e1Sdan
13e91a54e1Sdanset testdir [file dirname $argv0]
14e91a54e1Sdansource $testdir/tester.tcl
15e91a54e1Sdansource $testdir/lock_common.tcl
16e91a54e1Sdansource $testdir/malloc_common.tcl
17e91a54e1Sdan
18b0ac3e3aSdan#
19b0ac3e3aSdan# pager1-1.*: Test inter-process locking (clients in multiple processes).
20b0ac3e3aSdan#
21b0ac3e3aSdan# pager1-2.*: Test intra-process locking (multiple clients in this process).
22b0ac3e3aSdan#
23b0ac3e3aSdan# pager1-3.*: Savepoint related tests.
24b0ac3e3aSdan#
251f4cb65aSdan# pager1-4.*: Hot-journal related tests.
261f4cb65aSdan#
27de4996e2Sdan# pager1-5.*: Cases related to multi-file commits.
28de4996e2Sdan#
29*146ed78bSdan# pager1-6.*: Cases related to "PRAGMA max_page_count"
30*146ed78bSdan#
31b0ac3e3aSdan
32b0ac3e3aSdanproc do_execsql_test {testname sql result} {
33b0ac3e3aSdan  uplevel do_test $testname [list "execsql {$sql}"] [list $result]
34b0ac3e3aSdan}
35b0ac3e3aSdanproc do_catchsql_test {testname sql result} {
36b0ac3e3aSdan  uplevel do_test $testname [list "catchsql {$sql}"] [list $result]
37b0ac3e3aSdan}
38b0ac3e3aSdan
3953f04f3bSdanset a_string_counter 1
4053f04f3bSdanproc a_string {n} {
4153f04f3bSdan  global a_string_counter
4253f04f3bSdan  incr a_string_counter
4353f04f3bSdan  string range [string repeat "${a_string_counter}." $n] 1 $n
4453f04f3bSdan}
4553f04f3bSdandb func a_string a_string
4653f04f3bSdan
47a4a9095eSdando_multiclient_test tn {
48e91a54e1Sdan
49e91a54e1Sdan  # Create and populate a database table using connection [db]. Check
50e91a54e1Sdan  # that connections [db2] and [db3] can see the schema and content.
51e91a54e1Sdan  #
52e91a54e1Sdan  do_test pager1-$tn.1 {
53e91a54e1Sdan    sql1 {
54e91a54e1Sdan      CREATE TABLE t1(a PRIMARY KEY, b);
55e91a54e1Sdan      CREATE INDEX i1 ON t1(b);
56e91a54e1Sdan      INSERT INTO t1 VALUES(1, 'one');
57e91a54e1Sdan      INSERT INTO t1 VALUES(2, 'two');
58e91a54e1Sdan    }
59e91a54e1Sdan  } {}
60e91a54e1Sdan  do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
61e91a54e1Sdan  do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two}
62e91a54e1Sdan
63e91a54e1Sdan  # Open a transaction and add a row using [db]. This puts [db] in
64e91a54e1Sdan  # RESERVED state. Check that connections [db2] and [db3] can still
65e91a54e1Sdan  # read the database content as it was before the transaction was
66e91a54e1Sdan  # opened. [db] should see the inserted row.
67e91a54e1Sdan  #
68e91a54e1Sdan  do_test pager1-$tn.4 {
69e91a54e1Sdan    sql1 {
70e91a54e1Sdan      BEGIN;
71e91a54e1Sdan        INSERT INTO t1 VALUES(3, 'three');
72e91a54e1Sdan    }
73e91a54e1Sdan  } {}
74e91a54e1Sdan  do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
75e91a54e1Sdan  do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three}
76e91a54e1Sdan
77e91a54e1Sdan  # [db] still has an open write transaction. Check that this prevents
78e91a54e1Sdan  # other connections (specifically [db2]) from writing to the database.
79e91a54e1Sdan  #
80e91a54e1Sdan  # Even if [db2] opens a transaction first, it may not write to the
81e91a54e1Sdan  # database. After the attempt to write the db within a transaction,
82e91a54e1Sdan  # [db2] is left with an open transaction, but not a read-lock on
83e91a54e1Sdan  # the main database. So it does not prevent [db] from committing.
84e91a54e1Sdan  #
85e91a54e1Sdan  do_test pager1-$tn.8 {
86e91a54e1Sdan    csql2 { UPDATE t1 SET a = a + 10 }
87e91a54e1Sdan  } {1 {database is locked}}
88e91a54e1Sdan  do_test pager1-$tn.9 {
89e91a54e1Sdan    csql2 {
90e91a54e1Sdan      BEGIN;
91e91a54e1Sdan      UPDATE t1 SET a = a + 10;
92e91a54e1Sdan    }
93e91a54e1Sdan  } {1 {database is locked}}
94e91a54e1Sdan
95e91a54e1Sdan  # Have [db] commit its transactions. Check the other connections can
96e91a54e1Sdan  # now see the new database content.
97e91a54e1Sdan  #
98e91a54e1Sdan  do_test pager1-$tn.10 { sql1 { COMMIT } } {}
99e91a54e1Sdan  do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three}
100e91a54e1Sdan  do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three}
101e91a54e1Sdan  do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
102e91a54e1Sdan
103e91a54e1Sdan  # Check that, as noted above, [db2] really did keep an open transaction
104e91a54e1Sdan  # after the attempt to write the database failed.
105e91a54e1Sdan  #
106e91a54e1Sdan  do_test pager1-$tn.14 {
107e91a54e1Sdan    csql2 { BEGIN }
108e91a54e1Sdan  } {1 {cannot start a transaction within a transaction}}
109e91a54e1Sdan  do_test pager1-$tn.15 { sql2 { ROLLBACK } } {}
110e91a54e1Sdan
111e91a54e1Sdan  # Have [db2] open a transaction and take a read-lock on the database.
112e91a54e1Sdan  # Check that this prevents [db] from writing to the database (outside
113e91a54e1Sdan  # of any transaction). After this fails, check that [db3] can read
114e91a54e1Sdan  # the db (showing that [db] did not take a PENDING lock etc.)
115e91a54e1Sdan  #
116e91a54e1Sdan  do_test pager1-$tn.15 {
117e91a54e1Sdan    sql2 { BEGIN; SELECT * FROM t1; }
118e91a54e1Sdan  } {1 one 2 two 3 three}
119e91a54e1Sdan  do_test pager1-$tn.16 {
120e91a54e1Sdan    csql1 { UPDATE t1 SET a = a + 10 }
121e91a54e1Sdan  } {1 {database is locked}}
122e91a54e1Sdan  do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
123e91a54e1Sdan
124e91a54e1Sdan  # This time, have [db] open a transaction before writing the database.
125e91a54e1Sdan  # This works - [db] gets a RESERVED lock which does not conflict with
126e91a54e1Sdan  # the SHARED lock [db2] is holding.
127e91a54e1Sdan  #
128e91a54e1Sdan  do_test pager1-$tn.18 {
129e91a54e1Sdan    sql1 {
130e91a54e1Sdan      BEGIN;
131e91a54e1Sdan      UPDATE t1 SET a = a + 10;
132e91a54e1Sdan    }
133e91a54e1Sdan  } {}
134e91a54e1Sdan  do_test pager1-$tn-19 {
135e91a54e1Sdan    sql1 { PRAGMA lock_status }
136e91a54e1Sdan  } {main reserved temp closed}
137e91a54e1Sdan  do_test pager1-$tn-20 {
138e91a54e1Sdan    sql2 { PRAGMA lock_status }
139e91a54e1Sdan  } {main shared temp closed}
140e91a54e1Sdan
141e91a54e1Sdan  # Check that all connections can still read the database. Only [db] sees
142e91a54e1Sdan  # the updated content (as the transaction has not been committed yet).
143e91a54e1Sdan  #
144e91a54e1Sdan  do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three}
145e91a54e1Sdan  do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three}
146e91a54e1Sdan  do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
147e91a54e1Sdan
148e91a54e1Sdan  # Because [db2] still has the SHARED lock, [db] is unable to commit the
149e91a54e1Sdan  # transaction. If it tries, an error is returned and the connection
150e91a54e1Sdan  # upgrades to a PENDING lock.
151e91a54e1Sdan  #
152e91a54e1Sdan  # Once this happens, [db] can read the database and see the new content,
153e91a54e1Sdan  # [db2] (still holding SHARED) can still read the old content, but [db3]
154e91a54e1Sdan  # (not holding any lock) is prevented by [db]'s PENDING from reading
155e91a54e1Sdan  # the database.
156e91a54e1Sdan  #
157e91a54e1Sdan  do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}}
158e91a54e1Sdan  do_test pager1-$tn-25 {
159e91a54e1Sdan    sql1 { PRAGMA lock_status }
160e91a54e1Sdan  } {main pending temp closed}
161e91a54e1Sdan  do_test pager1-$tn.26 { sql1 { SELECT * FROM t1  } } {11 one 12 two 13 three}
162e91a54e1Sdan  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1  } } {1 one 2 two 3 three}
163e91a54e1Sdan  do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}}
164e91a54e1Sdan
165e91a54e1Sdan  # Have [db2] commit its read transaction, releasing the SHARED lock it
166e91a54e1Sdan  # is holding. Now, neither [db2] nor [db3] may read the database (as [db]
167e91a54e1Sdan  # is still holding a PENDING).
168e91a54e1Sdan  #
169e91a54e1Sdan  do_test pager1-$tn.29 { sql2 { COMMIT } } {}
170e91a54e1Sdan  do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}}
171e91a54e1Sdan  do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}}
172e91a54e1Sdan
173e91a54e1Sdan  # [db] is now able to commit the transaction. Once the transaction is
174e91a54e1Sdan  # committed, all three connections can read the new content.
175e91a54e1Sdan  #
176e91a54e1Sdan  do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {}
177e91a54e1Sdan  do_test pager1-$tn.26 { sql1 { COMMIT } } {}
178e91a54e1Sdan  do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three}
179e91a54e1Sdan  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three}
180e91a54e1Sdan  do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three}
181e91a54e1Sdan}
182e91a54e1Sdan
18353f04f3bSdan#-------------------------------------------------------------------------
18453f04f3bSdan# Savepoint related test cases.
18553f04f3bSdan#
186b0ac3e3aSdando_test pager1-3.1 {
187b0ac3e3aSdan  faultsim_delete_and_reopen
188b0ac3e3aSdan  execsql {
189b0ac3e3aSdan    CREATE TABLE t1(a PRIMARY KEY, b);
190b0ac3e3aSdan    CREATE TABLE counter(
191b0ac3e3aSdan      i CHECK (i<5),
192b0ac3e3aSdan      u CHECK (u<10)
193b0ac3e3aSdan    );
194b0ac3e3aSdan    INSERT INTO counter VALUES(0, 0);
195b0ac3e3aSdan    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
196b0ac3e3aSdan      UPDATE counter SET i = i+1;
197b0ac3e3aSdan    END;
198b0ac3e3aSdan    CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN
199b0ac3e3aSdan      UPDATE counter SET u = u+1;
200b0ac3e3aSdan    END;
201b0ac3e3aSdan  }
202b0ac3e3aSdan  execsql { SELECT * FROM counter }
203b0ac3e3aSdan} {0 0}
204b0ac3e3aSdan
205b0ac3e3aSdando_execsql_test pager1-3.2 {
206b0ac3e3aSdan  BEGIN;
207b0ac3e3aSdan    INSERT INTO t1 VALUES(1, randomblob(1500));
208b0ac3e3aSdan    INSERT INTO t1 VALUES(2, randomblob(1500));
209b0ac3e3aSdan    INSERT INTO t1 VALUES(3, randomblob(1500));
210b0ac3e3aSdan    SELECT * FROM counter;
211b0ac3e3aSdan} {3 0}
212b0ac3e3aSdando_catchsql_test pager1-3.3 {
213b0ac3e3aSdan    INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1
214b0ac3e3aSdan} {1 {constraint failed}}
215b0ac3e3aSdando_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0}
216b0ac3e3aSdando_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3}
217b0ac3e3aSdando_execsql_test pager1-3.6 { COMMIT } {}
218b0ac3e3aSdan
219de4996e2Sdanset otn 0
2201f4cb65aSdantestvfs tv -default 1
2211f4cb65aSdanforeach code [list {
2221f4cb65aSdan  set s 512
2231f4cb65aSdan} {
2241f4cb65aSdan  set s 1024
2251f4cb65aSdan  set sql { PRAGMA journal_mode = memory }
2261f4cb65aSdan} {
227*146ed78bSdan  set s 1024
228*146ed78bSdan  set sql {
229*146ed78bSdan    PRAGMA journal_mode = memory;
230*146ed78bSdan    PRAGMA locking_mode = exclusive;
231*146ed78bSdan  }
232*146ed78bSdan} {
2331f4cb65aSdan  set s 2048
2341f4cb65aSdan  tv devchar safe_append
2351f4cb65aSdan} {
2361f4cb65aSdan  set s 4096
237de4996e2Sdan} {
238de4996e2Sdan  set s 4096
2391f4cb65aSdan  set sql { PRAGMA journal_mode = WAL }
240de4996e2Sdan} {
241de4996e2Sdan  set s 8192
242de4996e2Sdan  set sql { PRAGMA synchronous = off }
2431f4cb65aSdan}] {
244de4996e2Sdan
245de4996e2Sdan  incr otn
246de4996e2Sdan  set sql ""
247de4996e2Sdan  tv devchar {}
2481f4cb65aSdan  eval $code
2491f4cb65aSdan  tv sectorsize $s
2501f4cb65aSdan
251de4996e2Sdan  do_test pager1-3.7.$otn.0 {
2521f4cb65aSdan    faultsim_delete_and_reopen
2531f4cb65aSdan    execsql $sql
2541f4cb65aSdan    execsql {
2551f4cb65aSdan      PRAGMA cache_size = 10;
2561f4cb65aSdan      CREATE TABLE t1(i INTEGER PRIMARY KEY, j blob);
2571f4cb65aSdan    }
2581f4cb65aSdan  } {}
2591f4cb65aSdan
2601f4cb65aSdan  set tn 0
2611f4cb65aSdan  set lowpoint 0
2621f4cb65aSdan  foreach x {
263de4996e2Sdan    100 x 0 100
264de4996e2Sdan  x
2651f4cb65aSdan    70 22 96 59 96 50 22 56 21 16 37 64 43 40  0 38 22 38 55  0  6
2661f4cb65aSdan    43 62 32 93 54 18 13 29 45 66 29 25 61 31 53 82 75 25 96 86 10 69
2671f4cb65aSdan     2 29  6 60 80 95 42 82 85 50 68 96 90 39 78 69 87 97 48 74 65 43
2681f4cb65aSdan  x
2691f4cb65aSdan    86 34 26 50 41 85 58 44 89 22  6 51 45 46 58 32 97  6  1 12 32  2
2701f4cb65aSdan    69 39 48 71 33 31  5 58 90 43 24 54 12  9 18 57  4 38 91 42 27 45
2711f4cb65aSdan    50 38 56 29 10  0 26 37 83  1 78 15 47 30 75 62 46 29 68  5 30  4
2721f4cb65aSdan    27 96 33 95 79 75 56 10 29 70 32 75 52 88  5 36 50 57 46 63 88 65
2731f4cb65aSdan  x
2741f4cb65aSdan    44 95 64 20 24 35 69 61 61  2 35 92 42 46 23 98 78  1 38 72 79 35
2751f4cb65aSdan    94 37 13 59  5 93 27 58 80 75 58  7 67 13 10 76 84  4  8 70 81 45
2761f4cb65aSdan     8 41 98  5 60 26 92 29 91 90  2 62 40  4  5 22 80 15 83 76 52 88
2771f4cb65aSdan    29  5 68 73 72  7 54 17 89 32 81 94 51 28 53 71  8 42 54 59 70 79
2781f4cb65aSdan  x
2791f4cb65aSdan  } {
2801f4cb65aSdan    incr tn
2811f4cb65aSdan    set now [db one {SELECT count(i) FROM t1}]
2821f4cb65aSdan    if {$x == "x"} {
2831f4cb65aSdan      execsql { COMMIT ; BEGIN }
2841f4cb65aSdan      set lowpoint $now
285de4996e2Sdan      do_test pager1.3.7.$otn.$tn {
2861f4cb65aSdan        sqlite3 db2 test.db
2871f4cb65aSdan        execsql {
2881f4cb65aSdan          SELECT COALESCE(max(i), 0) FROM t1;
2891f4cb65aSdan          PRAGMA integrity_check;
2901f4cb65aSdan        }
2911f4cb65aSdan      } [list $lowpoint ok]
2921f4cb65aSdan      db2 close
2931f4cb65aSdan    } else {
2941f4cb65aSdan      if {$now > $x } {
2951f4cb65aSdan        if { $x>=$lowpoint } {
2961f4cb65aSdan          execsql "ROLLBACK TO sp_$x"
2971f4cb65aSdan        } else {
2981f4cb65aSdan          execsql "DELETE FROM t1 WHERE i>$x"
2991f4cb65aSdan          set lowpoint $x
3001f4cb65aSdan        }
3011f4cb65aSdan      } elseif {$now < $x} {
3021f4cb65aSdan        for {set k $now} {$k < $x} {incr k} {
3031f4cb65aSdan          execsql "SAVEPOINT sp_$k"
3041f4cb65aSdan          execsql { INSERT INTO t1(j) VALUES(randomblob(1500)) }
3051f4cb65aSdan        }
3061f4cb65aSdan      }
307de4996e2Sdan      do_execsql_test pager1.3.7.$otn.$tn {
3081f4cb65aSdan        SELECT COALESCE(max(i), 0) FROM t1;
3091f4cb65aSdan        PRAGMA integrity_check;
3101f4cb65aSdan      } [list $x ok]
3111f4cb65aSdan    }
3121f4cb65aSdan  }
3131f4cb65aSdan}
3141f4cb65aSdandb close
3151f4cb65aSdantv delete
3161f4cb65aSdan
31753f04f3bSdan#-------------------------------------------------------------------------
31853f04f3bSdan# Hot journal rollback related test cases.
31953f04f3bSdan#
32053f04f3bSdan# pager1.4.1.*: Test that the pager module deletes very small invalid
32153f04f3bSdan#               journal files.
32253f04f3bSdan#
32353f04f3bSdan# pager1.4.2.*: Test that if the master journal pointer at the end of a
32453f04f3bSdan#               hot-journal file appears to be corrupt (checksum does not
32553f04f3bSdan#               compute) the associated journal is rolled back (and no
32653f04f3bSdan#               xAccess() call to check for the presence of any master
32753f04f3bSdan#               journal file is made).
32853f04f3bSdan#
329de4996e2Sdan# pager1.4.3.*: Test that the contents of a hot-journal are ignored if the
330de4996e2Sdan#               page-size or sector-size in the journal header appear to
331de4996e2Sdan#               be invalid (too large, too small or not a power of 2).
332de4996e2Sdan#
33353f04f3bSdando_test pager1.4.1.1 {
33453f04f3bSdan  faultsim_delete_and_reopen
33553f04f3bSdan  execsql {
33653f04f3bSdan    CREATE TABLE x(y, z);
33753f04f3bSdan    INSERT INTO x VALUES(1, 2);
33853f04f3bSdan  }
33953f04f3bSdan  set fd [open test.db-journal w]
34053f04f3bSdan  puts -nonewline $fd "helloworld"
34153f04f3bSdan  close $fd
34253f04f3bSdan  file exists test.db-journal
34353f04f3bSdan} {1}
34453f04f3bSdando_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2}
34553f04f3bSdando_test pager1.4.1.3 { file exists test.db-journal } {0}
34653f04f3bSdan
34753f04f3bSdan# Set up a [testvfs] to snapshot the file-system just before SQLite
34853f04f3bSdan# deletes the master-journal to commit a multi-file transaction.
34953f04f3bSdan#
35053f04f3bSdan# In subsequent test cases, invoking [faultsim_restore_and_reopen] sets
35153f04f3bSdan# up the file system to contain two databases, two hot-journal files and
35253f04f3bSdan# a master-journal.
35353f04f3bSdan#
35453f04f3bSdando_test pager1.4.2.1 {
35553f04f3bSdan  testvfs tstvfs -default 1
35653f04f3bSdan  tstvfs filter xDelete
35753f04f3bSdan  tstvfs script xDeleteCallback
35853f04f3bSdan  proc xDeleteCallback {method file args} {
35953f04f3bSdan    set file [file tail $file]
36053f04f3bSdan    if { [string match *mj* $file] } { faultsim_save }
36153f04f3bSdan  }
36253f04f3bSdan  faultsim_delete_and_reopen
36353f04f3bSdan  db func a_string a_string
36453f04f3bSdan  execsql {
36553f04f3bSdan    ATTACH 'test.db2' AS aux;
36653f04f3bSdan    PRAGMA journal_mode = DELETE;
36753f04f3bSdan    PRAGMA main.cache_size = 10;
36853f04f3bSdan    PRAGMA aux.cache_size = 10;
36953f04f3bSdan    CREATE TABLE t1(a UNIQUE, b UNIQUE);
37053f04f3bSdan    CREATE TABLE aux.t2(a UNIQUE, b UNIQUE);
37153f04f3bSdan    INSERT INTO t1 VALUES(a_string(200), a_string(300));
37253f04f3bSdan    INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
37353f04f3bSdan    INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
37453f04f3bSdan    INSERT INTO t2 SELECT * FROM t1;
37553f04f3bSdan    BEGIN;
37653f04f3bSdan      INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
37753f04f3bSdan      INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
37853f04f3bSdan      INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
37953f04f3bSdan      INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
38053f04f3bSdan      REPLACE INTO t2 SELECT * FROM t1;
38153f04f3bSdan    COMMIT;
38253f04f3bSdan  }
38353f04f3bSdan  db close
38453f04f3bSdan  tstvfs delete
38553f04f3bSdan} {}
38653f04f3bSdando_test pager1.4.2.2 {
38753f04f3bSdan  faultsim_restore_and_reopen
38853f04f3bSdan  execsql {
38953f04f3bSdan    SELECT count(*) FROM t1;
39053f04f3bSdan    PRAGMA integrity_check;
39153f04f3bSdan  }
39253f04f3bSdan} {4 ok}
39353f04f3bSdando_test pager1.4.2.3 {
39453f04f3bSdan  faultsim_restore_and_reopen
39553f04f3bSdan  foreach f [glob test.db-mj*] { file delete -force $f }
39653f04f3bSdan  execsql {
39753f04f3bSdan    SELECT count(*) FROM t1;
39853f04f3bSdan    PRAGMA integrity_check;
39953f04f3bSdan  }
40053f04f3bSdan} {64 ok}
40153f04f3bSdando_test pager1.4.2.4 {
40253f04f3bSdan  faultsim_restore_and_reopen
40353f04f3bSdan  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
40453f04f3bSdan  execsql {
40553f04f3bSdan    SELECT count(*) FROM t1;
40653f04f3bSdan    PRAGMA integrity_check;
40753f04f3bSdan  }
40853f04f3bSdan} {4 ok}
40953f04f3bSdando_test pager1.4.2.5 {
41053f04f3bSdan  faultsim_restore_and_reopen
41153f04f3bSdan  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
41253f04f3bSdan  foreach f [glob test.db-mj*] { file delete -force $f }
41353f04f3bSdan  execsql {
41453f04f3bSdan    SELECT count(*) FROM t1;
41553f04f3bSdan    PRAGMA integrity_check;
41653f04f3bSdan  }
41753f04f3bSdan} {4 ok}
41853f04f3bSdan
419de4996e2Sdando_test pager1.4.3.1 {
420de4996e2Sdan  testvfs tstvfs -default 1
421de4996e2Sdan  tstvfs filter xSync
422de4996e2Sdan  tstvfs script xSyncCallback
423de4996e2Sdan  proc xSyncCallback {method file args} {
424de4996e2Sdan    set file [file tail $file]
425de4996e2Sdan    if { 0==[string match *journal $file] } { faultsim_save }
426de4996e2Sdan  }
427de4996e2Sdan  faultsim_delete_and_reopen
428de4996e2Sdan  execsql {
429de4996e2Sdan    PRAGMA journal_mode = DELETE;
430de4996e2Sdan    CREATE TABLE t1(a, b);
431de4996e2Sdan    INSERT INTO t1 VALUES(1, 2);
432de4996e2Sdan    INSERT INTO t1 VALUES(3, 4);
433de4996e2Sdan  }
434de4996e2Sdan  db close
435de4996e2Sdan  tstvfs delete
436de4996e2Sdan} {}
437de4996e2Sdan
438de4996e2Sdanforeach {tn ofst value result} {
439de4996e2Sdan          2   20    31       {1 2 3 4}
440de4996e2Sdan          3   20    32       {1 2 3 4}
441de4996e2Sdan          4   20    33       {1 2 3 4}
442de4996e2Sdan          5   20    65536    {1 2 3 4}
443de4996e2Sdan          6   20    131072   {1 2 3 4}
444de4996e2Sdan
445de4996e2Sdan          7   24    511      {1 2 3 4}
446de4996e2Sdan          8   24    513      {1 2 3 4}
447de4996e2Sdan          9   24    65536    {1 2 3 4}
448de4996e2Sdan
449de4996e2Sdan         10   32    65536    {1 2}
450de4996e2Sdan} {
451de4996e2Sdan  do_test pager1.4.3.$tn {
452de4996e2Sdan    faultsim_restore_and_reopen
453de4996e2Sdan    hexio_write test.db-journal $ofst [format %.8x $value]
454de4996e2Sdan    execsql { SELECT * FROM t1 }
455de4996e2Sdan  } $result
456de4996e2Sdan}
457de4996e2Sdandb close
458de4996e2Sdan
459de4996e2Sdan#-------------------------------------------------------------------------
460*146ed78bSdan# The following tests deal with multi-file commits.
461de4996e2Sdan#
462*146ed78bSdan# pager1-5.1.*: The case where a multi-file cannot be committed because
463*146ed78bSdan#               another connection is holding a SHARED lock on one of the
464*146ed78bSdan#               files. After the SHARED lock is removed, the COMMIT succeeds.
465*146ed78bSdan#
466*146ed78bSdan# pager1-5.2.*: Multi-file commits with journal_mode=memory.
467*146ed78bSdan#
468*146ed78bSdan# pager1-5.3.*: Multi-file commits with journal_mode=memory.
469*146ed78bSdan#
470*146ed78bSdan# pager1-5.4.*: Check that with synchronous=normal, the master-journal file
471*146ed78bSdan#               name is added to a journal file immediately after the last
472*146ed78bSdan#               journal record. But with synchronous=full, extra unused space
473*146ed78bSdan#               is allocated between the last journal record and the
474*146ed78bSdan#               master-journal file name so that the master-journal file
475*146ed78bSdan#               name does not lie on the same sector as the last journal file
476*146ed78bSdan#               record.
477*146ed78bSdan#
478*146ed78bSdan# pager1-5.5.*:
479*146ed78bSdan#
480*146ed78bSdando_test pager1-5.1.1 {
481*146ed78bSdan  faultsim_delete_and_reopen
482*146ed78bSdan  execsql {
483*146ed78bSdan    ATTACH 'test.db2' AS aux;
484*146ed78bSdan    CREATE TABLE t1(a, b);
485*146ed78bSdan    CREATE TABLE aux.t2(a, b);
486*146ed78bSdan    INSERT INTO t1 VALUES(17, 'Lenin');
487*146ed78bSdan    INSERT INTO t1 VALUES(22, 'Stalin');
488*146ed78bSdan    INSERT INTO t1 VALUES(53, 'Khrushchev');
489*146ed78bSdan  }
490*146ed78bSdan} {}
491*146ed78bSdando_test pager1-5.1.2 {
492*146ed78bSdan  execsql {
493*146ed78bSdan    BEGIN;
494*146ed78bSdan      INSERT INTO t1 VALUES(64, 'Brezhnev');
495*146ed78bSdan      INSERT INTO t2 SELECT * FROM t1;
496*146ed78bSdan  }
497*146ed78bSdan  sqlite3 db2 test.db2
498*146ed78bSdan  execsql {
499*146ed78bSdan    BEGIN;
500*146ed78bSdan      SELECT * FROM t2;
501*146ed78bSdan  } db2
502*146ed78bSdan} {}
503*146ed78bSdando_test pager1-5.1.3 {
504*146ed78bSdan  catchsql COMMIT
505*146ed78bSdan} {1 {database is locked}}
506*146ed78bSdando_test pager1-5.1.4 {
507*146ed78bSdan  execsql COMMIT db2
508*146ed78bSdan  execsql COMMIT
509*146ed78bSdan  execsql { SELECT * FROM t2 } db2
510*146ed78bSdan} {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev}
511*146ed78bSdando_test pager1-5.1.5 {
512*146ed78bSdan  db2 close
513*146ed78bSdan} {}
514*146ed78bSdan
515*146ed78bSdando_test pager1-5.2.1 {
516*146ed78bSdan  execsql {
517*146ed78bSdan    PRAGMA journal_mode = memory;
518*146ed78bSdan    BEGIN;
519*146ed78bSdan      INSERT INTO t1 VALUES(84, 'Andropov');
520*146ed78bSdan      INSERT INTO t2 VALUES(84, 'Andropov');
521*146ed78bSdan    COMMIT;
522*146ed78bSdan  }
523*146ed78bSdan} {memory}
524*146ed78bSdando_test pager1-5.3.1 {
525*146ed78bSdan  execsql {
526*146ed78bSdan    PRAGMA journal_mode = off;
527*146ed78bSdan    BEGIN;
528*146ed78bSdan      INSERT INTO t1 VALUES(85, 'Gorbachev');
529*146ed78bSdan      INSERT INTO t2 VALUES(85, 'Gorbachev');
530*146ed78bSdan    COMMIT;
531*146ed78bSdan  }
532*146ed78bSdan} {off}
533*146ed78bSdan
534*146ed78bSdando_test pager1-5.4.1 {
535*146ed78bSdan  db close
536*146ed78bSdan  testvfs tv
537*146ed78bSdan  sqlite3 db test.db -vfs tv
538*146ed78bSdan  execsql { ATTACH 'test.db2' AS aux }
539*146ed78bSdan
540*146ed78bSdan  tv filter xDelete
541*146ed78bSdan  tv script max_journal_size
542*146ed78bSdan  tv sectorsize 512
543*146ed78bSdan  set ::max_journal 0
544*146ed78bSdan  proc max_journal_size {method args} {
545*146ed78bSdan    set sz 0
546*146ed78bSdan    catch { set sz [file size test.db-journal] }
547*146ed78bSdan    if {$sz > $::max_journal} {
548*146ed78bSdan      set ::max_journal $sz
549*146ed78bSdan    }
550*146ed78bSdan    return SQLITE_OK
551*146ed78bSdan  }
552*146ed78bSdan  execsql {
553*146ed78bSdan    PRAGMA journal_mode = DELETE;
554*146ed78bSdan    PRAGMA synchronous = NORMAL;
555*146ed78bSdan    BEGIN;
556*146ed78bSdan      INSERT INTO t1 VALUES(85, 'Gorbachev');
557*146ed78bSdan      INSERT INTO t2 VALUES(85, 'Gorbachev');
558*146ed78bSdan    COMMIT;
559*146ed78bSdan  }
560*146ed78bSdan  set ::max_journal
561*146ed78bSdan} [expr 2615+[string length [pwd]]]
562*146ed78bSdando_test pager1-5.4.2 {
563*146ed78bSdan  set ::max_journal 0
564*146ed78bSdan  execsql {
565*146ed78bSdan    PRAGMA synchronous = full;
566*146ed78bSdan    BEGIN;
567*146ed78bSdan      DELETE FROM t1 WHERE b = 'Lenin';
568*146ed78bSdan      DELETE FROM t2 WHERE b = 'Lenin';
569*146ed78bSdan    COMMIT;
570*146ed78bSdan  }
571*146ed78bSdan  set ::max_journal
572*146ed78bSdan} [expr 3111+[string length [pwd]]]
573*146ed78bSdandb close
574*146ed78bSdantv delete
575*146ed78bSdan
576*146ed78bSdando_test pager1-5.5.1 {
577*146ed78bSdan  sqlite3 db test.db
578*146ed78bSdan  execsql {
579*146ed78bSdan    ATTACH 'test.db2' AS aux;
580*146ed78bSdan    PRAGMA journal_mode = PERSIST;
581*146ed78bSdan    CREATE TABLE t3(a, b);
582*146ed78bSdan    INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1;
583*146ed78bSdan    UPDATE t3 SET b = randomblob(1500);
584*146ed78bSdan  }
585*146ed78bSdan  expr [file size test.db-journal] > 15000
586*146ed78bSdan} {1}
587*146ed78bSdando_test pager1-5.5.2 {
588*146ed78bSdan  execsql {
589*146ed78bSdan    PRAGMA synchronous = full;
590*146ed78bSdan    BEGIN;
591*146ed78bSdan      DELETE FROM t1 WHERE b = 'Stalin';
592*146ed78bSdan      DELETE FROM t2 WHERE b = 'Stalin';
593*146ed78bSdan    COMMIT;
594*146ed78bSdan  }
595*146ed78bSdan  file size test.db-journal
596*146ed78bSdan} {0}
597*146ed78bSdan
598*146ed78bSdan
599*146ed78bSdan#-------------------------------------------------------------------------
600*146ed78bSdan# The following tests work with "PRAGMA max_page_count"
601*146ed78bSdan#
602*146ed78bSdando_test pager1-6.1 {
603*146ed78bSdan  faultsim_delete_and_reopen
604*146ed78bSdan  execsql {
605*146ed78bSdan    PRAGMA max_page_count = 10;
606*146ed78bSdan    CREATE TABLE t2(a, b);
607*146ed78bSdan    CREATE TABLE t3(a, b);
608*146ed78bSdan    CREATE TABLE t4(a, b);
609*146ed78bSdan    CREATE TABLE t5(a, b);
610*146ed78bSdan    CREATE TABLE t6(a, b);
611*146ed78bSdan    CREATE TABLE t7(a, b);
612*146ed78bSdan    CREATE TABLE t8(a, b);
613*146ed78bSdan    CREATE TABLE t9(a, b);
614*146ed78bSdan    CREATE TABLE t10(a, b);
615*146ed78bSdan  }
616*146ed78bSdan} {10}
617*146ed78bSdando_test pager1-6.2 {
618*146ed78bSdan  catchsql {
619*146ed78bSdan    CREATE TABLE t11(a, b);
620*146ed78bSdan  }
621*146ed78bSdan} {1 {database or disk is full}}
622de4996e2Sdan
623e91a54e1Sdanfinish_test
624e91a54e1Sdan
625