xref: /sqlite-3.40.0/test/pager1.test (revision 153eda0a)
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
17*153eda0aSdansource $testdir/wal_common.tcl
18e91a54e1Sdan
19b0ac3e3aSdan#
20b0ac3e3aSdan# pager1-1.*: Test inter-process locking (clients in multiple processes).
21b0ac3e3aSdan#
22b0ac3e3aSdan# pager1-2.*: Test intra-process locking (multiple clients in this process).
23b0ac3e3aSdan#
24b0ac3e3aSdan# pager1-3.*: Savepoint related tests.
25b0ac3e3aSdan#
261f4cb65aSdan# pager1-4.*: Hot-journal related tests.
271f4cb65aSdan#
28de4996e2Sdan# pager1-5.*: Cases related to multi-file commits.
29de4996e2Sdan#
30146ed78bSdan# pager1-6.*: Cases related to "PRAGMA max_page_count"
31146ed78bSdan#
32*153eda0aSdan# pager1-7.*: Cases specific to "PRAGMA journal_mode=TRUNCATE"
33*153eda0aSdan#
34b0ac3e3aSdan
3553f04f3bSdanset a_string_counter 1
3653f04f3bSdanproc a_string {n} {
3753f04f3bSdan  global a_string_counter
3853f04f3bSdan  incr a_string_counter
3953f04f3bSdan  string range [string repeat "${a_string_counter}." $n] 1 $n
4053f04f3bSdan}
4153f04f3bSdandb func a_string a_string
4253f04f3bSdan
43a4a9095eSdando_multiclient_test tn {
44e91a54e1Sdan
45e91a54e1Sdan  # Create and populate a database table using connection [db]. Check
46e91a54e1Sdan  # that connections [db2] and [db3] can see the schema and content.
47e91a54e1Sdan  #
48e91a54e1Sdan  do_test pager1-$tn.1 {
49e91a54e1Sdan    sql1 {
50e91a54e1Sdan      CREATE TABLE t1(a PRIMARY KEY, b);
51e91a54e1Sdan      CREATE INDEX i1 ON t1(b);
52e91a54e1Sdan      INSERT INTO t1 VALUES(1, 'one');
53e91a54e1Sdan      INSERT INTO t1 VALUES(2, 'two');
54e91a54e1Sdan    }
55e91a54e1Sdan  } {}
56e91a54e1Sdan  do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
57e91a54e1Sdan  do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two}
58e91a54e1Sdan
59e91a54e1Sdan  # Open a transaction and add a row using [db]. This puts [db] in
60e91a54e1Sdan  # RESERVED state. Check that connections [db2] and [db3] can still
61e91a54e1Sdan  # read the database content as it was before the transaction was
62e91a54e1Sdan  # opened. [db] should see the inserted row.
63e91a54e1Sdan  #
64e91a54e1Sdan  do_test pager1-$tn.4 {
65e91a54e1Sdan    sql1 {
66e91a54e1Sdan      BEGIN;
67e91a54e1Sdan        INSERT INTO t1 VALUES(3, 'three');
68e91a54e1Sdan    }
69e91a54e1Sdan  } {}
70e91a54e1Sdan  do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
71e91a54e1Sdan  do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three}
72e91a54e1Sdan
73e91a54e1Sdan  # [db] still has an open write transaction. Check that this prevents
74e91a54e1Sdan  # other connections (specifically [db2]) from writing to the database.
75e91a54e1Sdan  #
76e91a54e1Sdan  # Even if [db2] opens a transaction first, it may not write to the
77e91a54e1Sdan  # database. After the attempt to write the db within a transaction,
78e91a54e1Sdan  # [db2] is left with an open transaction, but not a read-lock on
79e91a54e1Sdan  # the main database. So it does not prevent [db] from committing.
80e91a54e1Sdan  #
81e91a54e1Sdan  do_test pager1-$tn.8 {
82e91a54e1Sdan    csql2 { UPDATE t1 SET a = a + 10 }
83e91a54e1Sdan  } {1 {database is locked}}
84e91a54e1Sdan  do_test pager1-$tn.9 {
85e91a54e1Sdan    csql2 {
86e91a54e1Sdan      BEGIN;
87e91a54e1Sdan      UPDATE t1 SET a = a + 10;
88e91a54e1Sdan    }
89e91a54e1Sdan  } {1 {database is locked}}
90e91a54e1Sdan
91e91a54e1Sdan  # Have [db] commit its transactions. Check the other connections can
92e91a54e1Sdan  # now see the new database content.
93e91a54e1Sdan  #
94e91a54e1Sdan  do_test pager1-$tn.10 { sql1 { COMMIT } } {}
95e91a54e1Sdan  do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three}
96e91a54e1Sdan  do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three}
97e91a54e1Sdan  do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
98e91a54e1Sdan
99e91a54e1Sdan  # Check that, as noted above, [db2] really did keep an open transaction
100e91a54e1Sdan  # after the attempt to write the database failed.
101e91a54e1Sdan  #
102e91a54e1Sdan  do_test pager1-$tn.14 {
103e91a54e1Sdan    csql2 { BEGIN }
104e91a54e1Sdan  } {1 {cannot start a transaction within a transaction}}
105e91a54e1Sdan  do_test pager1-$tn.15 { sql2 { ROLLBACK } } {}
106e91a54e1Sdan
107e91a54e1Sdan  # Have [db2] open a transaction and take a read-lock on the database.
108e91a54e1Sdan  # Check that this prevents [db] from writing to the database (outside
109e91a54e1Sdan  # of any transaction). After this fails, check that [db3] can read
110e91a54e1Sdan  # the db (showing that [db] did not take a PENDING lock etc.)
111e91a54e1Sdan  #
112e91a54e1Sdan  do_test pager1-$tn.15 {
113e91a54e1Sdan    sql2 { BEGIN; SELECT * FROM t1; }
114e91a54e1Sdan  } {1 one 2 two 3 three}
115e91a54e1Sdan  do_test pager1-$tn.16 {
116e91a54e1Sdan    csql1 { UPDATE t1 SET a = a + 10 }
117e91a54e1Sdan  } {1 {database is locked}}
118e91a54e1Sdan  do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
119e91a54e1Sdan
120e91a54e1Sdan  # This time, have [db] open a transaction before writing the database.
121e91a54e1Sdan  # This works - [db] gets a RESERVED lock which does not conflict with
122e91a54e1Sdan  # the SHARED lock [db2] is holding.
123e91a54e1Sdan  #
124e91a54e1Sdan  do_test pager1-$tn.18 {
125e91a54e1Sdan    sql1 {
126e91a54e1Sdan      BEGIN;
127e91a54e1Sdan      UPDATE t1 SET a = a + 10;
128e91a54e1Sdan    }
129e91a54e1Sdan  } {}
130e91a54e1Sdan  do_test pager1-$tn-19 {
131e91a54e1Sdan    sql1 { PRAGMA lock_status }
132e91a54e1Sdan  } {main reserved temp closed}
133e91a54e1Sdan  do_test pager1-$tn-20 {
134e91a54e1Sdan    sql2 { PRAGMA lock_status }
135e91a54e1Sdan  } {main shared temp closed}
136e91a54e1Sdan
137e91a54e1Sdan  # Check that all connections can still read the database. Only [db] sees
138e91a54e1Sdan  # the updated content (as the transaction has not been committed yet).
139e91a54e1Sdan  #
140e91a54e1Sdan  do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three}
141e91a54e1Sdan  do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three}
142e91a54e1Sdan  do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
143e91a54e1Sdan
144e91a54e1Sdan  # Because [db2] still has the SHARED lock, [db] is unable to commit the
145e91a54e1Sdan  # transaction. If it tries, an error is returned and the connection
146e91a54e1Sdan  # upgrades to a PENDING lock.
147e91a54e1Sdan  #
148e91a54e1Sdan  # Once this happens, [db] can read the database and see the new content,
149e91a54e1Sdan  # [db2] (still holding SHARED) can still read the old content, but [db3]
150e91a54e1Sdan  # (not holding any lock) is prevented by [db]'s PENDING from reading
151e91a54e1Sdan  # the database.
152e91a54e1Sdan  #
153e91a54e1Sdan  do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}}
154e91a54e1Sdan  do_test pager1-$tn-25 {
155e91a54e1Sdan    sql1 { PRAGMA lock_status }
156e91a54e1Sdan  } {main pending temp closed}
157e91a54e1Sdan  do_test pager1-$tn.26 { sql1 { SELECT * FROM t1  } } {11 one 12 two 13 three}
158e91a54e1Sdan  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1  } } {1 one 2 two 3 three}
159e91a54e1Sdan  do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}}
160e91a54e1Sdan
161e91a54e1Sdan  # Have [db2] commit its read transaction, releasing the SHARED lock it
162e91a54e1Sdan  # is holding. Now, neither [db2] nor [db3] may read the database (as [db]
163e91a54e1Sdan  # is still holding a PENDING).
164e91a54e1Sdan  #
165e91a54e1Sdan  do_test pager1-$tn.29 { sql2 { COMMIT } } {}
166e91a54e1Sdan  do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}}
167e91a54e1Sdan  do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}}
168e91a54e1Sdan
169e91a54e1Sdan  # [db] is now able to commit the transaction. Once the transaction is
170e91a54e1Sdan  # committed, all three connections can read the new content.
171e91a54e1Sdan  #
172e91a54e1Sdan  do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {}
173e91a54e1Sdan  do_test pager1-$tn.26 { sql1 { COMMIT } } {}
174e91a54e1Sdan  do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three}
175e91a54e1Sdan  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three}
176e91a54e1Sdan  do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three}
177e91a54e1Sdan}
178e91a54e1Sdan
17953f04f3bSdan#-------------------------------------------------------------------------
18053f04f3bSdan# Savepoint related test cases.
18153f04f3bSdan#
182b0ac3e3aSdando_test pager1-3.1 {
183b0ac3e3aSdan  faultsim_delete_and_reopen
184b0ac3e3aSdan  execsql {
185b0ac3e3aSdan    CREATE TABLE t1(a PRIMARY KEY, b);
186b0ac3e3aSdan    CREATE TABLE counter(
187b0ac3e3aSdan      i CHECK (i<5),
188b0ac3e3aSdan      u CHECK (u<10)
189b0ac3e3aSdan    );
190b0ac3e3aSdan    INSERT INTO counter VALUES(0, 0);
191b0ac3e3aSdan    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
192b0ac3e3aSdan      UPDATE counter SET i = i+1;
193b0ac3e3aSdan    END;
194b0ac3e3aSdan    CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN
195b0ac3e3aSdan      UPDATE counter SET u = u+1;
196b0ac3e3aSdan    END;
197b0ac3e3aSdan  }
198b0ac3e3aSdan  execsql { SELECT * FROM counter }
199b0ac3e3aSdan} {0 0}
200b0ac3e3aSdan
201b0ac3e3aSdando_execsql_test pager1-3.2 {
202b0ac3e3aSdan  BEGIN;
203b0ac3e3aSdan    INSERT INTO t1 VALUES(1, randomblob(1500));
204b0ac3e3aSdan    INSERT INTO t1 VALUES(2, randomblob(1500));
205b0ac3e3aSdan    INSERT INTO t1 VALUES(3, randomblob(1500));
206b0ac3e3aSdan    SELECT * FROM counter;
207b0ac3e3aSdan} {3 0}
208b0ac3e3aSdando_catchsql_test pager1-3.3 {
209b0ac3e3aSdan    INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1
210b0ac3e3aSdan} {1 {constraint failed}}
211b0ac3e3aSdando_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0}
212b0ac3e3aSdando_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3}
213b0ac3e3aSdando_execsql_test pager1-3.6 { COMMIT } {}
214b0ac3e3aSdan
21553f04f3bSdan#-------------------------------------------------------------------------
21653f04f3bSdan# Hot journal rollback related test cases.
21753f04f3bSdan#
21853f04f3bSdan# pager1.4.1.*: Test that the pager module deletes very small invalid
21953f04f3bSdan#               journal files.
22053f04f3bSdan#
22153f04f3bSdan# pager1.4.2.*: Test that if the master journal pointer at the end of a
22253f04f3bSdan#               hot-journal file appears to be corrupt (checksum does not
22353f04f3bSdan#               compute) the associated journal is rolled back (and no
22453f04f3bSdan#               xAccess() call to check for the presence of any master
22553f04f3bSdan#               journal file is made).
22653f04f3bSdan#
227de4996e2Sdan# pager1.4.3.*: Test that the contents of a hot-journal are ignored if the
228de4996e2Sdan#               page-size or sector-size in the journal header appear to
229de4996e2Sdan#               be invalid (too large, too small or not a power of 2).
230de4996e2Sdan#
23153f04f3bSdando_test pager1.4.1.1 {
23253f04f3bSdan  faultsim_delete_and_reopen
23353f04f3bSdan  execsql {
23453f04f3bSdan    CREATE TABLE x(y, z);
23553f04f3bSdan    INSERT INTO x VALUES(1, 2);
23653f04f3bSdan  }
23753f04f3bSdan  set fd [open test.db-journal w]
23853f04f3bSdan  puts -nonewline $fd "helloworld"
23953f04f3bSdan  close $fd
24053f04f3bSdan  file exists test.db-journal
24153f04f3bSdan} {1}
24253f04f3bSdando_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2}
24353f04f3bSdando_test pager1.4.1.3 { file exists test.db-journal } {0}
24453f04f3bSdan
24553f04f3bSdan# Set up a [testvfs] to snapshot the file-system just before SQLite
24653f04f3bSdan# deletes the master-journal to commit a multi-file transaction.
24753f04f3bSdan#
24853f04f3bSdan# In subsequent test cases, invoking [faultsim_restore_and_reopen] sets
24953f04f3bSdan# up the file system to contain two databases, two hot-journal files and
25053f04f3bSdan# a master-journal.
25153f04f3bSdan#
25253f04f3bSdando_test pager1.4.2.1 {
25353f04f3bSdan  testvfs tstvfs -default 1
25453f04f3bSdan  tstvfs filter xDelete
25553f04f3bSdan  tstvfs script xDeleteCallback
25653f04f3bSdan  proc xDeleteCallback {method file args} {
25753f04f3bSdan    set file [file tail $file]
25853f04f3bSdan    if { [string match *mj* $file] } { faultsim_save }
25953f04f3bSdan  }
26053f04f3bSdan  faultsim_delete_and_reopen
26153f04f3bSdan  db func a_string a_string
26253f04f3bSdan  execsql {
26353f04f3bSdan    ATTACH 'test.db2' AS aux;
26453f04f3bSdan    PRAGMA journal_mode = DELETE;
26553f04f3bSdan    PRAGMA main.cache_size = 10;
26653f04f3bSdan    PRAGMA aux.cache_size = 10;
26753f04f3bSdan    CREATE TABLE t1(a UNIQUE, b UNIQUE);
26853f04f3bSdan    CREATE TABLE aux.t2(a UNIQUE, b UNIQUE);
26953f04f3bSdan    INSERT INTO t1 VALUES(a_string(200), a_string(300));
27053f04f3bSdan    INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
27153f04f3bSdan    INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
27253f04f3bSdan    INSERT INTO t2 SELECT * FROM t1;
27353f04f3bSdan    BEGIN;
27453f04f3bSdan      INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
27553f04f3bSdan      INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
27653f04f3bSdan      INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
27753f04f3bSdan      INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
27853f04f3bSdan      REPLACE INTO t2 SELECT * FROM t1;
27953f04f3bSdan    COMMIT;
28053f04f3bSdan  }
28153f04f3bSdan  db close
28253f04f3bSdan  tstvfs delete
28353f04f3bSdan} {}
28453f04f3bSdando_test pager1.4.2.2 {
28553f04f3bSdan  faultsim_restore_and_reopen
28653f04f3bSdan  execsql {
28753f04f3bSdan    SELECT count(*) FROM t1;
28853f04f3bSdan    PRAGMA integrity_check;
28953f04f3bSdan  }
29053f04f3bSdan} {4 ok}
29153f04f3bSdando_test pager1.4.2.3 {
29253f04f3bSdan  faultsim_restore_and_reopen
29353f04f3bSdan  foreach f [glob test.db-mj*] { file delete -force $f }
29453f04f3bSdan  execsql {
29553f04f3bSdan    SELECT count(*) FROM t1;
29653f04f3bSdan    PRAGMA integrity_check;
29753f04f3bSdan  }
29853f04f3bSdan} {64 ok}
29953f04f3bSdando_test pager1.4.2.4 {
30053f04f3bSdan  faultsim_restore_and_reopen
30153f04f3bSdan  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
30253f04f3bSdan  execsql {
30353f04f3bSdan    SELECT count(*) FROM t1;
30453f04f3bSdan    PRAGMA integrity_check;
30553f04f3bSdan  }
30653f04f3bSdan} {4 ok}
30753f04f3bSdando_test pager1.4.2.5 {
30853f04f3bSdan  faultsim_restore_and_reopen
30953f04f3bSdan  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
31053f04f3bSdan  foreach f [glob test.db-mj*] { file delete -force $f }
31153f04f3bSdan  execsql {
31253f04f3bSdan    SELECT count(*) FROM t1;
31353f04f3bSdan    PRAGMA integrity_check;
31453f04f3bSdan  }
31553f04f3bSdan} {4 ok}
31653f04f3bSdan
317de4996e2Sdando_test pager1.4.3.1 {
318de4996e2Sdan  testvfs tstvfs -default 1
319de4996e2Sdan  tstvfs filter xSync
320de4996e2Sdan  tstvfs script xSyncCallback
321de4996e2Sdan  proc xSyncCallback {method file args} {
322de4996e2Sdan    set file [file tail $file]
323de4996e2Sdan    if { 0==[string match *journal $file] } { faultsim_save }
324de4996e2Sdan  }
325de4996e2Sdan  faultsim_delete_and_reopen
326de4996e2Sdan  execsql {
327de4996e2Sdan    PRAGMA journal_mode = DELETE;
328de4996e2Sdan    CREATE TABLE t1(a, b);
329de4996e2Sdan    INSERT INTO t1 VALUES(1, 2);
330de4996e2Sdan    INSERT INTO t1 VALUES(3, 4);
331de4996e2Sdan  }
332de4996e2Sdan  db close
333de4996e2Sdan  tstvfs delete
334de4996e2Sdan} {}
335de4996e2Sdan
336de4996e2Sdanforeach {tn ofst value result} {
337de4996e2Sdan          2   20    31       {1 2 3 4}
338de4996e2Sdan          3   20    32       {1 2 3 4}
339de4996e2Sdan          4   20    33       {1 2 3 4}
340de4996e2Sdan          5   20    65536    {1 2 3 4}
341de4996e2Sdan          6   20    131072   {1 2 3 4}
342de4996e2Sdan
343de4996e2Sdan          7   24    511      {1 2 3 4}
344de4996e2Sdan          8   24    513      {1 2 3 4}
345de4996e2Sdan          9   24    65536    {1 2 3 4}
346de4996e2Sdan
347de4996e2Sdan         10   32    65536    {1 2}
348de4996e2Sdan} {
349de4996e2Sdan  do_test pager1.4.3.$tn {
350de4996e2Sdan    faultsim_restore_and_reopen
351de4996e2Sdan    hexio_write test.db-journal $ofst [format %.8x $value]
352de4996e2Sdan    execsql { SELECT * FROM t1 }
353de4996e2Sdan  } $result
354de4996e2Sdan}
355de4996e2Sdandb close
356de4996e2Sdan
357de4996e2Sdan#-------------------------------------------------------------------------
358146ed78bSdan# The following tests deal with multi-file commits.
359de4996e2Sdan#
360146ed78bSdan# pager1-5.1.*: The case where a multi-file cannot be committed because
361146ed78bSdan#               another connection is holding a SHARED lock on one of the
362146ed78bSdan#               files. After the SHARED lock is removed, the COMMIT succeeds.
363146ed78bSdan#
364146ed78bSdan# pager1-5.2.*: Multi-file commits with journal_mode=memory.
365146ed78bSdan#
366146ed78bSdan# pager1-5.3.*: Multi-file commits with journal_mode=memory.
367146ed78bSdan#
368146ed78bSdan# pager1-5.4.*: Check that with synchronous=normal, the master-journal file
369146ed78bSdan#               name is added to a journal file immediately after the last
370146ed78bSdan#               journal record. But with synchronous=full, extra unused space
371146ed78bSdan#               is allocated between the last journal record and the
372146ed78bSdan#               master-journal file name so that the master-journal file
373146ed78bSdan#               name does not lie on the same sector as the last journal file
374146ed78bSdan#               record.
375146ed78bSdan#
376146ed78bSdan# pager1-5.5.*:
377146ed78bSdan#
378146ed78bSdando_test pager1-5.1.1 {
379146ed78bSdan  faultsim_delete_and_reopen
380146ed78bSdan  execsql {
381146ed78bSdan    ATTACH 'test.db2' AS aux;
382146ed78bSdan    CREATE TABLE t1(a, b);
383146ed78bSdan    CREATE TABLE aux.t2(a, b);
384146ed78bSdan    INSERT INTO t1 VALUES(17, 'Lenin');
385146ed78bSdan    INSERT INTO t1 VALUES(22, 'Stalin');
386146ed78bSdan    INSERT INTO t1 VALUES(53, 'Khrushchev');
387146ed78bSdan  }
388146ed78bSdan} {}
389146ed78bSdando_test pager1-5.1.2 {
390146ed78bSdan  execsql {
391146ed78bSdan    BEGIN;
392146ed78bSdan      INSERT INTO t1 VALUES(64, 'Brezhnev');
393146ed78bSdan      INSERT INTO t2 SELECT * FROM t1;
394146ed78bSdan  }
395146ed78bSdan  sqlite3 db2 test.db2
396146ed78bSdan  execsql {
397146ed78bSdan    BEGIN;
398146ed78bSdan      SELECT * FROM t2;
399146ed78bSdan  } db2
400146ed78bSdan} {}
401146ed78bSdando_test pager1-5.1.3 {
402146ed78bSdan  catchsql COMMIT
403146ed78bSdan} {1 {database is locked}}
404146ed78bSdando_test pager1-5.1.4 {
405146ed78bSdan  execsql COMMIT db2
406146ed78bSdan  execsql COMMIT
407146ed78bSdan  execsql { SELECT * FROM t2 } db2
408146ed78bSdan} {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev}
409146ed78bSdando_test pager1-5.1.5 {
410146ed78bSdan  db2 close
411146ed78bSdan} {}
412146ed78bSdan
413146ed78bSdando_test pager1-5.2.1 {
414146ed78bSdan  execsql {
415146ed78bSdan    PRAGMA journal_mode = memory;
416146ed78bSdan    BEGIN;
417146ed78bSdan      INSERT INTO t1 VALUES(84, 'Andropov');
418146ed78bSdan      INSERT INTO t2 VALUES(84, 'Andropov');
419146ed78bSdan    COMMIT;
420146ed78bSdan  }
421146ed78bSdan} {memory}
422146ed78bSdando_test pager1-5.3.1 {
423146ed78bSdan  execsql {
424146ed78bSdan    PRAGMA journal_mode = off;
425146ed78bSdan    BEGIN;
426146ed78bSdan      INSERT INTO t1 VALUES(85, 'Gorbachev');
427146ed78bSdan      INSERT INTO t2 VALUES(85, 'Gorbachev');
428146ed78bSdan    COMMIT;
429146ed78bSdan  }
430146ed78bSdan} {off}
431146ed78bSdan
432146ed78bSdando_test pager1-5.4.1 {
433146ed78bSdan  db close
434146ed78bSdan  testvfs tv
435146ed78bSdan  sqlite3 db test.db -vfs tv
436146ed78bSdan  execsql { ATTACH 'test.db2' AS aux }
437146ed78bSdan
438146ed78bSdan  tv filter xDelete
439146ed78bSdan  tv script max_journal_size
440146ed78bSdan  tv sectorsize 512
441146ed78bSdan  set ::max_journal 0
442146ed78bSdan  proc max_journal_size {method args} {
443146ed78bSdan    set sz 0
444146ed78bSdan    catch { set sz [file size test.db-journal] }
445146ed78bSdan    if {$sz > $::max_journal} {
446146ed78bSdan      set ::max_journal $sz
447146ed78bSdan    }
448146ed78bSdan    return SQLITE_OK
449146ed78bSdan  }
450146ed78bSdan  execsql {
451146ed78bSdan    PRAGMA journal_mode = DELETE;
452146ed78bSdan    PRAGMA synchronous = NORMAL;
453146ed78bSdan    BEGIN;
454146ed78bSdan      INSERT INTO t1 VALUES(85, 'Gorbachev');
455146ed78bSdan      INSERT INTO t2 VALUES(85, 'Gorbachev');
456146ed78bSdan    COMMIT;
457146ed78bSdan  }
458146ed78bSdan  set ::max_journal
459146ed78bSdan} [expr 2615+[string length [pwd]]]
460146ed78bSdando_test pager1-5.4.2 {
461146ed78bSdan  set ::max_journal 0
462146ed78bSdan  execsql {
463146ed78bSdan    PRAGMA synchronous = full;
464146ed78bSdan    BEGIN;
465146ed78bSdan      DELETE FROM t1 WHERE b = 'Lenin';
466146ed78bSdan      DELETE FROM t2 WHERE b = 'Lenin';
467146ed78bSdan    COMMIT;
468146ed78bSdan  }
469146ed78bSdan  set ::max_journal
470146ed78bSdan} [expr 3111+[string length [pwd]]]
471146ed78bSdandb close
472146ed78bSdantv delete
473146ed78bSdan
474146ed78bSdando_test pager1-5.5.1 {
475146ed78bSdan  sqlite3 db test.db
476146ed78bSdan  execsql {
477146ed78bSdan    ATTACH 'test.db2' AS aux;
478146ed78bSdan    PRAGMA journal_mode = PERSIST;
479146ed78bSdan    CREATE TABLE t3(a, b);
480146ed78bSdan    INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1;
481146ed78bSdan    UPDATE t3 SET b = randomblob(1500);
482146ed78bSdan  }
483146ed78bSdan  expr [file size test.db-journal] > 15000
484146ed78bSdan} {1}
485146ed78bSdando_test pager1-5.5.2 {
486146ed78bSdan  execsql {
487146ed78bSdan    PRAGMA synchronous = full;
488146ed78bSdan    BEGIN;
489146ed78bSdan      DELETE FROM t1 WHERE b = 'Stalin';
490146ed78bSdan      DELETE FROM t2 WHERE b = 'Stalin';
491146ed78bSdan    COMMIT;
492146ed78bSdan  }
493146ed78bSdan  file size test.db-journal
494146ed78bSdan} {0}
495146ed78bSdan
496146ed78bSdan
497146ed78bSdan#-------------------------------------------------------------------------
498146ed78bSdan# The following tests work with "PRAGMA max_page_count"
499146ed78bSdan#
500146ed78bSdando_test pager1-6.1 {
501146ed78bSdan  faultsim_delete_and_reopen
502146ed78bSdan  execsql {
503146ed78bSdan    PRAGMA max_page_count = 10;
504146ed78bSdan    CREATE TABLE t2(a, b);
505146ed78bSdan    CREATE TABLE t3(a, b);
506146ed78bSdan    CREATE TABLE t4(a, b);
507146ed78bSdan    CREATE TABLE t5(a, b);
508146ed78bSdan    CREATE TABLE t6(a, b);
509146ed78bSdan    CREATE TABLE t7(a, b);
510146ed78bSdan    CREATE TABLE t8(a, b);
511146ed78bSdan    CREATE TABLE t9(a, b);
512146ed78bSdan    CREATE TABLE t10(a, b);
513146ed78bSdan  }
514146ed78bSdan} {10}
515146ed78bSdando_test pager1-6.2 {
516146ed78bSdan  catchsql {
517146ed78bSdan    CREATE TABLE t11(a, b);
518146ed78bSdan  }
519146ed78bSdan} {1 {database or disk is full}}
520de4996e2Sdan
521*153eda0aSdan
522*153eda0aSdan#-------------------------------------------------------------------------
523*153eda0aSdan# The following tests work with "PRAGMA journal_mode=TRUNCATE" and
524*153eda0aSdan# "PRAGMA locking_mode=EXCLUSIVE".
525*153eda0aSdan#
526*153eda0aSdan# Each test is specified with 5 variables. As follows:
527*153eda0aSdan#
528*153eda0aSdan#   $tn:  Test Number. Used as part of the [do_test] test names.
529*153eda0aSdan#   $sql: SQL to execute.
530*153eda0aSdan#   $res: Expected result of executing $sql.
531*153eda0aSdan#   $js:  The expected size of the journal file, in bytes, after executing
532*153eda0aSdan#         the SQL script. Or -1 if the journal is not expected to exist.
533*153eda0aSdan#   $ws:  The expected size of the WAL file, in bytes, after executing
534*153eda0aSdan#         the SQL script. Or -1 if the WAL is not expected to exist.
535*153eda0aSdan#
536*153eda0aSdanfaultsim_delete_and_reopen
537*153eda0aSdanforeach {tn sql res js ws} [subst {
538*153eda0aSdan
539*153eda0aSdan  1  {
540*153eda0aSdan    CREATE TABLE t1(a, b);
541*153eda0aSdan    PRAGMA auto_vacuum=OFF;
542*153eda0aSdan    PRAGMA synchronous=NORMAL;
543*153eda0aSdan    PRAGMA page_size=1024;
544*153eda0aSdan    PRAGMA locking_mode=EXCLUSIVE;
545*153eda0aSdan    PRAGMA journal_mode=TRUNCATE;
546*153eda0aSdan    INSERT INTO t1 VALUES(1, 2);
547*153eda0aSdan  } {exclusive truncate} 0 -1
548*153eda0aSdan
549*153eda0aSdan  2  {
550*153eda0aSdan    BEGIN IMMEDIATE;
551*153eda0aSdan      SELECT * FROM t1;
552*153eda0aSdan    COMMIT;
553*153eda0aSdan  } {1 2} 0 -1
554*153eda0aSdan
555*153eda0aSdan  3  {
556*153eda0aSdan    BEGIN;
557*153eda0aSdan      SELECT * FROM t1;
558*153eda0aSdan    COMMIT;
559*153eda0aSdan  } {1 2} 0 -1
560*153eda0aSdan
561*153eda0aSdan  4  { PRAGMA journal_mode = WAL }    wal    -1 -1
562*153eda0aSdan  5  { INSERT INTO t1 VALUES(3, 4) }  {}     -1 [wal_file_size 1 1024]
563*153eda0aSdan  6  { PRAGMA locking_mode = NORMAL } normal -1 [wal_file_size 1 1024]
564*153eda0aSdan  7  { INSERT INTO t1 VALUES(5, 6); } {}     -1 [wal_file_size 2 1024]
565*153eda0aSdan
566*153eda0aSdan  8  { PRAGMA journal_mode = TRUNCATE } truncate          0 -1
567*153eda0aSdan  9  { INSERT INTO t1 VALUES(7, 8) }    {}                0 -1
568*153eda0aSdan  10 { SELECT * FROM t1 }               {1 2 3 4 5 6 7 8} 0 -1
569*153eda0aSdan
570*153eda0aSdan}] {
571*153eda0aSdan  do_execsql_test pager1-7.1.$tn.1 $sql $res
572*153eda0aSdan  catch { set J -1 ; set J [file size test.db-journal] }
573*153eda0aSdan  catch { set W -1 ; set W [file size test.db-wal] }
574*153eda0aSdan  do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws]
575*153eda0aSdan}
576*153eda0aSdan
577*153eda0aSdando_test pager1-8.1 {
578*153eda0aSdan  faultsim_delete_and_reopen
579*153eda0aSdan  db close
580*153eda0aSdan  sqlite3 db :memory:
581*153eda0aSdan  execsql {
582*153eda0aSdan    CREATE TABLE x1(x);
583*153eda0aSdan    INSERT INTO x1 VALUES('Charles');
584*153eda0aSdan    INSERT INTO x1 VALUES('James');
585*153eda0aSdan    INSERT INTO x1 VALUES('Mary');
586*153eda0aSdan    SELECT * FROM x1;
587*153eda0aSdan  }
588*153eda0aSdan} {Charles James Mary}
589*153eda0aSdando_test pager1-8.2 {
590*153eda0aSdan  db close
591*153eda0aSdan  sqlite3 db :memory:
592*153eda0aSdan  catchsql { SELECT * FROM x1 }
593*153eda0aSdan} {1 {no such table: x1}}
594*153eda0aSdan
595e91a54e1Sdanfinish_test
596e91a54e1Sdan
597