xref: /sqlite-3.40.0/test/pager1.test (revision 10f5a50e)
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#
41b0ac3e3aSdan
4253f04f3bSdanset a_string_counter 1
4353f04f3bSdanproc a_string {n} {
4453f04f3bSdan  global a_string_counter
4553f04f3bSdan  incr a_string_counter
4653f04f3bSdan  string range [string repeat "${a_string_counter}." $n] 1 $n
4753f04f3bSdan}
4853f04f3bSdandb func a_string a_string
4953f04f3bSdan
50a4a9095eSdando_multiclient_test tn {
51e91a54e1Sdan
52e91a54e1Sdan  # Create and populate a database table using connection [db]. Check
53e91a54e1Sdan  # that connections [db2] and [db3] can see the schema and content.
54e91a54e1Sdan  #
55e91a54e1Sdan  do_test pager1-$tn.1 {
56e91a54e1Sdan    sql1 {
57e91a54e1Sdan      CREATE TABLE t1(a PRIMARY KEY, b);
58e91a54e1Sdan      CREATE INDEX i1 ON t1(b);
59e91a54e1Sdan      INSERT INTO t1 VALUES(1, 'one');
60e91a54e1Sdan      INSERT INTO t1 VALUES(2, 'two');
61e91a54e1Sdan    }
62e91a54e1Sdan  } {}
63e91a54e1Sdan  do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
64e91a54e1Sdan  do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two}
65e91a54e1Sdan
66e91a54e1Sdan  # Open a transaction and add a row using [db]. This puts [db] in
67e91a54e1Sdan  # RESERVED state. Check that connections [db2] and [db3] can still
68e91a54e1Sdan  # read the database content as it was before the transaction was
69e91a54e1Sdan  # opened. [db] should see the inserted row.
70e91a54e1Sdan  #
71e91a54e1Sdan  do_test pager1-$tn.4 {
72e91a54e1Sdan    sql1 {
73e91a54e1Sdan      BEGIN;
74e91a54e1Sdan        INSERT INTO t1 VALUES(3, 'three');
75e91a54e1Sdan    }
76e91a54e1Sdan  } {}
77e91a54e1Sdan  do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two}
78e91a54e1Sdan  do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three}
79e91a54e1Sdan
80e91a54e1Sdan  # [db] still has an open write transaction. Check that this prevents
81e91a54e1Sdan  # other connections (specifically [db2]) from writing to the database.
82e91a54e1Sdan  #
83e91a54e1Sdan  # Even if [db2] opens a transaction first, it may not write to the
84e91a54e1Sdan  # database. After the attempt to write the db within a transaction,
85e91a54e1Sdan  # [db2] is left with an open transaction, but not a read-lock on
86e91a54e1Sdan  # the main database. So it does not prevent [db] from committing.
87e91a54e1Sdan  #
88e91a54e1Sdan  do_test pager1-$tn.8 {
89e91a54e1Sdan    csql2 { UPDATE t1 SET a = a + 10 }
90e91a54e1Sdan  } {1 {database is locked}}
91e91a54e1Sdan  do_test pager1-$tn.9 {
92e91a54e1Sdan    csql2 {
93e91a54e1Sdan      BEGIN;
94e91a54e1Sdan      UPDATE t1 SET a = a + 10;
95e91a54e1Sdan    }
96e91a54e1Sdan  } {1 {database is locked}}
97e91a54e1Sdan
98e91a54e1Sdan  # Have [db] commit its transactions. Check the other connections can
99e91a54e1Sdan  # now see the new database content.
100e91a54e1Sdan  #
101e91a54e1Sdan  do_test pager1-$tn.10 { sql1 { COMMIT } } {}
102e91a54e1Sdan  do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three}
103e91a54e1Sdan  do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three}
104e91a54e1Sdan  do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
105e91a54e1Sdan
106e91a54e1Sdan  # Check that, as noted above, [db2] really did keep an open transaction
107e91a54e1Sdan  # after the attempt to write the database failed.
108e91a54e1Sdan  #
109e91a54e1Sdan  do_test pager1-$tn.14 {
110e91a54e1Sdan    csql2 { BEGIN }
111e91a54e1Sdan  } {1 {cannot start a transaction within a transaction}}
112e91a54e1Sdan  do_test pager1-$tn.15 { sql2 { ROLLBACK } } {}
113e91a54e1Sdan
114e91a54e1Sdan  # Have [db2] open a transaction and take a read-lock on the database.
115e91a54e1Sdan  # Check that this prevents [db] from writing to the database (outside
116e91a54e1Sdan  # of any transaction). After this fails, check that [db3] can read
117e91a54e1Sdan  # the db (showing that [db] did not take a PENDING lock etc.)
118e91a54e1Sdan  #
119e91a54e1Sdan  do_test pager1-$tn.15 {
120e91a54e1Sdan    sql2 { BEGIN; SELECT * FROM t1; }
121e91a54e1Sdan  } {1 one 2 two 3 three}
122e91a54e1Sdan  do_test pager1-$tn.16 {
123e91a54e1Sdan    csql1 { UPDATE t1 SET a = a + 10 }
124e91a54e1Sdan  } {1 {database is locked}}
125e91a54e1Sdan  do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
126e91a54e1Sdan
127e91a54e1Sdan  # This time, have [db] open a transaction before writing the database.
128e91a54e1Sdan  # This works - [db] gets a RESERVED lock which does not conflict with
129e91a54e1Sdan  # the SHARED lock [db2] is holding.
130e91a54e1Sdan  #
131e91a54e1Sdan  do_test pager1-$tn.18 {
132e91a54e1Sdan    sql1 {
133e91a54e1Sdan      BEGIN;
134e91a54e1Sdan      UPDATE t1 SET a = a + 10;
135e91a54e1Sdan    }
136e91a54e1Sdan  } {}
137e91a54e1Sdan  do_test pager1-$tn-19 {
138e91a54e1Sdan    sql1 { PRAGMA lock_status }
139e91a54e1Sdan  } {main reserved temp closed}
140e91a54e1Sdan  do_test pager1-$tn-20 {
141e91a54e1Sdan    sql2 { PRAGMA lock_status }
142e91a54e1Sdan  } {main shared temp closed}
143e91a54e1Sdan
144e91a54e1Sdan  # Check that all connections can still read the database. Only [db] sees
145e91a54e1Sdan  # the updated content (as the transaction has not been committed yet).
146e91a54e1Sdan  #
147e91a54e1Sdan  do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three}
148e91a54e1Sdan  do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three}
149e91a54e1Sdan  do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three}
150e91a54e1Sdan
151e91a54e1Sdan  # Because [db2] still has the SHARED lock, [db] is unable to commit the
152e91a54e1Sdan  # transaction. If it tries, an error is returned and the connection
153e91a54e1Sdan  # upgrades to a PENDING lock.
154e91a54e1Sdan  #
155e91a54e1Sdan  # Once this happens, [db] can read the database and see the new content,
156e91a54e1Sdan  # [db2] (still holding SHARED) can still read the old content, but [db3]
157e91a54e1Sdan  # (not holding any lock) is prevented by [db]'s PENDING from reading
158e91a54e1Sdan  # the database.
159e91a54e1Sdan  #
160e91a54e1Sdan  do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}}
161e91a54e1Sdan  do_test pager1-$tn-25 {
162e91a54e1Sdan    sql1 { PRAGMA lock_status }
163e91a54e1Sdan  } {main pending temp closed}
164e91a54e1Sdan  do_test pager1-$tn.26 { sql1 { SELECT * FROM t1  } } {11 one 12 two 13 three}
165e91a54e1Sdan  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1  } } {1 one 2 two 3 three}
166e91a54e1Sdan  do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}}
167e91a54e1Sdan
168e91a54e1Sdan  # Have [db2] commit its read transaction, releasing the SHARED lock it
169e91a54e1Sdan  # is holding. Now, neither [db2] nor [db3] may read the database (as [db]
170e91a54e1Sdan  # is still holding a PENDING).
171e91a54e1Sdan  #
172e91a54e1Sdan  do_test pager1-$tn.29 { sql2 { COMMIT } } {}
173e91a54e1Sdan  do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}}
174e91a54e1Sdan  do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}}
175e91a54e1Sdan
176e91a54e1Sdan  # [db] is now able to commit the transaction. Once the transaction is
177e91a54e1Sdan  # committed, all three connections can read the new content.
178e91a54e1Sdan  #
179e91a54e1Sdan  do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {}
180e91a54e1Sdan  do_test pager1-$tn.26 { sql1 { COMMIT } } {}
181e91a54e1Sdan  do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three}
182e91a54e1Sdan  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three}
183e91a54e1Sdan  do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three}
184e91a54e1Sdan}
185e91a54e1Sdan
18653f04f3bSdan#-------------------------------------------------------------------------
18753f04f3bSdan# Savepoint related test cases.
18853f04f3bSdan#
1890e986f51Sdando_test pager1-3.1.1 {
190b0ac3e3aSdan  faultsim_delete_and_reopen
191b0ac3e3aSdan  execsql {
192b0ac3e3aSdan    CREATE TABLE t1(a PRIMARY KEY, b);
193b0ac3e3aSdan    CREATE TABLE counter(
194b0ac3e3aSdan      i CHECK (i<5),
195b0ac3e3aSdan      u CHECK (u<10)
196b0ac3e3aSdan    );
197b0ac3e3aSdan    INSERT INTO counter VALUES(0, 0);
198b0ac3e3aSdan    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
199b0ac3e3aSdan      UPDATE counter SET i = i+1;
200b0ac3e3aSdan    END;
201b0ac3e3aSdan    CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN
202b0ac3e3aSdan      UPDATE counter SET u = u+1;
203b0ac3e3aSdan    END;
204b0ac3e3aSdan  }
205b0ac3e3aSdan  execsql { SELECT * FROM counter }
206b0ac3e3aSdan} {0 0}
207b0ac3e3aSdan
2080e986f51Sdando_execsql_test pager1-3.1.2 {
209b0ac3e3aSdan  BEGIN;
210b0ac3e3aSdan    INSERT INTO t1 VALUES(1, randomblob(1500));
211b0ac3e3aSdan    INSERT INTO t1 VALUES(2, randomblob(1500));
212b0ac3e3aSdan    INSERT INTO t1 VALUES(3, randomblob(1500));
213b0ac3e3aSdan    SELECT * FROM counter;
214b0ac3e3aSdan} {3 0}
2150e986f51Sdando_catchsql_test pager1-3.1.3 {
216b0ac3e3aSdan    INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1
217b0ac3e3aSdan} {1 {constraint failed}}
218b0ac3e3aSdando_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0}
219b0ac3e3aSdando_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3}
220b0ac3e3aSdando_execsql_test pager1-3.6 { COMMIT } {}
221b0ac3e3aSdan
22253f04f3bSdan#-------------------------------------------------------------------------
22353f04f3bSdan# Hot journal rollback related test cases.
22453f04f3bSdan#
22553f04f3bSdan# pager1.4.1.*: Test that the pager module deletes very small invalid
22653f04f3bSdan#               journal files.
22753f04f3bSdan#
22853f04f3bSdan# pager1.4.2.*: Test that if the master journal pointer at the end of a
22953f04f3bSdan#               hot-journal file appears to be corrupt (checksum does not
23053f04f3bSdan#               compute) the associated journal is rolled back (and no
23153f04f3bSdan#               xAccess() call to check for the presence of any master
23253f04f3bSdan#               journal file is made).
23353f04f3bSdan#
234de4996e2Sdan# pager1.4.3.*: Test that the contents of a hot-journal are ignored if the
235de4996e2Sdan#               page-size or sector-size in the journal header appear to
236de4996e2Sdan#               be invalid (too large, too small or not a power of 2).
237de4996e2Sdan#
238e08341c6Sdan# pager1.4.4.*: Test hot-journal rollback of journal file with a master
239e08341c6Sdan#               journal pointer generated in various "PRAGMA synchronous"
240e08341c6Sdan#               modes.
241e08341c6Sdan#
242e08341c6Sdan# pager1.4.5.*: Test that hot-journal rollback stops if it encounters a
243e08341c6Sdan#               journal-record for which the checksum fails.
244e08341c6Sdan#
24553f04f3bSdando_test pager1.4.1.1 {
24653f04f3bSdan  faultsim_delete_and_reopen
24753f04f3bSdan  execsql {
24853f04f3bSdan    CREATE TABLE x(y, z);
24953f04f3bSdan    INSERT INTO x VALUES(1, 2);
25053f04f3bSdan  }
25153f04f3bSdan  set fd [open test.db-journal w]
25253f04f3bSdan  puts -nonewline $fd "helloworld"
25353f04f3bSdan  close $fd
25453f04f3bSdan  file exists test.db-journal
25553f04f3bSdan} {1}
25653f04f3bSdando_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2}
25753f04f3bSdando_test pager1.4.1.3 { file exists test.db-journal } {0}
25853f04f3bSdan
25953f04f3bSdan# Set up a [testvfs] to snapshot the file-system just before SQLite
26053f04f3bSdan# deletes the master-journal to commit a multi-file transaction.
26153f04f3bSdan#
26253f04f3bSdan# In subsequent test cases, invoking [faultsim_restore_and_reopen] sets
26353f04f3bSdan# up the file system to contain two databases, two hot-journal files and
26453f04f3bSdan# a master-journal.
26553f04f3bSdan#
26653f04f3bSdando_test pager1.4.2.1 {
26753f04f3bSdan  testvfs tstvfs -default 1
26853f04f3bSdan  tstvfs filter xDelete
26953f04f3bSdan  tstvfs script xDeleteCallback
27053f04f3bSdan  proc xDeleteCallback {method file args} {
27153f04f3bSdan    set file [file tail $file]
27253f04f3bSdan    if { [string match *mj* $file] } { faultsim_save }
27353f04f3bSdan  }
27453f04f3bSdan  faultsim_delete_and_reopen
27553f04f3bSdan  db func a_string a_string
27653f04f3bSdan  execsql {
27753f04f3bSdan    ATTACH 'test.db2' AS aux;
27853f04f3bSdan    PRAGMA journal_mode = DELETE;
27953f04f3bSdan    PRAGMA main.cache_size = 10;
28053f04f3bSdan    PRAGMA aux.cache_size = 10;
28153f04f3bSdan    CREATE TABLE t1(a UNIQUE, b UNIQUE);
28253f04f3bSdan    CREATE TABLE aux.t2(a UNIQUE, b UNIQUE);
28353f04f3bSdan    INSERT INTO t1 VALUES(a_string(200), a_string(300));
28453f04f3bSdan    INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
28553f04f3bSdan    INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
28653f04f3bSdan    INSERT INTO t2 SELECT * FROM t1;
28753f04f3bSdan    BEGIN;
28853f04f3bSdan      INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1;
28953f04f3bSdan      INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1;
29053f04f3bSdan      INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1;
29153f04f3bSdan      INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1;
29253f04f3bSdan      REPLACE INTO t2 SELECT * FROM t1;
29353f04f3bSdan    COMMIT;
29453f04f3bSdan  }
29553f04f3bSdan  db close
29653f04f3bSdan  tstvfs delete
29753f04f3bSdan} {}
29853f04f3bSdando_test pager1.4.2.2 {
29953f04f3bSdan  faultsim_restore_and_reopen
30053f04f3bSdan  execsql {
30153f04f3bSdan    SELECT count(*) FROM t1;
30253f04f3bSdan    PRAGMA integrity_check;
30353f04f3bSdan  }
30453f04f3bSdan} {4 ok}
30553f04f3bSdando_test pager1.4.2.3 {
30653f04f3bSdan  faultsim_restore_and_reopen
30753f04f3bSdan  foreach f [glob test.db-mj*] { file delete -force $f }
30853f04f3bSdan  execsql {
30953f04f3bSdan    SELECT count(*) FROM t1;
31053f04f3bSdan    PRAGMA integrity_check;
31153f04f3bSdan  }
31253f04f3bSdan} {64 ok}
31353f04f3bSdando_test pager1.4.2.4 {
31453f04f3bSdan  faultsim_restore_and_reopen
31553f04f3bSdan  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
31653f04f3bSdan  execsql {
31753f04f3bSdan    SELECT count(*) FROM t1;
31853f04f3bSdan    PRAGMA integrity_check;
31953f04f3bSdan  }
32053f04f3bSdan} {4 ok}
32153f04f3bSdando_test pager1.4.2.5 {
32253f04f3bSdan  faultsim_restore_and_reopen
32353f04f3bSdan  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
32453f04f3bSdan  foreach f [glob test.db-mj*] { file delete -force $f }
32553f04f3bSdan  execsql {
32653f04f3bSdan    SELECT count(*) FROM t1;
32753f04f3bSdan    PRAGMA integrity_check;
32853f04f3bSdan  }
32953f04f3bSdan} {4 ok}
33053f04f3bSdan
331de4996e2Sdando_test pager1.4.3.1 {
332de4996e2Sdan  testvfs tstvfs -default 1
333de4996e2Sdan  tstvfs filter xSync
334de4996e2Sdan  tstvfs script xSyncCallback
335de4996e2Sdan  proc xSyncCallback {method file args} {
336de4996e2Sdan    set file [file tail $file]
337de4996e2Sdan    if { 0==[string match *journal $file] } { faultsim_save }
338de4996e2Sdan  }
339de4996e2Sdan  faultsim_delete_and_reopen
340de4996e2Sdan  execsql {
341de4996e2Sdan    PRAGMA journal_mode = DELETE;
342de4996e2Sdan    CREATE TABLE t1(a, b);
343de4996e2Sdan    INSERT INTO t1 VALUES(1, 2);
344de4996e2Sdan    INSERT INTO t1 VALUES(3, 4);
345de4996e2Sdan  }
346de4996e2Sdan  db close
347de4996e2Sdan  tstvfs delete
348de4996e2Sdan} {}
349de4996e2Sdan
350de4996e2Sdanforeach {tn ofst value result} {
351de4996e2Sdan          2   20    31       {1 2 3 4}
352de4996e2Sdan          3   20    32       {1 2 3 4}
353de4996e2Sdan          4   20    33       {1 2 3 4}
354de4996e2Sdan          5   20    65536    {1 2 3 4}
355de4996e2Sdan          6   20    131072   {1 2 3 4}
356de4996e2Sdan
357de4996e2Sdan          7   24    511      {1 2 3 4}
358de4996e2Sdan          8   24    513      {1 2 3 4}
359de4996e2Sdan          9   24    65536    {1 2 3 4}
360de4996e2Sdan
361de4996e2Sdan         10   32    65536    {1 2}
362de4996e2Sdan} {
363de4996e2Sdan  do_test pager1.4.3.$tn {
364de4996e2Sdan    faultsim_restore_and_reopen
365de4996e2Sdan    hexio_write test.db-journal $ofst [format %.8x $value]
366de4996e2Sdan    execsql { SELECT * FROM t1 }
367de4996e2Sdan  } $result
368de4996e2Sdan}
369de4996e2Sdandb close
370de4996e2Sdan
371e08341c6Sdan# Set up a VFS that snapshots the file-system just before a master journal
372e08341c6Sdan# file is deleted to commit a multi-file transaction. Specifically, the
373e08341c6Sdan# file-system is saved just before the xDelete() call to remove the
374e08341c6Sdan# master journal file from the file-system.
375e08341c6Sdan#
376e08341c6Sdantestvfs tv -default 1
377e08341c6Sdantv script copy_on_mj_delete
378e08341c6Sdanset ::mj_filename_length 0
379e08341c6Sdanproc copy_on_mj_delete {method filename args} {
380e08341c6Sdan  if {[string match *mj* [file tail $filename]]} {
381e08341c6Sdan    set ::mj_filename_length [string length $filename]
382e08341c6Sdan    faultsim_save
383e08341c6Sdan  }
384e08341c6Sdan  return SQLITE_OK
385e08341c6Sdan}
386e08341c6Sdan
387e08341c6Sdanset pwd [pwd]
388e08341c6Sdanforeach {tn1 tcl} {
389e08341c6Sdan  1 { set prefix "test.db" }
390e08341c6Sdan  2 {
391e08341c6Sdan    # This test depends on the underlying VFS being able to open paths
392e08341c6Sdan    # 512 bytes in length. The idea is to create a hot-journal file that
393e08341c6Sdan    # contains a master-journal pointer so large that it could contain
394e08341c6Sdan    # a valid page record (if the file page-size is 512 bytes). So as to
395e08341c6Sdan    # make sure SQLite doesn't get confused by this.
396e08341c6Sdan    #
397e08341c6Sdan    set nPadding [expr 511 - $::mj_filename_length]
398e08341c6Sdan
399e08341c6Sdan    # We cannot just create a really long database file name to open, as
400e08341c6Sdan    # Linux limits a single component of a path to 255 bytes by default
401e08341c6Sdan    # (and presumably other systems have limits too). So create a directory
402e08341c6Sdan    # hierarchy to work in.
403e08341c6Sdan    #
404e08341c6Sdan    set dirname "d123456789012345678901234567890/"
405e08341c6Sdan    set nDir [expr $nPadding / 32]
406e08341c6Sdan    if { $nDir } {
407e08341c6Sdan      set p [string repeat $dirname $nDir]
408e08341c6Sdan      file mkdir $p
409e08341c6Sdan      cd $p
410e08341c6Sdan    }
411e08341c6Sdan
412e08341c6Sdan    set padding [string repeat x [expr $nPadding %32]]
413e08341c6Sdan    set prefix "test.db${padding}"
414e08341c6Sdan  }
415e08341c6Sdan} {
416e08341c6Sdan  eval $tcl
417e08341c6Sdan  foreach {tn2 sql} {
418e08341c6Sdan    o {
419e08341c6Sdan      PRAGMA main.synchronous=OFF;
420e08341c6Sdan      PRAGMA aux.synchronous=OFF;
421e08341c6Sdan    }
422e08341c6Sdan    o512 {
423e08341c6Sdan      PRAGMA main.synchronous=OFF;
424e08341c6Sdan      PRAGMA aux.synchronous=OFF;
425e08341c6Sdan      PRAGMA main.page_size = 512;
426e08341c6Sdan      PRAGMA aux.page_size = 512;
427e08341c6Sdan    }
428e08341c6Sdan    n {
429e08341c6Sdan      PRAGMA main.synchronous=NORMAL;
430e08341c6Sdan      PRAGMA aux.synchronous=NORMAL;
431e08341c6Sdan    }
432e08341c6Sdan    f {
433e08341c6Sdan      PRAGMA main.synchronous=FULL;
434e08341c6Sdan      PRAGMA aux.synchronous=FULL;
435e08341c6Sdan    }
436e08341c6Sdan  } {
437e08341c6Sdan
438e08341c6Sdan    set tn "${tn1}.${tn2}"
439e08341c6Sdan
440e08341c6Sdan    # Set up a connection to have two databases, test.db (main) and
441e08341c6Sdan    # test.db2 (aux). Then run a multi-file transaction on them. The
442e08341c6Sdan    # VFS will snapshot the file-system just before the master-journal
443e08341c6Sdan    # file is deleted to commit the transaction.
444e08341c6Sdan    #
445e08341c6Sdan    tv filter xDelete
446e08341c6Sdan    do_test pager1-4.4.$tn.1 {
447e08341c6Sdan      faultsim_delete_and_reopen $prefix
448e08341c6Sdan      execsql "
449e08341c6Sdan        ATTACH '${prefix}2' AS aux;
450e08341c6Sdan        $sql
451e08341c6Sdan        CREATE TABLE a(x);
452e08341c6Sdan        CREATE TABLE aux.b(x);
453e08341c6Sdan        INSERT INTO a VALUES('double-you');
454e08341c6Sdan        INSERT INTO a VALUES('why');
455e08341c6Sdan        INSERT INTO a VALUES('zed');
456e08341c6Sdan        INSERT INTO b VALUES('won');
457e08341c6Sdan        INSERT INTO b VALUES('too');
458e08341c6Sdan        INSERT INTO b VALUES('free');
459e08341c6Sdan      "
460e08341c6Sdan      execsql {
461e08341c6Sdan        BEGIN;
462e08341c6Sdan          INSERT INTO a SELECT * FROM b WHERE rowid<=3;
463e08341c6Sdan          INSERT INTO b SELECT * FROM a WHERE rowid<=3;
464e08341c6Sdan        COMMIT;
465e08341c6Sdan      }
466e08341c6Sdan    } {}
467e08341c6Sdan    tv filter {}
468e08341c6Sdan
469e08341c6Sdan    # Check that the transaction was committed successfully.
470e08341c6Sdan    #
471e08341c6Sdan    do_execsql_test pager1-4.4.$tn.2 {
472e08341c6Sdan      SELECT * FROM a
473e08341c6Sdan    } {double-you why zed won too free}
474e08341c6Sdan    do_execsql_test pager1-4.4.$tn.3 {
475e08341c6Sdan      SELECT * FROM b
476e08341c6Sdan    } {won too free double-you why zed}
477e08341c6Sdan
478e08341c6Sdan    # Restore the file-system and reopen the databases. Check that it now
479e08341c6Sdan    # appears that the transaction was not committed (because the file-system
480e08341c6Sdan    # was restored to the state where it had not been).
481e08341c6Sdan    #
482e08341c6Sdan    do_test pager1-4.4.$tn.4 {
483e08341c6Sdan      faultsim_restore_and_reopen $prefix
484e08341c6Sdan      execsql "ATTACH '${prefix}2' AS aux"
485e08341c6Sdan    } {}
486e08341c6Sdan    do_execsql_test pager1-4.4.$tn.5 {SELECT * FROM a} {double-you why zed}
487e08341c6Sdan    do_execsql_test pager1-4.4.$tn.6 {SELECT * FROM b} {won too free}
488e08341c6Sdan
489e08341c6Sdan    # Restore the file-system again. This time, before reopening the databases,
490e08341c6Sdan    # delete the master-journal file from the file-system. It now appears that
491e08341c6Sdan    # the transaction was committed (no master-journal file == no rollback).
492e08341c6Sdan    #
493e08341c6Sdan    do_test pager1-4.4.$tn.7 {
494e08341c6Sdan      faultsim_restore_and_reopen $prefix
495e08341c6Sdan      foreach f [glob ${prefix}-mj*] { file delete -force $f }
496e08341c6Sdan      execsql "ATTACH '${prefix}2' AS aux"
497e08341c6Sdan    } {}
498e08341c6Sdan    do_execsql_test pager1-4.4.$tn.8 {
499e08341c6Sdan      SELECT * FROM a
500e08341c6Sdan    } {double-you why zed won too free}
501e08341c6Sdan    do_execsql_test pager1-4.4.$tn.9 {
502e08341c6Sdan      SELECT * FROM b
503e08341c6Sdan    } {won too free double-you why zed}
504e08341c6Sdan  }
505e08341c6Sdan
506e08341c6Sdan  cd $pwd
507e08341c6Sdan}
508e08341c6Sdandb close
509e08341c6Sdantv delete
5100e986f51Sdanfile delete -force $dirname
5110e986f51Sdan
5120e986f51Sdan
5130e986f51Sdan# Set up a VFS to make a copy of the file-system just before deleting a
5140e986f51Sdan# journal file to commit a transaction. The transaction modifies exactly
5150e986f51Sdan# two database pages (and page 1 - the change counter).
5160e986f51Sdan#
5170e986f51Sdantestvfs tv -default 1
5180e986f51Sdantv sectorsize 512
5190e986f51Sdantv script copy_on_journal_delete
5200e986f51Sdantv filter xDelete
5210e986f51Sdanset ::mj_filename_length 0
5220e986f51Sdanproc copy_on_journal_delete {method filename args} {
5230e986f51Sdan  if {[string match *journal $filename]} faultsim_save
5240e986f51Sdan  return SQLITE_OK
5250e986f51Sdan}
5260e986f51Sdanfaultsim_delete_and_reopen
5270e986f51Sdando_execsql_test pager1.4.5.1 {
5280e986f51Sdan  PRAGMA page_size = 1024;
5290e986f51Sdan  CREATE TABLE t1(a, b);
5300e986f51Sdan  CREATE TABLE t2(a, b);
5310e986f51Sdan  INSERT INTO t1 VALUES('I', 'II');
5320e986f51Sdan  INSERT INTO t2 VALUES('III', 'IV');
5330e986f51Sdan  BEGIN;
5340e986f51Sdan    INSERT INTO t1 VALUES(1, 2);
5350e986f51Sdan    INSERT INTO t2 VALUES(3, 4);
5360e986f51Sdan  COMMIT;
5370e986f51Sdan} {}
5380e986f51Sdantv filter {}
5390e986f51Sdan
5400e986f51Sdan# Check the transaction was committed:
5410e986f51Sdan#
5420e986f51Sdando_execsql_test pager1.4.5.2 {
5430e986f51Sdan  SELECT * FROM t1;
5440e986f51Sdan  SELECT * FROM t2;
5450e986f51Sdan} {I II 1 2 III IV 3 4}
5460e986f51Sdan
5470e986f51Sdan# Now try three tests:
5480e986f51Sdan#
5490e986f51Sdan#  pager1-4.5.3: Restore the file-system. Check that the whole transaction
5500e986f51Sdan#                is rolled back.
5510e986f51Sdan#
5520e986f51Sdan#  pager1-4.5.4: Restore the file-system. Corrupt the first record in the
5530e986f51Sdan#                journal. Check the transaction is not rolled back.
5540e986f51Sdan#
5550e986f51Sdan#  pager1-4.5.5: Restore the file-system. Corrupt the second record in the
5560e986f51Sdan#                journal. Check that the first record in the transaction is
5570e986f51Sdan#                played back, but not the second.
5580e986f51Sdan#
559*10f5a50eSdan#  pager1-4.5.6: Restore the file-system. Try to open the database with a
560*10f5a50eSdan#                readonly connection. This should fail, as a read-only
561*10f5a50eSdan#                connection cannot roll back the database file.
562*10f5a50eSdan#
5630e986f51Sdanfaultsim_restore_and_reopen
5640e986f51Sdando_execsql_test pager1.4.5.3 {
5650e986f51Sdan  SELECT * FROM t1;
5660e986f51Sdan  SELECT * FROM t2;
5670e986f51Sdan} {I II III IV}
5680e986f51Sdanfaultsim_restore_and_reopen
5690e986f51Sdanhexio_write test.db-journal [expr 512+4+1024 - 202] 0123456789ABCDEF
5700e986f51Sdando_execsql_test pager1.4.5.4 {
5710e986f51Sdan  SELECT * FROM t1;
5720e986f51Sdan  SELECT * FROM t2;
5730e986f51Sdan} {I II 1 2 III IV 3 4}
5740e986f51Sdanfaultsim_restore_and_reopen
5750e986f51Sdanhexio_write test.db-journal [expr 512+4+1024+4+4+1024 - 202] 0123456789ABCDEF
5760e986f51Sdando_execsql_test pager1.4.5.5 {
5770e986f51Sdan  SELECT * FROM t1;
5780e986f51Sdan  SELECT * FROM t2;
5790e986f51Sdan} {I II III IV 3 4}
5800e986f51Sdan
581*10f5a50eSdanfaultsim_restore_and_reopen
582*10f5a50eSdandb close
583*10f5a50eSdansqlite3 db test.db -readonly 1
584*10f5a50eSdando_catchsql_test pager1.4.5.6 {
585*10f5a50eSdan  SELECT * FROM t1;
586*10f5a50eSdan  SELECT * FROM t2;
587*10f5a50eSdan} {1 {disk I/O error}}
588*10f5a50eSdan
5890e986f51Sdandb close
5900e986f51Sdantv delete
591e08341c6Sdan
592de4996e2Sdan#-------------------------------------------------------------------------
593146ed78bSdan# The following tests deal with multi-file commits.
594de4996e2Sdan#
595146ed78bSdan# pager1-5.1.*: The case where a multi-file cannot be committed because
596146ed78bSdan#               another connection is holding a SHARED lock on one of the
597146ed78bSdan#               files. After the SHARED lock is removed, the COMMIT succeeds.
598146ed78bSdan#
599146ed78bSdan# pager1-5.2.*: Multi-file commits with journal_mode=memory.
600146ed78bSdan#
601146ed78bSdan# pager1-5.3.*: Multi-file commits with journal_mode=memory.
602146ed78bSdan#
603146ed78bSdan# pager1-5.4.*: Check that with synchronous=normal, the master-journal file
604146ed78bSdan#               name is added to a journal file immediately after the last
605146ed78bSdan#               journal record. But with synchronous=full, extra unused space
606146ed78bSdan#               is allocated between the last journal record and the
607146ed78bSdan#               master-journal file name so that the master-journal file
608146ed78bSdan#               name does not lie on the same sector as the last journal file
609146ed78bSdan#               record.
610146ed78bSdan#
611e08341c6Sdan# pager1-5.5.*: Check that in journal_mode=PERSIST mode, a journal file is
612e08341c6Sdan#               truncated to zero bytes when a multi-file transaction is
613e08341c6Sdan#               committed (instead of the first couple of bytes being zeroed).
614e08341c6Sdan#
615146ed78bSdan#
616146ed78bSdando_test pager1-5.1.1 {
617146ed78bSdan  faultsim_delete_and_reopen
618146ed78bSdan  execsql {
619146ed78bSdan    ATTACH 'test.db2' AS aux;
620146ed78bSdan    CREATE TABLE t1(a, b);
621146ed78bSdan    CREATE TABLE aux.t2(a, b);
622146ed78bSdan    INSERT INTO t1 VALUES(17, 'Lenin');
623146ed78bSdan    INSERT INTO t1 VALUES(22, 'Stalin');
624146ed78bSdan    INSERT INTO t1 VALUES(53, 'Khrushchev');
625146ed78bSdan  }
626146ed78bSdan} {}
627146ed78bSdando_test pager1-5.1.2 {
628146ed78bSdan  execsql {
629146ed78bSdan    BEGIN;
630146ed78bSdan      INSERT INTO t1 VALUES(64, 'Brezhnev');
631146ed78bSdan      INSERT INTO t2 SELECT * FROM t1;
632146ed78bSdan  }
633146ed78bSdan  sqlite3 db2 test.db2
634146ed78bSdan  execsql {
635146ed78bSdan    BEGIN;
636146ed78bSdan      SELECT * FROM t2;
637146ed78bSdan  } db2
638146ed78bSdan} {}
639146ed78bSdando_test pager1-5.1.3 {
640146ed78bSdan  catchsql COMMIT
641146ed78bSdan} {1 {database is locked}}
642146ed78bSdando_test pager1-5.1.4 {
643146ed78bSdan  execsql COMMIT db2
644146ed78bSdan  execsql COMMIT
645146ed78bSdan  execsql { SELECT * FROM t2 } db2
646146ed78bSdan} {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev}
647146ed78bSdando_test pager1-5.1.5 {
648146ed78bSdan  db2 close
649146ed78bSdan} {}
650146ed78bSdan
651146ed78bSdando_test pager1-5.2.1 {
652146ed78bSdan  execsql {
653146ed78bSdan    PRAGMA journal_mode = memory;
654146ed78bSdan    BEGIN;
655146ed78bSdan      INSERT INTO t1 VALUES(84, 'Andropov');
656146ed78bSdan      INSERT INTO t2 VALUES(84, 'Andropov');
657146ed78bSdan    COMMIT;
658146ed78bSdan  }
659146ed78bSdan} {memory}
660146ed78bSdando_test pager1-5.3.1 {
661146ed78bSdan  execsql {
662146ed78bSdan    PRAGMA journal_mode = off;
663146ed78bSdan    BEGIN;
664146ed78bSdan      INSERT INTO t1 VALUES(85, 'Gorbachev');
665146ed78bSdan      INSERT INTO t2 VALUES(85, 'Gorbachev');
666146ed78bSdan    COMMIT;
667146ed78bSdan  }
668146ed78bSdan} {off}
669146ed78bSdan
670146ed78bSdando_test pager1-5.4.1 {
671146ed78bSdan  db close
672146ed78bSdan  testvfs tv
673146ed78bSdan  sqlite3 db test.db -vfs tv
674146ed78bSdan  execsql { ATTACH 'test.db2' AS aux }
675146ed78bSdan
676146ed78bSdan  tv filter xDelete
677146ed78bSdan  tv script max_journal_size
678146ed78bSdan  tv sectorsize 512
679146ed78bSdan  set ::max_journal 0
680146ed78bSdan  proc max_journal_size {method args} {
681146ed78bSdan    set sz 0
682146ed78bSdan    catch { set sz [file size test.db-journal] }
683146ed78bSdan    if {$sz > $::max_journal} {
684146ed78bSdan      set ::max_journal $sz
685146ed78bSdan    }
686146ed78bSdan    return SQLITE_OK
687146ed78bSdan  }
688146ed78bSdan  execsql {
689146ed78bSdan    PRAGMA journal_mode = DELETE;
690146ed78bSdan    PRAGMA synchronous = NORMAL;
691146ed78bSdan    BEGIN;
692146ed78bSdan      INSERT INTO t1 VALUES(85, 'Gorbachev');
693146ed78bSdan      INSERT INTO t2 VALUES(85, 'Gorbachev');
694146ed78bSdan    COMMIT;
695146ed78bSdan  }
696146ed78bSdan  set ::max_journal
697146ed78bSdan} [expr 2615+[string length [pwd]]]
698146ed78bSdando_test pager1-5.4.2 {
699146ed78bSdan  set ::max_journal 0
700146ed78bSdan  execsql {
701146ed78bSdan    PRAGMA synchronous = full;
702146ed78bSdan    BEGIN;
703146ed78bSdan      DELETE FROM t1 WHERE b = 'Lenin';
704146ed78bSdan      DELETE FROM t2 WHERE b = 'Lenin';
705146ed78bSdan    COMMIT;
706146ed78bSdan  }
707146ed78bSdan  set ::max_journal
708146ed78bSdan} [expr 3111+[string length [pwd]]]
709146ed78bSdandb close
710146ed78bSdantv delete
711146ed78bSdan
712146ed78bSdando_test pager1-5.5.1 {
713146ed78bSdan  sqlite3 db test.db
714146ed78bSdan  execsql {
715146ed78bSdan    ATTACH 'test.db2' AS aux;
716146ed78bSdan    PRAGMA journal_mode = PERSIST;
717146ed78bSdan    CREATE TABLE t3(a, b);
718146ed78bSdan    INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1;
719146ed78bSdan    UPDATE t3 SET b = randomblob(1500);
720146ed78bSdan  }
721146ed78bSdan  expr [file size test.db-journal] > 15000
722146ed78bSdan} {1}
723146ed78bSdando_test pager1-5.5.2 {
724146ed78bSdan  execsql {
725146ed78bSdan    PRAGMA synchronous = full;
726146ed78bSdan    BEGIN;
727146ed78bSdan      DELETE FROM t1 WHERE b = 'Stalin';
728146ed78bSdan      DELETE FROM t2 WHERE b = 'Stalin';
729146ed78bSdan    COMMIT;
730146ed78bSdan  }
731146ed78bSdan  file size test.db-journal
732146ed78bSdan} {0}
733146ed78bSdan
734146ed78bSdan
735146ed78bSdan#-------------------------------------------------------------------------
736146ed78bSdan# The following tests work with "PRAGMA max_page_count"
737146ed78bSdan#
738146ed78bSdando_test pager1-6.1 {
739146ed78bSdan  faultsim_delete_and_reopen
740146ed78bSdan  execsql {
741146ed78bSdan    PRAGMA max_page_count = 10;
742146ed78bSdan    CREATE TABLE t2(a, b);
743146ed78bSdan    CREATE TABLE t3(a, b);
744146ed78bSdan    CREATE TABLE t4(a, b);
745146ed78bSdan    CREATE TABLE t5(a, b);
746146ed78bSdan    CREATE TABLE t6(a, b);
747146ed78bSdan    CREATE TABLE t7(a, b);
748146ed78bSdan    CREATE TABLE t8(a, b);
749146ed78bSdan    CREATE TABLE t9(a, b);
750146ed78bSdan    CREATE TABLE t10(a, b);
751146ed78bSdan  }
752146ed78bSdan} {10}
753146ed78bSdando_test pager1-6.2 {
754146ed78bSdan  catchsql {
755146ed78bSdan    CREATE TABLE t11(a, b);
756146ed78bSdan  }
757146ed78bSdan} {1 {database or disk is full}}
758de4996e2Sdan
759153eda0aSdan
760153eda0aSdan#-------------------------------------------------------------------------
761153eda0aSdan# The following tests work with "PRAGMA journal_mode=TRUNCATE" and
762153eda0aSdan# "PRAGMA locking_mode=EXCLUSIVE".
763153eda0aSdan#
764153eda0aSdan# Each test is specified with 5 variables. As follows:
765153eda0aSdan#
766153eda0aSdan#   $tn:  Test Number. Used as part of the [do_test] test names.
767153eda0aSdan#   $sql: SQL to execute.
768153eda0aSdan#   $res: Expected result of executing $sql.
769153eda0aSdan#   $js:  The expected size of the journal file, in bytes, after executing
770153eda0aSdan#         the SQL script. Or -1 if the journal is not expected to exist.
771153eda0aSdan#   $ws:  The expected size of the WAL file, in bytes, after executing
772153eda0aSdan#         the SQL script. Or -1 if the WAL is not expected to exist.
773153eda0aSdan#
774153eda0aSdanfaultsim_delete_and_reopen
775153eda0aSdanforeach {tn sql res js ws} [subst {
776153eda0aSdan
777153eda0aSdan  1  {
778153eda0aSdan    CREATE TABLE t1(a, b);
779153eda0aSdan    PRAGMA auto_vacuum=OFF;
780153eda0aSdan    PRAGMA synchronous=NORMAL;
781153eda0aSdan    PRAGMA page_size=1024;
782153eda0aSdan    PRAGMA locking_mode=EXCLUSIVE;
783153eda0aSdan    PRAGMA journal_mode=TRUNCATE;
784153eda0aSdan    INSERT INTO t1 VALUES(1, 2);
785153eda0aSdan  } {exclusive truncate} 0 -1
786153eda0aSdan
787153eda0aSdan  2  {
788153eda0aSdan    BEGIN IMMEDIATE;
789153eda0aSdan      SELECT * FROM t1;
790153eda0aSdan    COMMIT;
791153eda0aSdan  } {1 2} 0 -1
792153eda0aSdan
793153eda0aSdan  3  {
794153eda0aSdan    BEGIN;
795153eda0aSdan      SELECT * FROM t1;
796153eda0aSdan    COMMIT;
797153eda0aSdan  } {1 2} 0 -1
798153eda0aSdan
799153eda0aSdan  4  { PRAGMA journal_mode = WAL }    wal    -1 -1
800153eda0aSdan  5  { INSERT INTO t1 VALUES(3, 4) }  {}     -1 [wal_file_size 1 1024]
801153eda0aSdan  6  { PRAGMA locking_mode = NORMAL } normal -1 [wal_file_size 1 1024]
802153eda0aSdan  7  { INSERT INTO t1 VALUES(5, 6); } {}     -1 [wal_file_size 2 1024]
803153eda0aSdan
804153eda0aSdan  8  { PRAGMA journal_mode = TRUNCATE } truncate          0 -1
805153eda0aSdan  9  { INSERT INTO t1 VALUES(7, 8) }    {}                0 -1
806153eda0aSdan  10 { SELECT * FROM t1 }               {1 2 3 4 5 6 7 8} 0 -1
807153eda0aSdan
808153eda0aSdan}] {
809153eda0aSdan  do_execsql_test pager1-7.1.$tn.1 $sql $res
810153eda0aSdan  catch { set J -1 ; set J [file size test.db-journal] }
811153eda0aSdan  catch { set W -1 ; set W [file size test.db-wal] }
812153eda0aSdan  do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws]
813153eda0aSdan}
814153eda0aSdan
8150e986f51Sdanforeach {tn filename} {
8160e986f51Sdan  1 :memory:
8170e986f51Sdan  2 ""
8180e986f51Sdan} {
8190e986f51Sdan  do_test pager1-8.$tn.1 {
820153eda0aSdan    faultsim_delete_and_reopen
821153eda0aSdan    db close
8220e986f51Sdan    sqlite3 db $filename
823153eda0aSdan    execsql {
824153eda0aSdan      CREATE TABLE x1(x);
825153eda0aSdan      INSERT INTO x1 VALUES('Charles');
826153eda0aSdan      INSERT INTO x1 VALUES('James');
827153eda0aSdan      INSERT INTO x1 VALUES('Mary');
828153eda0aSdan      SELECT * FROM x1;
829153eda0aSdan    }
830153eda0aSdan  } {Charles James Mary}
8310e986f51Sdan
8320e986f51Sdan  do_test pager1-8.$tn.2 {
8330e986f51Sdan    sqlite3 db2 $filename
8340e986f51Sdan    catchsql { SELECT * FROM x1 } db2
835153eda0aSdan  } {1 {no such table: x1}}
836153eda0aSdan
8370e986f51Sdan  do_execsql_test pager1-8.$tn.3 {
8380e986f51Sdan    BEGIN;
8390e986f51Sdan      INSERT INTO x1 VALUES('William');
8400e986f51Sdan      INSERT INTO x1 VALUES('Anne');
8410e986f51Sdan    ROLLBACK;
8420e986f51Sdan  } {}
8430e986f51Sdan}
8440e986f51Sdan
845e91a54e1Sdanfinish_test
846e91a54e1Sdan
847