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