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 18d7a558a9Sdanset testprefix pager1 1968928b6cSdan 2068928b6cSdan# Do not use a codec for tests in this file, as the database file is 2168928b6cSdan# manipulated directly using tcl scripts (using the [hexio_write] command). 2268928b6cSdan# 2368928b6cSdando_not_use_codec 24e91a54e1Sdan 25b0ac3e3aSdan# 26b0ac3e3aSdan# pager1-1.*: Test inter-process locking (clients in multiple processes). 27b0ac3e3aSdan# 28b0ac3e3aSdan# pager1-2.*: Test intra-process locking (multiple clients in this process). 29b0ac3e3aSdan# 30b0ac3e3aSdan# pager1-3.*: Savepoint related tests. 31b0ac3e3aSdan# 321f4cb65aSdan# pager1-4.*: Hot-journal related tests. 331f4cb65aSdan# 34de4996e2Sdan# pager1-5.*: Cases related to multi-file commits. 35de4996e2Sdan# 36146ed78bSdan# pager1-6.*: Cases related to "PRAGMA max_page_count" 37146ed78bSdan# 38153eda0aSdan# pager1-7.*: Cases specific to "PRAGMA journal_mode=TRUNCATE" 39153eda0aSdan# 400e986f51Sdan# pager1-8.*: Cases using temporary and in-memory databases. 410e986f51Sdan# 42dca321aeSdan# pager1-9.*: Tests related to the backup API. 43dca321aeSdan# 44ec6ffc1aSdan# pager1-10.*: Test that the assumed file-system sector-size is limited to 45ec6ffc1aSdan# 64KB. 46ec6ffc1aSdan# 47d353331aSdan# pager1-12.*: Tests involving "PRAGMA page_size" 48d353331aSdan# 49d353331aSdan# pager1-13.*: Cases specific to "PRAGMA journal_mode=PERSIST" 50d353331aSdan# 51d353331aSdan# pager1-14.*: Cases specific to "PRAGMA journal_mode=OFF" 52ec6ffc1aSdan# 53c8ce3972Sdan# pager1-15.*: Varying sqlite3_vfs.szOsFile 54c8ce3972Sdan# 55c8ce3972Sdan# pager1-16.*: Varying sqlite3_vfs.mxPathname 56c8ce3972Sdan# 57c8ce3972Sdan# pager1-17.*: Tests related to "PRAGMA omit_readlock" 5833f111dcSdrh# (The omit_readlock pragma has been removed and so have 5933f111dcSdrh# these tests.) 60c8ce3972Sdan# 61c8ce3972Sdan# pager1-18.*: Test that the pager layer responds correctly if the b-tree 62c8ce3972Sdan# requests an invalid page number (due to db corruption). 63c8ce3972Sdan# 64b0ac3e3aSdan 65c396d4afSdanproc recursive_select {id table {script {}}} { 66c396d4afSdan set cnt 0 67c396d4afSdan db eval "SELECT rowid, * FROM $table WHERE rowid = ($id-1)" { 68c396d4afSdan recursive_select $rowid $table $script 69c396d4afSdan incr cnt 70c396d4afSdan } 71c396d4afSdan if {$cnt==0} { eval $script } 72c396d4afSdan} 73c396d4afSdan 7453f04f3bSdanset a_string_counter 1 7553f04f3bSdanproc a_string {n} { 7653f04f3bSdan global a_string_counter 7753f04f3bSdan incr a_string_counter 7853f04f3bSdan string range [string repeat "${a_string_counter}." $n] 1 $n 7953f04f3bSdan} 8053f04f3bSdandb func a_string a_string 8153f04f3bSdan 82a4a9095eSdando_multiclient_test tn { 83e91a54e1Sdan 84e91a54e1Sdan # Create and populate a database table using connection [db]. Check 85e91a54e1Sdan # that connections [db2] and [db3] can see the schema and content. 86e91a54e1Sdan # 87e91a54e1Sdan do_test pager1-$tn.1 { 88e91a54e1Sdan sql1 { 89e91a54e1Sdan CREATE TABLE t1(a PRIMARY KEY, b); 90e91a54e1Sdan CREATE INDEX i1 ON t1(b); 91d353331aSdan INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); 92e91a54e1Sdan } 93e91a54e1Sdan } {} 94e91a54e1Sdan do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two} 95e91a54e1Sdan do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two} 96e91a54e1Sdan 97e91a54e1Sdan # Open a transaction and add a row using [db]. This puts [db] in 98e91a54e1Sdan # RESERVED state. Check that connections [db2] and [db3] can still 99e91a54e1Sdan # read the database content as it was before the transaction was 100e91a54e1Sdan # opened. [db] should see the inserted row. 101e91a54e1Sdan # 102e91a54e1Sdan do_test pager1-$tn.4 { 103e91a54e1Sdan sql1 { 104e91a54e1Sdan BEGIN; 105e91a54e1Sdan INSERT INTO t1 VALUES(3, 'three'); 106e91a54e1Sdan } 107e91a54e1Sdan } {} 108e91a54e1Sdan do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two} 109e91a54e1Sdan do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} 110e91a54e1Sdan 111e91a54e1Sdan # [db] still has an open write transaction. Check that this prevents 112e91a54e1Sdan # other connections (specifically [db2]) from writing to the database. 113e91a54e1Sdan # 114e91a54e1Sdan # Even if [db2] opens a transaction first, it may not write to the 115e91a54e1Sdan # database. After the attempt to write the db within a transaction, 116e91a54e1Sdan # [db2] is left with an open transaction, but not a read-lock on 117e91a54e1Sdan # the main database. So it does not prevent [db] from committing. 118e91a54e1Sdan # 119e91a54e1Sdan do_test pager1-$tn.8 { 120e91a54e1Sdan csql2 { UPDATE t1 SET a = a + 10 } 121e91a54e1Sdan } {1 {database is locked}} 122e91a54e1Sdan do_test pager1-$tn.9 { 123e91a54e1Sdan csql2 { 124e91a54e1Sdan BEGIN; 125e91a54e1Sdan UPDATE t1 SET a = a + 10; 126e91a54e1Sdan } 127e91a54e1Sdan } {1 {database is locked}} 128e91a54e1Sdan 129e91a54e1Sdan # Have [db] commit its transactions. Check the other connections can 130e91a54e1Sdan # now see the new database content. 131e91a54e1Sdan # 132e91a54e1Sdan do_test pager1-$tn.10 { sql1 { COMMIT } } {} 133e91a54e1Sdan do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} 134e91a54e1Sdan do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 135e91a54e1Sdan do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 136e91a54e1Sdan 137e91a54e1Sdan # Check that, as noted above, [db2] really did keep an open transaction 138e91a54e1Sdan # after the attempt to write the database failed. 139e91a54e1Sdan # 140e91a54e1Sdan do_test pager1-$tn.14 { 141e91a54e1Sdan csql2 { BEGIN } 142e91a54e1Sdan } {1 {cannot start a transaction within a transaction}} 143e91a54e1Sdan do_test pager1-$tn.15 { sql2 { ROLLBACK } } {} 144e91a54e1Sdan 145e91a54e1Sdan # Have [db2] open a transaction and take a read-lock on the database. 146e91a54e1Sdan # Check that this prevents [db] from writing to the database (outside 147e91a54e1Sdan # of any transaction). After this fails, check that [db3] can read 148e91a54e1Sdan # the db (showing that [db] did not take a PENDING lock etc.) 149e91a54e1Sdan # 150e91a54e1Sdan do_test pager1-$tn.15 { 151e91a54e1Sdan sql2 { BEGIN; SELECT * FROM t1; } 152e91a54e1Sdan } {1 one 2 two 3 three} 153e91a54e1Sdan do_test pager1-$tn.16 { 154e91a54e1Sdan csql1 { UPDATE t1 SET a = a + 10 } 155e91a54e1Sdan } {1 {database is locked}} 156e91a54e1Sdan do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 157e91a54e1Sdan 158e91a54e1Sdan # This time, have [db] open a transaction before writing the database. 159e91a54e1Sdan # This works - [db] gets a RESERVED lock which does not conflict with 160e91a54e1Sdan # the SHARED lock [db2] is holding. 161e91a54e1Sdan # 162e91a54e1Sdan do_test pager1-$tn.18 { 163e91a54e1Sdan sql1 { 164e91a54e1Sdan BEGIN; 165e91a54e1Sdan UPDATE t1 SET a = a + 10; 166e91a54e1Sdan } 167e91a54e1Sdan } {} 168e91a54e1Sdan do_test pager1-$tn-19 { 169e91a54e1Sdan sql1 { PRAGMA lock_status } 170e91a54e1Sdan } {main reserved temp closed} 171e91a54e1Sdan do_test pager1-$tn-20 { 172e91a54e1Sdan sql2 { PRAGMA lock_status } 173e91a54e1Sdan } {main shared temp closed} 174e91a54e1Sdan 175e91a54e1Sdan # Check that all connections can still read the database. Only [db] sees 176e91a54e1Sdan # the updated content (as the transaction has not been committed yet). 177e91a54e1Sdan # 178e91a54e1Sdan do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} 179e91a54e1Sdan do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 180e91a54e1Sdan do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 181e91a54e1Sdan 182e91a54e1Sdan # Because [db2] still has the SHARED lock, [db] is unable to commit the 183e91a54e1Sdan # transaction. If it tries, an error is returned and the connection 184e91a54e1Sdan # upgrades to a PENDING lock. 185e91a54e1Sdan # 186e91a54e1Sdan # Once this happens, [db] can read the database and see the new content, 187e91a54e1Sdan # [db2] (still holding SHARED) can still read the old content, but [db3] 188e91a54e1Sdan # (not holding any lock) is prevented by [db]'s PENDING from reading 189e91a54e1Sdan # the database. 190e91a54e1Sdan # 191e91a54e1Sdan do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}} 192e91a54e1Sdan do_test pager1-$tn-25 { 193e91a54e1Sdan sql1 { PRAGMA lock_status } 194e91a54e1Sdan } {main pending temp closed} 195e91a54e1Sdan do_test pager1-$tn.26 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} 196e91a54e1Sdan do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 197e91a54e1Sdan do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} 198e91a54e1Sdan 199e91a54e1Sdan # Have [db2] commit its read transaction, releasing the SHARED lock it 200e91a54e1Sdan # is holding. Now, neither [db2] nor [db3] may read the database (as [db] 201e91a54e1Sdan # is still holding a PENDING). 202e91a54e1Sdan # 203e91a54e1Sdan do_test pager1-$tn.29 { sql2 { COMMIT } } {} 204e91a54e1Sdan do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}} 205e91a54e1Sdan do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} 206e91a54e1Sdan 207e91a54e1Sdan # [db] is now able to commit the transaction. Once the transaction is 208e91a54e1Sdan # committed, all three connections can read the new content. 209e91a54e1Sdan # 210e91a54e1Sdan do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {} 211e91a54e1Sdan do_test pager1-$tn.26 { sql1 { COMMIT } } {} 212e91a54e1Sdan do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three} 213e91a54e1Sdan do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three} 214e91a54e1Sdan do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three} 215d353331aSdan 216d353331aSdan # Install a busy-handler for connection [db]. 217d353331aSdan # 218d353331aSdan set ::nbusy [list] 219d353331aSdan proc busy {n} { 220d353331aSdan lappend ::nbusy $n 221d353331aSdan if {$n>5} { sql2 COMMIT } 222d353331aSdan return 0 223d353331aSdan } 224d353331aSdan db busy busy 225d353331aSdan 226d353331aSdan do_test pager1-$tn.29 { 227d353331aSdan sql1 { BEGIN ; INSERT INTO t1 VALUES('x', 'y') } 228d353331aSdan } {} 229d353331aSdan do_test pager1-$tn.30 { 230d353331aSdan sql2 { BEGIN ; SELECT * FROM t1 } 231d353331aSdan } {21 one 22 two 23 three} 232d353331aSdan do_test pager1-$tn.31 { sql1 COMMIT } {} 233d353331aSdan do_test pager1-$tn.32 { set ::nbusy } {0 1 2 3 4 5 6} 234e91a54e1Sdan} 235e91a54e1Sdan 23653f04f3bSdan#------------------------------------------------------------------------- 23753f04f3bSdan# Savepoint related test cases. 23853f04f3bSdan# 239dca321aeSdan# pager1-3.1.2.*: Force a savepoint rollback to cause the database file 240dca321aeSdan# to grow. 241dca321aeSdan# 242273f3f0dSdan# pager1-3.1.3.*: Use a journal created in synchronous=off mode as part 243273f3f0dSdan# of a savepoint rollback. 244273f3f0dSdan# 2450e986f51Sdando_test pager1-3.1.1 { 246b0ac3e3aSdan faultsim_delete_and_reopen 247b0ac3e3aSdan execsql { 248b0ac3e3aSdan CREATE TABLE t1(a PRIMARY KEY, b); 249b0ac3e3aSdan CREATE TABLE counter( 250b0ac3e3aSdan i CHECK (i<5), 251b0ac3e3aSdan u CHECK (u<10) 252b0ac3e3aSdan ); 253b0ac3e3aSdan INSERT INTO counter VALUES(0, 0); 254b0ac3e3aSdan CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN 255b0ac3e3aSdan UPDATE counter SET i = i+1; 256b0ac3e3aSdan END; 257b0ac3e3aSdan CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN 258b0ac3e3aSdan UPDATE counter SET u = u+1; 259b0ac3e3aSdan END; 260b0ac3e3aSdan } 261b0ac3e3aSdan execsql { SELECT * FROM counter } 262b0ac3e3aSdan} {0 0} 263b0ac3e3aSdan 2640e986f51Sdando_execsql_test pager1-3.1.2 { 265d353331aSdan PRAGMA cache_size = 10; 266b0ac3e3aSdan BEGIN; 267b0ac3e3aSdan INSERT INTO t1 VALUES(1, randomblob(1500)); 268b0ac3e3aSdan INSERT INTO t1 VALUES(2, randomblob(1500)); 269b0ac3e3aSdan INSERT INTO t1 VALUES(3, randomblob(1500)); 270b0ac3e3aSdan SELECT * FROM counter; 271b0ac3e3aSdan} {3 0} 2720e986f51Sdando_catchsql_test pager1-3.1.3 { 273b0ac3e3aSdan INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1 274f9c8ce3cSdrh} {1 {CHECK constraint failed: counter}} 275b0ac3e3aSdando_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0} 276b0ac3e3aSdando_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3} 277b0ac3e3aSdando_execsql_test pager1-3.6 { COMMIT } {} 278b0ac3e3aSdan 279273f3f0dSdanforeach {tn sql tcl} { 280d353331aSdan 7 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 0 } { 281273f3f0dSdan testvfs tv -default 1 282273f3f0dSdan tv devchar safe_append 283273f3f0dSdan } 284d353331aSdan 8 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 2 } { 285d353331aSdan testvfs tv -default 1 286d353331aSdan tv devchar sequential 287d353331aSdan } 288d353331aSdan 9 { PRAGMA synchronous = FULL } { } 289d353331aSdan 10 { PRAGMA synchronous = NORMAL } { } 290d353331aSdan 11 { PRAGMA synchronous = OFF } { } 291d353331aSdan 12 { PRAGMA synchronous = FULL ; PRAGMA fullfsync = 1 } { } 292d353331aSdan 13 { PRAGMA synchronous = FULL } { 293d353331aSdan testvfs tv -default 1 294d353331aSdan tv devchar sequential 295d353331aSdan } 2966b63ab47Sdan 14 { PRAGMA locking_mode = EXCLUSIVE } { 2976b63ab47Sdan } 298273f3f0dSdan} { 299273f3f0dSdan do_test pager1-3.$tn.1 { 300273f3f0dSdan eval $tcl 301dca321aeSdan faultsim_delete_and_reopen 302dca321aeSdan db func a_string a_string 303273f3f0dSdan execsql $sql 304dca321aeSdan execsql { 305dca321aeSdan PRAGMA auto_vacuum = 2; 306dca321aeSdan PRAGMA cache_size = 10; 307dca321aeSdan CREATE TABLE z(x INTEGER PRIMARY KEY, y); 308dca321aeSdan BEGIN; 309dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 310dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 2 311dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 4 312dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 8 313dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 16 314dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 32 315dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 64 316dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 128 317dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 256 318dca321aeSdan COMMIT; 319dca321aeSdan } 320dca321aeSdan execsql { PRAGMA auto_vacuum } 321dca321aeSdan } {2} 322273f3f0dSdan do_execsql_test pager1-3.$tn.2 { 323dca321aeSdan BEGIN; 324dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 325dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 326dca321aeSdan SAVEPOINT one; 327273f3f0dSdan UPDATE z SET y = NULL WHERE x>256; 328dca321aeSdan PRAGMA incremental_vacuum; 329dca321aeSdan SELECT count(*) FROM z WHERE x < 100; 330dca321aeSdan ROLLBACK TO one; 331dca321aeSdan COMMIT; 332dca321aeSdan } {99} 333dca321aeSdan 334273f3f0dSdan do_execsql_test pager1-3.$tn.3 { 335273f3f0dSdan BEGIN; 336273f3f0dSdan SAVEPOINT one; 337273f3f0dSdan UPDATE z SET y = y||x; 338273f3f0dSdan ROLLBACK TO one; 339273f3f0dSdan COMMIT; 340273f3f0dSdan SELECT count(*) FROM z; 341273f3f0dSdan } {258} 342273f3f0dSdan 343273f3f0dSdan do_execsql_test pager1-3.$tn.4 { 344273f3f0dSdan SAVEPOINT one; 345273f3f0dSdan UPDATE z SET y = y||x; 346273f3f0dSdan ROLLBACK TO one; 347273f3f0dSdan } {} 348273f3f0dSdan do_execsql_test pager1-3.$tn.5 { 349273f3f0dSdan SELECT count(*) FROM z; 350273f3f0dSdan RELEASE one; 351273f3f0dSdan PRAGMA integrity_check; 352273f3f0dSdan } {258 ok} 353273f3f0dSdan 35478f1e538Sdan do_execsql_test pager1-3.$tn.6 { 35578f1e538Sdan SAVEPOINT one; 35678f1e538Sdan RELEASE one; 35778f1e538Sdan } {} 35878f1e538Sdan 359273f3f0dSdan db close 360273f3f0dSdan catch { tv delete } 361273f3f0dSdan} 362273f3f0dSdan 36353f04f3bSdan#------------------------------------------------------------------------- 36453f04f3bSdan# Hot journal rollback related test cases. 36553f04f3bSdan# 36653f04f3bSdan# pager1.4.1.*: Test that the pager module deletes very small invalid 36753f04f3bSdan# journal files. 36853f04f3bSdan# 36953f04f3bSdan# pager1.4.2.*: Test that if the master journal pointer at the end of a 37053f04f3bSdan# hot-journal file appears to be corrupt (checksum does not 37153f04f3bSdan# compute) the associated journal is rolled back (and no 37253f04f3bSdan# xAccess() call to check for the presence of any master 37353f04f3bSdan# journal file is made). 37453f04f3bSdan# 375de4996e2Sdan# pager1.4.3.*: Test that the contents of a hot-journal are ignored if the 376de4996e2Sdan# page-size or sector-size in the journal header appear to 377de4996e2Sdan# be invalid (too large, too small or not a power of 2). 378de4996e2Sdan# 379e08341c6Sdan# pager1.4.4.*: Test hot-journal rollback of journal file with a master 380e08341c6Sdan# journal pointer generated in various "PRAGMA synchronous" 381e08341c6Sdan# modes. 382e08341c6Sdan# 383e08341c6Sdan# pager1.4.5.*: Test that hot-journal rollback stops if it encounters a 384e08341c6Sdan# journal-record for which the checksum fails. 385e08341c6Sdan# 386ec6ffc1aSdan# pager1.4.6.*: Test that when rolling back a hot-journal that contains a 387ec6ffc1aSdan# master journal pointer, the master journal file is deleted 388ec6ffc1aSdan# after all the hot-journals that refer to it are deleted. 389ec6ffc1aSdan# 390c8ce3972Sdan# pager1.4.7.*: Test that if a hot-journal file exists but a client can 391c8ce3972Sdan# open it for reading only, the database cannot be accessed and 392c8ce3972Sdan# SQLITE_CANTOPEN is returned. 393c8ce3972Sdan# 39453f04f3bSdando_test pager1.4.1.1 { 39553f04f3bSdan faultsim_delete_and_reopen 39653f04f3bSdan execsql { 39753f04f3bSdan CREATE TABLE x(y, z); 39853f04f3bSdan INSERT INTO x VALUES(1, 2); 39953f04f3bSdan } 40053f04f3bSdan set fd [open test.db-journal w] 40153f04f3bSdan puts -nonewline $fd "helloworld" 40253f04f3bSdan close $fd 40353f04f3bSdan file exists test.db-journal 40453f04f3bSdan} {1} 40553f04f3bSdando_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2} 40653f04f3bSdando_test pager1.4.1.3 { file exists test.db-journal } {0} 40753f04f3bSdan 40853f04f3bSdan# Set up a [testvfs] to snapshot the file-system just before SQLite 40953f04f3bSdan# deletes the master-journal to commit a multi-file transaction. 41053f04f3bSdan# 41153f04f3bSdan# In subsequent test cases, invoking [faultsim_restore_and_reopen] sets 41253f04f3bSdan# up the file system to contain two databases, two hot-journal files and 41353f04f3bSdan# a master-journal. 41453f04f3bSdan# 41553f04f3bSdando_test pager1.4.2.1 { 41653f04f3bSdan testvfs tstvfs -default 1 41753f04f3bSdan tstvfs filter xDelete 41853f04f3bSdan tstvfs script xDeleteCallback 41953f04f3bSdan proc xDeleteCallback {method file args} { 42053f04f3bSdan set file [file tail $file] 42153f04f3bSdan if { [string match *mj* $file] } { faultsim_save } 42253f04f3bSdan } 42353f04f3bSdan faultsim_delete_and_reopen 42453f04f3bSdan db func a_string a_string 42553f04f3bSdan execsql { 42653f04f3bSdan ATTACH 'test.db2' AS aux; 42753f04f3bSdan PRAGMA journal_mode = DELETE; 42853f04f3bSdan PRAGMA main.cache_size = 10; 42953f04f3bSdan PRAGMA aux.cache_size = 10; 43053f04f3bSdan CREATE TABLE t1(a UNIQUE, b UNIQUE); 43153f04f3bSdan CREATE TABLE aux.t2(a UNIQUE, b UNIQUE); 43253f04f3bSdan INSERT INTO t1 VALUES(a_string(200), a_string(300)); 43353f04f3bSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 43453f04f3bSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 43553f04f3bSdan INSERT INTO t2 SELECT * FROM t1; 43653f04f3bSdan BEGIN; 43753f04f3bSdan INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1; 43853f04f3bSdan INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1; 43953f04f3bSdan INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1; 44053f04f3bSdan INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1; 44153f04f3bSdan REPLACE INTO t2 SELECT * FROM t1; 44253f04f3bSdan COMMIT; 44353f04f3bSdan } 44453f04f3bSdan db close 44553f04f3bSdan tstvfs delete 44653f04f3bSdan} {} 447b2f20bfcSshaneh 448b2f20bfcSshanehif {$::tcl_platform(platform)!="windows"} { 44953f04f3bSdando_test pager1.4.2.2 { 45053f04f3bSdan faultsim_restore_and_reopen 45153f04f3bSdan execsql { 45253f04f3bSdan SELECT count(*) FROM t1; 45353f04f3bSdan PRAGMA integrity_check; 45453f04f3bSdan } 45553f04f3bSdan} {4 ok} 45653f04f3bSdando_test pager1.4.2.3 { 45753f04f3bSdan faultsim_restore_and_reopen 458fda06befSmistachkin foreach f [glob test.db-mj*] { forcedelete $f } 45953f04f3bSdan execsql { 46053f04f3bSdan SELECT count(*) FROM t1; 46153f04f3bSdan PRAGMA integrity_check; 46253f04f3bSdan } 46353f04f3bSdan} {64 ok} 46453f04f3bSdando_test pager1.4.2.4 { 46553f04f3bSdan faultsim_restore_and_reopen 4660971140bSdrh hexio_write test.db-journal [expr [file size test.db-journal]-30] 123456 46753f04f3bSdan execsql { 46853f04f3bSdan SELECT count(*) FROM t1; 46953f04f3bSdan PRAGMA integrity_check; 47053f04f3bSdan } 47153f04f3bSdan} {4 ok} 47253f04f3bSdando_test pager1.4.2.5 { 47353f04f3bSdan faultsim_restore_and_reopen 4740971140bSdrh hexio_write test.db-journal [expr [file size test.db-journal]-30] 123456 475fda06befSmistachkin foreach f [glob test.db-mj*] { forcedelete $f } 47653f04f3bSdan execsql { 47753f04f3bSdan SELECT count(*) FROM t1; 47853f04f3bSdan PRAGMA integrity_check; 47953f04f3bSdan } 48053f04f3bSdan} {4 ok} 481b2f20bfcSshaneh} 48253f04f3bSdan 483de4996e2Sdando_test pager1.4.3.1 { 484de4996e2Sdan testvfs tstvfs -default 1 485de4996e2Sdan tstvfs filter xSync 486de4996e2Sdan tstvfs script xSyncCallback 487de4996e2Sdan proc xSyncCallback {method file args} { 488de4996e2Sdan set file [file tail $file] 489de4996e2Sdan if { 0==[string match *journal $file] } { faultsim_save } 490de4996e2Sdan } 491de4996e2Sdan faultsim_delete_and_reopen 492de4996e2Sdan execsql { 493de4996e2Sdan PRAGMA journal_mode = DELETE; 494de4996e2Sdan CREATE TABLE t1(a, b); 495de4996e2Sdan INSERT INTO t1 VALUES(1, 2); 496de4996e2Sdan INSERT INTO t1 VALUES(3, 4); 497de4996e2Sdan } 498de4996e2Sdan db close 499de4996e2Sdan tstvfs delete 500de4996e2Sdan} {} 501de4996e2Sdan 502de4996e2Sdanforeach {tn ofst value result} { 503de4996e2Sdan 2 20 31 {1 2 3 4} 504de4996e2Sdan 3 20 32 {1 2 3 4} 505de4996e2Sdan 4 20 33 {1 2 3 4} 506de4996e2Sdan 5 20 65536 {1 2 3 4} 507de4996e2Sdan 6 20 131072 {1 2 3 4} 508de4996e2Sdan 509de4996e2Sdan 7 24 511 {1 2 3 4} 510de4996e2Sdan 8 24 513 {1 2 3 4} 511b2eced5dSdrh 9 24 131072 {1 2 3 4} 512de4996e2Sdan 513de4996e2Sdan 10 32 65536 {1 2} 514de4996e2Sdan} { 515de4996e2Sdan do_test pager1.4.3.$tn { 516de4996e2Sdan faultsim_restore_and_reopen 517de4996e2Sdan hexio_write test.db-journal $ofst [format %.8x $value] 518de4996e2Sdan execsql { SELECT * FROM t1 } 519de4996e2Sdan } $result 520de4996e2Sdan} 521de4996e2Sdandb close 522de4996e2Sdan 523e08341c6Sdan# Set up a VFS that snapshots the file-system just before a master journal 524e08341c6Sdan# file is deleted to commit a multi-file transaction. Specifically, the 525e08341c6Sdan# file-system is saved just before the xDelete() call to remove the 526e08341c6Sdan# master journal file from the file-system. 527e08341c6Sdan# 5286aa18c95Smistachkinset pwd [get_pwd] 529e08341c6Sdantestvfs tv -default 1 530e08341c6Sdantv script copy_on_mj_delete 531e08341c6Sdanset ::mj_filename_length 0 5328e6cf0a7Sdrhset ::mj_delete_cnt 0 533e08341c6Sdanproc copy_on_mj_delete {method filename args} { 534e08341c6Sdan if {[string match *mj* [file tail $filename]]} { 535c5484654Smistachkin # 536c5484654Smistachkin # NOTE: Is the file name relative? If so, add the length of the current 537c5484654Smistachkin # directory. 538c5484654Smistachkin # 539c5484654Smistachkin if {[is_relative_file $filename]} { 540c5484654Smistachkin set ::mj_filename_length \ 541c5484654Smistachkin [expr {[string length $filename] + [string length $::pwd]}] 542c5484654Smistachkin } else { 543e08341c6Sdan set ::mj_filename_length [string length $filename] 544c5484654Smistachkin } 545e08341c6Sdan faultsim_save 5468e6cf0a7Sdrh incr ::mj_delete_cnt 547e08341c6Sdan } 548e08341c6Sdan return SQLITE_OK 549e08341c6Sdan} 550e08341c6Sdan 551e08341c6Sdanforeach {tn1 tcl} { 552e08341c6Sdan 1 { set prefix "test.db" } 553e08341c6Sdan 2 { 554e08341c6Sdan # This test depends on the underlying VFS being able to open paths 555e08341c6Sdan # 512 bytes in length. The idea is to create a hot-journal file that 556e08341c6Sdan # contains a master-journal pointer so large that it could contain 557e08341c6Sdan # a valid page record (if the file page-size is 512 bytes). So as to 558e08341c6Sdan # make sure SQLite doesn't get confused by this. 559e08341c6Sdan # 560e08341c6Sdan set nPadding [expr 511 - $::mj_filename_length] 56133d85c9cSshaneh if {$tcl_platform(platform)=="windows"} { 56233d85c9cSshaneh # TBD need to figure out how to do this correctly for Windows!!! 56333d85c9cSshaneh set nPadding [expr 255 - $::mj_filename_length] 56433d85c9cSshaneh } 565e08341c6Sdan 566e08341c6Sdan # We cannot just create a really long database file name to open, as 567e08341c6Sdan # Linux limits a single component of a path to 255 bytes by default 568e08341c6Sdan # (and presumably other systems have limits too). So create a directory 569e08341c6Sdan # hierarchy to work in. 570e08341c6Sdan # 571e08341c6Sdan set dirname "d123456789012345678901234567890/" 572e08341c6Sdan set nDir [expr $nPadding / 32] 573e08341c6Sdan if { $nDir } { 574e08341c6Sdan set p [string repeat $dirname $nDir] 575e08341c6Sdan file mkdir $p 576e08341c6Sdan cd $p 577e08341c6Sdan } 578e08341c6Sdan 579e08341c6Sdan set padding [string repeat x [expr $nPadding %32]] 580e08341c6Sdan set prefix "test.db${padding}" 581e08341c6Sdan } 582e08341c6Sdan} { 583e08341c6Sdan eval $tcl 5848e6cf0a7Sdrh foreach {tn2 sql usesMJ} { 585e08341c6Sdan o { 586e08341c6Sdan PRAGMA main.synchronous=OFF; 587e08341c6Sdan PRAGMA aux.synchronous=OFF; 5883f94b609Sdan PRAGMA journal_mode = DELETE; 5898e6cf0a7Sdrh } 0 590e08341c6Sdan o512 { 591e08341c6Sdan PRAGMA main.synchronous=OFF; 592e08341c6Sdan PRAGMA aux.synchronous=OFF; 593e08341c6Sdan PRAGMA main.page_size = 512; 594e08341c6Sdan PRAGMA aux.page_size = 512; 5953f94b609Sdan PRAGMA journal_mode = DELETE; 5968e6cf0a7Sdrh } 0 597e08341c6Sdan n { 598e08341c6Sdan PRAGMA main.synchronous=NORMAL; 599e08341c6Sdan PRAGMA aux.synchronous=NORMAL; 6003f94b609Sdan PRAGMA journal_mode = DELETE; 6018e6cf0a7Sdrh } 1 602e08341c6Sdan f { 603e08341c6Sdan PRAGMA main.synchronous=FULL; 604e08341c6Sdan PRAGMA aux.synchronous=FULL; 6053f94b609Sdan PRAGMA journal_mode = DELETE; 6068e6cf0a7Sdrh } 1 6078e6cf0a7Sdrh w1 { 6088e6cf0a7Sdrh PRAGMA main.synchronous=NORMAL; 6098e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6108e6cf0a7Sdrh PRAGMA journal_mode = WAL; 6118e6cf0a7Sdrh } 0 6128e6cf0a7Sdrh w2 { 6138e6cf0a7Sdrh PRAGMA main.synchronous=NORMAL; 6148e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6158e6cf0a7Sdrh PRAGMA main.journal_mode=DELETE; 6168e6cf0a7Sdrh PRAGMA aux.journal_mode=WAL; 6178e6cf0a7Sdrh } 0 6188e6cf0a7Sdrh o1a { 6198e6cf0a7Sdrh PRAGMA main.synchronous=FULL; 6208e6cf0a7Sdrh PRAGMA aux.synchronous=OFF; 6218e6cf0a7Sdrh PRAGMA journal_mode=DELETE; 6228e6cf0a7Sdrh } 0 6238e6cf0a7Sdrh o1b { 6248e6cf0a7Sdrh PRAGMA main.synchronous=OFF; 6258e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6268e6cf0a7Sdrh PRAGMA journal_mode=DELETE; 6278e6cf0a7Sdrh } 0 6288e6cf0a7Sdrh m1 { 6298e6cf0a7Sdrh PRAGMA main.synchronous=NORMAL; 6308e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6318e6cf0a7Sdrh PRAGMA main.journal_mode=DELETE; 6328e6cf0a7Sdrh PRAGMA aux.journal_mode = MEMORY; 6338e6cf0a7Sdrh } 0 6348e6cf0a7Sdrh t1 { 6358e6cf0a7Sdrh PRAGMA main.synchronous=NORMAL; 6368e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6378e6cf0a7Sdrh PRAGMA main.journal_mode=DELETE; 6388e6cf0a7Sdrh PRAGMA aux.journal_mode = TRUNCATE; 6398e6cf0a7Sdrh } 1 6408e6cf0a7Sdrh p1 { 6418e6cf0a7Sdrh PRAGMA main.synchronous=NORMAL; 6428e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6438e6cf0a7Sdrh PRAGMA main.journal_mode=DELETE; 6448e6cf0a7Sdrh PRAGMA aux.journal_mode = PERSIST; 6458e6cf0a7Sdrh } 1 646e08341c6Sdan } { 647e08341c6Sdan 648e08341c6Sdan set tn "${tn1}.${tn2}" 649e08341c6Sdan 650e08341c6Sdan # Set up a connection to have two databases, test.db (main) and 651e08341c6Sdan # test.db2 (aux). Then run a multi-file transaction on them. The 652e08341c6Sdan # VFS will snapshot the file-system just before the master-journal 653e08341c6Sdan # file is deleted to commit the transaction. 654e08341c6Sdan # 655e08341c6Sdan tv filter xDelete 656e08341c6Sdan do_test pager1-4.4.$tn.1 { 6578e6cf0a7Sdrh set ::mj_delete_cnt 0 658e08341c6Sdan faultsim_delete_and_reopen $prefix 659e08341c6Sdan execsql " 660e08341c6Sdan ATTACH '${prefix}2' AS aux; 661e08341c6Sdan $sql 662e08341c6Sdan CREATE TABLE a(x); 663e08341c6Sdan CREATE TABLE aux.b(x); 664e08341c6Sdan INSERT INTO a VALUES('double-you'); 665e08341c6Sdan INSERT INTO a VALUES('why'); 666e08341c6Sdan INSERT INTO a VALUES('zed'); 667e08341c6Sdan INSERT INTO b VALUES('won'); 668e08341c6Sdan INSERT INTO b VALUES('too'); 669e08341c6Sdan INSERT INTO b VALUES('free'); 670e08341c6Sdan " 671e08341c6Sdan execsql { 672e08341c6Sdan BEGIN; 673e08341c6Sdan INSERT INTO a SELECT * FROM b WHERE rowid<=3; 674e08341c6Sdan INSERT INTO b SELECT * FROM a WHERE rowid<=3; 675e08341c6Sdan COMMIT; 676e08341c6Sdan } 677e08341c6Sdan } {} 678e08341c6Sdan tv filter {} 679e08341c6Sdan 6808e6cf0a7Sdrh # Verify that a master journal was deleted only for those cases where 6818e6cf0a7Sdrh # master journals really ought to be used 6828e6cf0a7Sdrh # 6838e6cf0a7Sdrh do_test pager1-4.4.$tn.1b { 6848e6cf0a7Sdrh set ::mj_delete_cnt 6858e6cf0a7Sdrh } $usesMJ 6868e6cf0a7Sdrh 687e08341c6Sdan # Check that the transaction was committed successfully. 688e08341c6Sdan # 689e08341c6Sdan do_execsql_test pager1-4.4.$tn.2 { 690e08341c6Sdan SELECT * FROM a 691e08341c6Sdan } {double-you why zed won too free} 692e08341c6Sdan do_execsql_test pager1-4.4.$tn.3 { 693e08341c6Sdan SELECT * FROM b 694e08341c6Sdan } {won too free double-you why zed} 695e08341c6Sdan 6968e6cf0a7Sdrh if {$usesMJ} { 697e08341c6Sdan # Restore the file-system and reopen the databases. Check that it now 698e08341c6Sdan # appears that the transaction was not committed (because the file-system 699e08341c6Sdan # was restored to the state where it had not been). 700e08341c6Sdan # 701e08341c6Sdan do_test pager1-4.4.$tn.4 { 702e08341c6Sdan faultsim_restore_and_reopen $prefix 703e08341c6Sdan execsql "ATTACH '${prefix}2' AS aux" 704e08341c6Sdan } {} 705e08341c6Sdan do_execsql_test pager1-4.4.$tn.5 {SELECT * FROM a} {double-you why zed} 706e08341c6Sdan do_execsql_test pager1-4.4.$tn.6 {SELECT * FROM b} {won too free} 7078e6cf0a7Sdrh } 708e08341c6Sdan 709e08341c6Sdan # Restore the file-system again. This time, before reopening the databases, 710e08341c6Sdan # delete the master-journal file from the file-system. It now appears that 711e08341c6Sdan # the transaction was committed (no master-journal file == no rollback). 712e08341c6Sdan # 713e08341c6Sdan do_test pager1-4.4.$tn.7 { 7148e6cf0a7Sdrh if {$::mj_delete_cnt>0} { 715e08341c6Sdan faultsim_restore_and_reopen $prefix 716fda06befSmistachkin foreach f [glob ${prefix}-mj*] { forcedelete $f } 7178e6cf0a7Sdrh } else { 7188e6cf0a7Sdrh db close 7198e6cf0a7Sdrh sqlite3 db $prefix 7208e6cf0a7Sdrh } 721e08341c6Sdan execsql "ATTACH '${prefix}2' AS aux" 7228e6cf0a7Sdrh glob -nocomplain ${prefix}-mj* 723e08341c6Sdan } {} 724e08341c6Sdan do_execsql_test pager1-4.4.$tn.8 { 725e08341c6Sdan SELECT * FROM a 726e08341c6Sdan } {double-you why zed won too free} 727e08341c6Sdan do_execsql_test pager1-4.4.$tn.9 { 728e08341c6Sdan SELECT * FROM b 729e08341c6Sdan } {won too free double-you why zed} 730e08341c6Sdan } 731e08341c6Sdan 732e08341c6Sdan cd $pwd 733e08341c6Sdan} 734e08341c6Sdandb close 735e08341c6Sdantv delete 736fda06befSmistachkinforcedelete $dirname 7370e986f51Sdan 7380e986f51Sdan# Set up a VFS to make a copy of the file-system just before deleting a 7390e986f51Sdan# journal file to commit a transaction. The transaction modifies exactly 7400e986f51Sdan# two database pages (and page 1 - the change counter). 7410e986f51Sdan# 7420e986f51Sdantestvfs tv -default 1 7430e986f51Sdantv sectorsize 512 7440e986f51Sdantv script copy_on_journal_delete 7450e986f51Sdantv filter xDelete 7460e986f51Sdanproc copy_on_journal_delete {method filename args} { 7470e986f51Sdan if {[string match *journal $filename]} faultsim_save 7480e986f51Sdan return SQLITE_OK 7490e986f51Sdan} 7500e986f51Sdanfaultsim_delete_and_reopen 7510e986f51Sdando_execsql_test pager1.4.5.1 { 7523f94b609Sdan PRAGMA journal_mode = DELETE; 7530e986f51Sdan PRAGMA page_size = 1024; 7540e986f51Sdan CREATE TABLE t1(a, b); 7550e986f51Sdan CREATE TABLE t2(a, b); 7560e986f51Sdan INSERT INTO t1 VALUES('I', 'II'); 7570e986f51Sdan INSERT INTO t2 VALUES('III', 'IV'); 7580e986f51Sdan BEGIN; 7590e986f51Sdan INSERT INTO t1 VALUES(1, 2); 7600e986f51Sdan INSERT INTO t2 VALUES(3, 4); 7610e986f51Sdan COMMIT; 7623f94b609Sdan} {delete} 7630e986f51Sdantv filter {} 7640e986f51Sdan 7650e986f51Sdan# Check the transaction was committed: 7660e986f51Sdan# 7670e986f51Sdando_execsql_test pager1.4.5.2 { 7680e986f51Sdan SELECT * FROM t1; 7690e986f51Sdan SELECT * FROM t2; 7700e986f51Sdan} {I II 1 2 III IV 3 4} 7710e986f51Sdan 772ec6ffc1aSdan# Now try four tests: 7730e986f51Sdan# 7740e986f51Sdan# pager1-4.5.3: Restore the file-system. Check that the whole transaction 7750e986f51Sdan# is rolled back. 7760e986f51Sdan# 7770e986f51Sdan# pager1-4.5.4: Restore the file-system. Corrupt the first record in the 7780e986f51Sdan# journal. Check the transaction is not rolled back. 7790e986f51Sdan# 7800e986f51Sdan# pager1-4.5.5: Restore the file-system. Corrupt the second record in the 7810e986f51Sdan# journal. Check that the first record in the transaction is 7820e986f51Sdan# played back, but not the second. 7830e986f51Sdan# 78410f5a50eSdan# pager1-4.5.6: Restore the file-system. Try to open the database with a 78510f5a50eSdan# readonly connection. This should fail, as a read-only 78610f5a50eSdan# connection cannot roll back the database file. 78710f5a50eSdan# 7880e986f51Sdanfaultsim_restore_and_reopen 7890e986f51Sdando_execsql_test pager1.4.5.3 { 7900e986f51Sdan SELECT * FROM t1; 7910e986f51Sdan SELECT * FROM t2; 7920e986f51Sdan} {I II III IV} 7930e986f51Sdanfaultsim_restore_and_reopen 7940e986f51Sdanhexio_write test.db-journal [expr 512+4+1024 - 202] 0123456789ABCDEF 7950e986f51Sdando_execsql_test pager1.4.5.4 { 7960e986f51Sdan SELECT * FROM t1; 7970e986f51Sdan SELECT * FROM t2; 7980e986f51Sdan} {I II 1 2 III IV 3 4} 7990e986f51Sdanfaultsim_restore_and_reopen 8000e986f51Sdanhexio_write test.db-journal [expr 512+4+1024+4+4+1024 - 202] 0123456789ABCDEF 8010e986f51Sdando_execsql_test pager1.4.5.5 { 8020e986f51Sdan SELECT * FROM t1; 8030e986f51Sdan SELECT * FROM t2; 8040e986f51Sdan} {I II III IV 3 4} 8050e986f51Sdan 80610f5a50eSdanfaultsim_restore_and_reopen 80710f5a50eSdandb close 80810f5a50eSdansqlite3 db test.db -readonly 1 80910f5a50eSdando_catchsql_test pager1.4.5.6 { 81010f5a50eSdan SELECT * FROM t1; 81110f5a50eSdan SELECT * FROM t2; 812b83c21e6Sdan} {1 {attempt to write a readonly database}} 813ec6ffc1aSdandb close 814ec6ffc1aSdan 815ec6ffc1aSdan# Snapshot the file-system just before multi-file commit. Save the name 816ec6ffc1aSdan# of the master journal file in $::mj_filename. 817ec6ffc1aSdan# 818ec6ffc1aSdantv script copy_on_mj_delete 819ec6ffc1aSdantv filter xDelete 820ec6ffc1aSdanproc copy_on_mj_delete {method filename args} { 821ec6ffc1aSdan if {[string match *mj* [file tail $filename]]} { 822ec6ffc1aSdan set ::mj_filename $filename 823ec6ffc1aSdan faultsim_save 824ec6ffc1aSdan } 825ec6ffc1aSdan return SQLITE_OK 826ec6ffc1aSdan} 827ec6ffc1aSdando_test pager1.4.6.1 { 828ec6ffc1aSdan faultsim_delete_and_reopen 829ec6ffc1aSdan execsql { 8303f94b609Sdan PRAGMA journal_mode = DELETE; 831ec6ffc1aSdan ATTACH 'test.db2' AS two; 832ec6ffc1aSdan CREATE TABLE t1(a, b); 833ec6ffc1aSdan CREATE TABLE two.t2(a, b); 834ec6ffc1aSdan INSERT INTO t1 VALUES(1, 't1.1'); 835ec6ffc1aSdan INSERT INTO t2 VALUES(1, 't2.1'); 836ec6ffc1aSdan BEGIN; 837ec6ffc1aSdan UPDATE t1 SET b = 't1.2'; 838ec6ffc1aSdan UPDATE t2 SET b = 't2.2'; 839ec6ffc1aSdan COMMIT; 840ec6ffc1aSdan } 841ec6ffc1aSdan tv filter {} 842ec6ffc1aSdan db close 843ec6ffc1aSdan} {} 844ec6ffc1aSdan 845ec6ffc1aSdanfaultsim_restore_and_reopen 846ec6ffc1aSdando_execsql_test pager1.4.6.2 { SELECT * FROM t1 } {1 t1.1} 847ec6ffc1aSdando_test pager1.4.6.3 { file exists $::mj_filename } {1} 848ec6ffc1aSdando_execsql_test pager1.4.6.4 { 849ec6ffc1aSdan ATTACH 'test.db2' AS two; 850ec6ffc1aSdan SELECT * FROM t2; 851ec6ffc1aSdan} {1 t2.1} 852ec6ffc1aSdando_test pager1.4.6.5 { file exists $::mj_filename } {0} 853ec6ffc1aSdan 854ec6ffc1aSdanfaultsim_restore_and_reopen 855ec6ffc1aSdandb close 856ec6ffc1aSdando_test pager1.4.6.8 { 857ec6ffc1aSdan set ::mj_filename1 $::mj_filename 858ec6ffc1aSdan tv filter xDelete 859ec6ffc1aSdan sqlite3 db test.db2 860ec6ffc1aSdan execsql { 8613f94b609Sdan PRAGMA journal_mode = DELETE; 862ec6ffc1aSdan ATTACH 'test.db3' AS three; 863ec6ffc1aSdan CREATE TABLE three.t3(a, b); 864ec6ffc1aSdan INSERT INTO t3 VALUES(1, 't3.1'); 865ec6ffc1aSdan BEGIN; 866ec6ffc1aSdan UPDATE t2 SET b = 't2.3'; 867ec6ffc1aSdan UPDATE t3 SET b = 't3.3'; 868ec6ffc1aSdan COMMIT; 869ec6ffc1aSdan } 870ec6ffc1aSdan expr {$::mj_filename1 != $::mj_filename} 871ec6ffc1aSdan} {1} 872ec6ffc1aSdanfaultsim_restore_and_reopen 873ec6ffc1aSdantv filter {} 874ec6ffc1aSdan 875ec6ffc1aSdan# The file-system now contains: 876ec6ffc1aSdan# 877ec6ffc1aSdan# * three databases 878ec6ffc1aSdan# * three hot-journal files 879ec6ffc1aSdan# * two master-journal files. 880ec6ffc1aSdan# 881ec6ffc1aSdan# The hot-journals associated with test.db2 and test.db3 point to 882ec6ffc1aSdan# master journal $::mj_filename. The hot-journal file associated with 883ec6ffc1aSdan# test.db points to master journal $::mj_filename1. So reading from 884ec6ffc1aSdan# test.db should delete $::mj_filename1. 885ec6ffc1aSdan# 886ec6ffc1aSdando_test pager1.4.6.9 { 887ec6ffc1aSdan lsort [glob test.db*] 888ec6ffc1aSdan} [lsort [list \ 889ec6ffc1aSdan test.db test.db2 test.db3 \ 890ec6ffc1aSdan test.db-journal test.db2-journal test.db3-journal \ 891ec6ffc1aSdan [file tail $::mj_filename] [file tail $::mj_filename1] 892ec6ffc1aSdan]] 893ec6ffc1aSdan 894ec6ffc1aSdan# The master-journal $::mj_filename1 contains pointers to test.db and 895ec6ffc1aSdan# test.db2. However the hot-journal associated with test.db2 points to 896ec6ffc1aSdan# a different master-journal. Therefore, reading from test.db only should 897ec6ffc1aSdan# be enough to cause SQLite to delete $::mj_filename1. 898ec6ffc1aSdan# 899ec6ffc1aSdando_test pager1.4.6.10 { file exists $::mj_filename } {1} 900ec6ffc1aSdando_test pager1.4.6.11 { file exists $::mj_filename1 } {1} 901ec6ffc1aSdando_execsql_test pager1.4.6.12 { SELECT * FROM t1 } {1 t1.1} 902ec6ffc1aSdando_test pager1.4.6.13 { file exists $::mj_filename } {1} 903ec6ffc1aSdando_test pager1.4.6.14 { file exists $::mj_filename1 } {0} 904ec6ffc1aSdan 905ec6ffc1aSdando_execsql_test pager1.4.6.12 { 906ec6ffc1aSdan ATTACH 'test.db2' AS two; 907ec6ffc1aSdan SELECT * FROM t2; 908ec6ffc1aSdan} {1 t2.1} 909ec6ffc1aSdando_test pager1.4.6.13 { file exists $::mj_filename } {1} 910ec6ffc1aSdando_execsql_test pager1.4.6.14 { 911ec6ffc1aSdan ATTACH 'test.db3' AS three; 912ec6ffc1aSdan SELECT * FROM t3; 913ec6ffc1aSdan} {1 t3.1} 914ec6ffc1aSdando_test pager1.4.6.15 { file exists $::mj_filename } {0} 91510f5a50eSdan 9160e986f51Sdandb close 9170e986f51Sdantv delete 918e08341c6Sdan 919c8ce3972Sdantestvfs tv -default 1 920c8ce3972Sdantv sectorsize 512 921c8ce3972Sdantv script copy_on_journal_delete 922c8ce3972Sdantv filter xDelete 923c8ce3972Sdanproc copy_on_journal_delete {method filename args} { 924c8ce3972Sdan if {[string match *journal $filename]} faultsim_save 925c8ce3972Sdan return SQLITE_OK 926c8ce3972Sdan} 927c8ce3972Sdanfaultsim_delete_and_reopen 928c8ce3972Sdando_execsql_test pager1.4.7.1 { 9293f94b609Sdan PRAGMA journal_mode = DELETE; 930c8ce3972Sdan CREATE TABLE t1(x PRIMARY KEY, y); 931c8ce3972Sdan CREATE INDEX i1 ON t1(y); 932c8ce3972Sdan INSERT INTO t1 VALUES('I', 'one'); 933c8ce3972Sdan INSERT INTO t1 VALUES('II', 'four'); 934c8ce3972Sdan INSERT INTO t1 VALUES('III', 'nine'); 935c8ce3972Sdan BEGIN; 936c8ce3972Sdan INSERT INTO t1 VALUES('IV', 'sixteen'); 937c8ce3972Sdan INSERT INTO t1 VALUES('V' , 'twentyfive'); 938c8ce3972Sdan COMMIT; 9393f94b609Sdan} {delete} 940c8ce3972Sdantv filter {} 941c8ce3972Sdandb close 942c8ce3972Sdantv delete 943e1186ab2Sdrhcatch { 944e1186ab2Sdrh test_syscall install fchmod 945e1186ab2Sdrh test_syscall fault 1 1 946e1186ab2Sdrh} 947c8ce3972Sdando_test pager1.4.7.2 { 948c8ce3972Sdan faultsim_restore_and_reopen 949c8ce3972Sdan catch {file attributes test.db-journal -permissions r--------} 950c8ce3972Sdan catch {file attributes test.db-journal -readonly 1} 951c8ce3972Sdan catchsql { SELECT * FROM t1 } 952c8ce3972Sdan} {1 {unable to open database file}} 953e1186ab2Sdrhcatch { 954e1186ab2Sdrh test_syscall reset 955e1186ab2Sdrh test_syscall fault 0 0 956e1186ab2Sdrh} 957c8ce3972Sdando_test pager1.4.7.3 { 958c8ce3972Sdan db close 959c8ce3972Sdan catch {file attributes test.db-journal -permissions rw-rw-rw-} 960c8ce3972Sdan catch {file attributes test.db-journal -readonly 0} 961fda06befSmistachkin delete_file test.db-journal 962c8ce3972Sdan file exists test.db-journal 963c8ce3972Sdan} {0} 964421377e6Sdrhdo_test pager1.4.8.1 { 965421377e6Sdrh catch {file attributes test.db -permissions r--------} 966421377e6Sdrh catch {file attributes test.db -readonly 1} 967421377e6Sdrh sqlite3 db test.db 968421377e6Sdrh db eval { SELECT * FROM t1 } 969421377e6Sdrh sqlite3_db_readonly db main 970421377e6Sdrh} {1} 971421377e6Sdrhdo_test pager1.4.8.2 { 972421377e6Sdrh sqlite3_db_readonly db xyz 973421377e6Sdrh} {-1} 974421377e6Sdrhdo_test pager1.4.8.3 { 975421377e6Sdrh db close 976421377e6Sdrh catch {file attributes test.db -readonly 0} 977db0ad5f2Sdan catch {file attributes test.db -permissions rw-rw-rw-} msg 978421377e6Sdrh sqlite3 db test.db 979421377e6Sdrh db eval { SELECT * FROM t1 } 980421377e6Sdrh sqlite3_db_readonly db main 981421377e6Sdrh} {0} 982c8ce3972Sdan 983de4996e2Sdan#------------------------------------------------------------------------- 984146ed78bSdan# The following tests deal with multi-file commits. 985de4996e2Sdan# 986146ed78bSdan# pager1-5.1.*: The case where a multi-file cannot be committed because 987146ed78bSdan# another connection is holding a SHARED lock on one of the 988146ed78bSdan# files. After the SHARED lock is removed, the COMMIT succeeds. 989146ed78bSdan# 990146ed78bSdan# pager1-5.2.*: Multi-file commits with journal_mode=memory. 991146ed78bSdan# 992146ed78bSdan# pager1-5.3.*: Multi-file commits with journal_mode=memory. 993146ed78bSdan# 994146ed78bSdan# pager1-5.4.*: Check that with synchronous=normal, the master-journal file 995146ed78bSdan# name is added to a journal file immediately after the last 996146ed78bSdan# journal record. But with synchronous=full, extra unused space 997146ed78bSdan# is allocated between the last journal record and the 998146ed78bSdan# master-journal file name so that the master-journal file 999146ed78bSdan# name does not lie on the same sector as the last journal file 1000146ed78bSdan# record. 1001146ed78bSdan# 1002e08341c6Sdan# pager1-5.5.*: Check that in journal_mode=PERSIST mode, a journal file is 1003e08341c6Sdan# truncated to zero bytes when a multi-file transaction is 1004e08341c6Sdan# committed (instead of the first couple of bytes being zeroed). 1005e08341c6Sdan# 1006146ed78bSdan# 1007146ed78bSdando_test pager1-5.1.1 { 1008146ed78bSdan faultsim_delete_and_reopen 1009146ed78bSdan execsql { 1010146ed78bSdan ATTACH 'test.db2' AS aux; 1011146ed78bSdan CREATE TABLE t1(a, b); 1012146ed78bSdan CREATE TABLE aux.t2(a, b); 1013146ed78bSdan INSERT INTO t1 VALUES(17, 'Lenin'); 1014146ed78bSdan INSERT INTO t1 VALUES(22, 'Stalin'); 1015146ed78bSdan INSERT INTO t1 VALUES(53, 'Khrushchev'); 1016146ed78bSdan } 1017146ed78bSdan} {} 1018146ed78bSdando_test pager1-5.1.2 { 1019146ed78bSdan execsql { 1020146ed78bSdan BEGIN; 1021146ed78bSdan INSERT INTO t1 VALUES(64, 'Brezhnev'); 1022146ed78bSdan INSERT INTO t2 SELECT * FROM t1; 1023146ed78bSdan } 1024146ed78bSdan sqlite3 db2 test.db2 1025146ed78bSdan execsql { 1026146ed78bSdan BEGIN; 1027146ed78bSdan SELECT * FROM t2; 1028146ed78bSdan } db2 1029146ed78bSdan} {} 1030146ed78bSdando_test pager1-5.1.3 { 1031146ed78bSdan catchsql COMMIT 1032146ed78bSdan} {1 {database is locked}} 1033146ed78bSdando_test pager1-5.1.4 { 1034146ed78bSdan execsql COMMIT db2 1035146ed78bSdan execsql COMMIT 1036146ed78bSdan execsql { SELECT * FROM t2 } db2 1037146ed78bSdan} {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev} 1038146ed78bSdando_test pager1-5.1.5 { 1039146ed78bSdan db2 close 1040146ed78bSdan} {} 1041146ed78bSdan 1042146ed78bSdando_test pager1-5.2.1 { 1043146ed78bSdan execsql { 1044146ed78bSdan PRAGMA journal_mode = memory; 1045146ed78bSdan BEGIN; 1046146ed78bSdan INSERT INTO t1 VALUES(84, 'Andropov'); 1047146ed78bSdan INSERT INTO t2 VALUES(84, 'Andropov'); 1048146ed78bSdan COMMIT; 1049146ed78bSdan } 1050146ed78bSdan} {memory} 1051146ed78bSdando_test pager1-5.3.1 { 1052146ed78bSdan execsql { 1053146ed78bSdan PRAGMA journal_mode = off; 1054146ed78bSdan BEGIN; 1055146ed78bSdan INSERT INTO t1 VALUES(85, 'Gorbachev'); 1056146ed78bSdan INSERT INTO t2 VALUES(85, 'Gorbachev'); 1057146ed78bSdan COMMIT; 1058146ed78bSdan } 1059146ed78bSdan} {off} 1060146ed78bSdan 1061146ed78bSdando_test pager1-5.4.1 { 1062146ed78bSdan db close 1063146ed78bSdan testvfs tv 1064146ed78bSdan sqlite3 db test.db -vfs tv 1065146ed78bSdan execsql { ATTACH 'test.db2' AS aux } 1066146ed78bSdan 1067146ed78bSdan tv filter xDelete 1068146ed78bSdan tv script max_journal_size 1069146ed78bSdan tv sectorsize 512 1070146ed78bSdan set ::max_journal 0 1071146ed78bSdan proc max_journal_size {method args} { 1072146ed78bSdan set sz 0 1073146ed78bSdan catch { set sz [file size test.db-journal] } 1074146ed78bSdan if {$sz > $::max_journal} { 1075146ed78bSdan set ::max_journal $sz 1076146ed78bSdan } 1077146ed78bSdan return SQLITE_OK 1078146ed78bSdan } 1079146ed78bSdan execsql { 1080146ed78bSdan PRAGMA journal_mode = DELETE; 1081146ed78bSdan PRAGMA synchronous = NORMAL; 1082146ed78bSdan BEGIN; 1083146ed78bSdan INSERT INTO t1 VALUES(85, 'Gorbachev'); 1084146ed78bSdan INSERT INTO t2 VALUES(85, 'Gorbachev'); 1085146ed78bSdan COMMIT; 1086146ed78bSdan } 10877f9026ddSdan 10887f9026ddSdan # The size of the journal file is now: 10897f9026ddSdan # 10907f9026ddSdan # 1) 512 byte header + 10917f9026ddSdan # 2) 2 * (1024+8) byte records + 10927f9026ddSdan # 3) 20+N bytes of master-journal pointer, where N is the size of 10937f9026ddSdan # the master-journal name encoded as utf-8 with no nul term. 10947f9026ddSdan # 10957f9026ddSdan set mj_pointer [expr { 1096c5484654Smistachkin 20 + [string length "test.db-mjXXXXXX9XX"] 10977f9026ddSdan }] 1098c5484654Smistachkin # 1099c5484654Smistachkin # NOTE: For item 3 above, if the current SQLite VFS lacks the concept of a 1100c5484654Smistachkin # current directory, the length of the current directory name plus 1 1101c5484654Smistachkin # character for the directory separator character are NOT counted as 1102c5484654Smistachkin # part of the total size; otherwise, they are. 1103c5484654Smistachkin # 1104c5484654Smistachkin ifcapable curdir { 11056aa18c95Smistachkin set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}] 1106c5484654Smistachkin } 11077f9026ddSdan expr {$::max_journal==(512+2*(1024+8)+$mj_pointer)} 11087f9026ddSdan} 1 1109146ed78bSdando_test pager1-5.4.2 { 1110146ed78bSdan set ::max_journal 0 1111146ed78bSdan execsql { 1112146ed78bSdan PRAGMA synchronous = full; 1113146ed78bSdan BEGIN; 1114146ed78bSdan DELETE FROM t1 WHERE b = 'Lenin'; 1115146ed78bSdan DELETE FROM t2 WHERE b = 'Lenin'; 1116146ed78bSdan COMMIT; 1117146ed78bSdan } 11187f9026ddSdan 11197f9026ddSdan # In synchronous=full mode, the master-journal pointer is not written 11207f9026ddSdan # directly after the last record in the journal file. Instead, it is 11217f9026ddSdan # written starting at the next (in this case 512 byte) sector boundary. 11227f9026ddSdan # 11237f9026ddSdan set mj_pointer [expr { 1124c5484654Smistachkin 20 + [string length "test.db-mjXXXXXX9XX"] 11257f9026ddSdan }] 1126c5484654Smistachkin # 1127c5484654Smistachkin # NOTE: If the current SQLite VFS lacks the concept of a current directory, 1128c5484654Smistachkin # the length of the current directory name plus 1 character for the 1129c5484654Smistachkin # directory separator character are NOT counted as part of the total 1130c5484654Smistachkin # size; otherwise, they are. 1131c5484654Smistachkin # 1132c5484654Smistachkin ifcapable curdir { 11336aa18c95Smistachkin set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}] 1134c5484654Smistachkin } 11357f9026ddSdan expr {$::max_journal==(((512+2*(1024+8)+511)/512)*512 + $mj_pointer)} 11367f9026ddSdan} 1 1137146ed78bSdandb close 1138146ed78bSdantv delete 1139146ed78bSdan 1140146ed78bSdando_test pager1-5.5.1 { 1141146ed78bSdan sqlite3 db test.db 1142146ed78bSdan execsql { 1143146ed78bSdan ATTACH 'test.db2' AS aux; 1144146ed78bSdan PRAGMA journal_mode = PERSIST; 1145146ed78bSdan CREATE TABLE t3(a, b); 1146146ed78bSdan INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1; 1147146ed78bSdan UPDATE t3 SET b = randomblob(1500); 1148146ed78bSdan } 1149146ed78bSdan expr [file size test.db-journal] > 15000 1150146ed78bSdan} {1} 1151146ed78bSdando_test pager1-5.5.2 { 1152146ed78bSdan execsql { 1153146ed78bSdan PRAGMA synchronous = full; 1154146ed78bSdan BEGIN; 1155146ed78bSdan DELETE FROM t1 WHERE b = 'Stalin'; 1156146ed78bSdan DELETE FROM t2 WHERE b = 'Stalin'; 1157146ed78bSdan COMMIT; 1158146ed78bSdan } 1159146ed78bSdan file size test.db-journal 1160146ed78bSdan} {0} 1161146ed78bSdan 1162146ed78bSdan 1163146ed78bSdan#------------------------------------------------------------------------- 1164146ed78bSdan# The following tests work with "PRAGMA max_page_count" 1165146ed78bSdan# 1166146ed78bSdando_test pager1-6.1 { 1167146ed78bSdan faultsim_delete_and_reopen 1168146ed78bSdan execsql { 1169f43d7fceSdan PRAGMA auto_vacuum = none; 1170146ed78bSdan PRAGMA max_page_count = 10; 1171146ed78bSdan CREATE TABLE t2(a, b); 1172146ed78bSdan CREATE TABLE t3(a, b); 1173146ed78bSdan CREATE TABLE t4(a, b); 1174146ed78bSdan CREATE TABLE t5(a, b); 1175146ed78bSdan CREATE TABLE t6(a, b); 1176146ed78bSdan CREATE TABLE t7(a, b); 1177146ed78bSdan CREATE TABLE t8(a, b); 1178146ed78bSdan CREATE TABLE t9(a, b); 1179146ed78bSdan CREATE TABLE t10(a, b); 1180146ed78bSdan } 1181146ed78bSdan} {10} 1182d353331aSdando_catchsql_test pager1-6.2 { 1183d353331aSdan CREATE TABLE t11(a, b) 1184146ed78bSdan} {1 {database or disk is full}} 1185d353331aSdando_execsql_test pager1-6.4 { PRAGMA max_page_count } {10} 1186d353331aSdando_execsql_test pager1-6.5 { PRAGMA max_page_count = 15 } {15} 1187d353331aSdando_execsql_test pager1-6.6 { CREATE TABLE t11(a, b) } {} 1188d353331aSdando_execsql_test pager1-6.7 { 1189d353331aSdan BEGIN; 1190d353331aSdan INSERT INTO t11 VALUES(1, 2); 1191d353331aSdan PRAGMA max_page_count = 13; 1192d353331aSdan} {13} 1193d353331aSdando_execsql_test pager1-6.8 { 1194d353331aSdan INSERT INTO t11 VALUES(3, 4); 1195d353331aSdan PRAGMA max_page_count = 10; 1196d353331aSdan} {11} 1197d353331aSdando_execsql_test pager1-6.9 { COMMIT } {} 1198de4996e2Sdan 119960ac3f42Sdrhdo_execsql_test pager1-6.10 { PRAGMA max_page_count = 10 } {11} 120022b328b2Sdando_execsql_test pager1-6.11 { SELECT * FROM t11 } {1 2 3 4} 120122b328b2Sdando_execsql_test pager1-6.12 { PRAGMA max_page_count } {11} 120222b328b2Sdan 1203153eda0aSdan 1204153eda0aSdan#------------------------------------------------------------------------- 1205153eda0aSdan# The following tests work with "PRAGMA journal_mode=TRUNCATE" and 1206153eda0aSdan# "PRAGMA locking_mode=EXCLUSIVE". 1207153eda0aSdan# 1208153eda0aSdan# Each test is specified with 5 variables. As follows: 1209153eda0aSdan# 1210153eda0aSdan# $tn: Test Number. Used as part of the [do_test] test names. 1211153eda0aSdan# $sql: SQL to execute. 1212153eda0aSdan# $res: Expected result of executing $sql. 1213153eda0aSdan# $js: The expected size of the journal file, in bytes, after executing 1214153eda0aSdan# the SQL script. Or -1 if the journal is not expected to exist. 1215153eda0aSdan# $ws: The expected size of the WAL file, in bytes, after executing 1216153eda0aSdan# the SQL script. Or -1 if the WAL is not expected to exist. 1217153eda0aSdan# 121838e1a279Sdanifcapable wal { 1219153eda0aSdan faultsim_delete_and_reopen 1220153eda0aSdan foreach {tn sql res js ws} [subst { 1221153eda0aSdan 1222153eda0aSdan 1 { 1223153eda0aSdan CREATE TABLE t1(a, b); 1224153eda0aSdan PRAGMA auto_vacuum=OFF; 1225153eda0aSdan PRAGMA synchronous=NORMAL; 1226153eda0aSdan PRAGMA page_size=1024; 1227153eda0aSdan PRAGMA locking_mode=EXCLUSIVE; 1228153eda0aSdan PRAGMA journal_mode=TRUNCATE; 1229153eda0aSdan INSERT INTO t1 VALUES(1, 2); 1230153eda0aSdan } {exclusive truncate} 0 -1 1231153eda0aSdan 1232153eda0aSdan 2 { 1233153eda0aSdan BEGIN IMMEDIATE; 1234153eda0aSdan SELECT * FROM t1; 1235153eda0aSdan COMMIT; 1236153eda0aSdan } {1 2} 0 -1 1237153eda0aSdan 1238153eda0aSdan 3 { 1239153eda0aSdan BEGIN; 1240153eda0aSdan SELECT * FROM t1; 1241153eda0aSdan COMMIT; 1242153eda0aSdan } {1 2} 0 -1 1243153eda0aSdan 1244153eda0aSdan 4 { PRAGMA journal_mode = WAL } wal -1 -1 1245153eda0aSdan 5 { INSERT INTO t1 VALUES(3, 4) } {} -1 [wal_file_size 1 1024] 12468c408004Sdan 6 { PRAGMA locking_mode = NORMAL } exclusive -1 [wal_file_size 1 1024] 1247153eda0aSdan 7 { INSERT INTO t1 VALUES(5, 6); } {} -1 [wal_file_size 2 1024] 1248153eda0aSdan 1249153eda0aSdan 8 { PRAGMA journal_mode = TRUNCATE } truncate 0 -1 1250153eda0aSdan 9 { INSERT INTO t1 VALUES(7, 8) } {} 0 -1 1251153eda0aSdan 10 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8} 0 -1 1252153eda0aSdan 1253153eda0aSdan }] { 1254153eda0aSdan do_execsql_test pager1-7.1.$tn.1 $sql $res 1255153eda0aSdan catch { set J -1 ; set J [file size test.db-journal] } 1256153eda0aSdan catch { set W -1 ; set W [file size test.db-wal] } 1257153eda0aSdan do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws] 1258153eda0aSdan } 125938e1a279Sdan} 1260153eda0aSdan 126189ccf448Sdando_test pager1-7.2.1 { 126289ccf448Sdan faultsim_delete_and_reopen 126389ccf448Sdan execsql { 126489ccf448Sdan PRAGMA locking_mode = EXCLUSIVE; 126589ccf448Sdan CREATE TABLE t1(a, b); 126689ccf448Sdan BEGIN; 126789ccf448Sdan PRAGMA journal_mode = delete; 126889ccf448Sdan PRAGMA journal_mode = truncate; 126989ccf448Sdan } 127089ccf448Sdan} {exclusive delete truncate} 127189ccf448Sdando_test pager1-7.2.2 { 127289ccf448Sdan execsql { INSERT INTO t1 VALUES(1, 2) } 127389ccf448Sdan execsql { PRAGMA journal_mode = persist } 127489ccf448Sdan} {truncate} 127589ccf448Sdando_test pager1-7.2.3 { 127689ccf448Sdan execsql { COMMIT } 127789ccf448Sdan execsql { 127889ccf448Sdan PRAGMA journal_mode = persist; 127989ccf448Sdan PRAGMA journal_size_limit; 128089ccf448Sdan } 128189ccf448Sdan} {persist -1} 128289ccf448Sdan 1283d353331aSdan#------------------------------------------------------------------------- 1284d353331aSdan# The following tests, pager1-8.*, test that the special filenames 1285d353331aSdan# ":memory:" and "" open temporary databases. 1286d353331aSdan# 12870e986f51Sdanforeach {tn filename} { 12880e986f51Sdan 1 :memory: 12890e986f51Sdan 2 "" 12900e986f51Sdan} { 12910e986f51Sdan do_test pager1-8.$tn.1 { 1292153eda0aSdan faultsim_delete_and_reopen 1293153eda0aSdan db close 12940e986f51Sdan sqlite3 db $filename 1295153eda0aSdan execsql { 1296c8ce3972Sdan PRAGMA auto_vacuum = 1; 1297153eda0aSdan CREATE TABLE x1(x); 1298153eda0aSdan INSERT INTO x1 VALUES('Charles'); 1299153eda0aSdan INSERT INTO x1 VALUES('James'); 1300153eda0aSdan INSERT INTO x1 VALUES('Mary'); 1301153eda0aSdan SELECT * FROM x1; 1302153eda0aSdan } 1303153eda0aSdan } {Charles James Mary} 13040e986f51Sdan 13050e986f51Sdan do_test pager1-8.$tn.2 { 13060e986f51Sdan sqlite3 db2 $filename 13070e986f51Sdan catchsql { SELECT * FROM x1 } db2 1308153eda0aSdan } {1 {no such table: x1}} 1309153eda0aSdan 13100e986f51Sdan do_execsql_test pager1-8.$tn.3 { 13110e986f51Sdan BEGIN; 13120e986f51Sdan INSERT INTO x1 VALUES('William'); 13130e986f51Sdan INSERT INTO x1 VALUES('Anne'); 13140e986f51Sdan ROLLBACK; 13150e986f51Sdan } {} 13160e986f51Sdan} 13170e986f51Sdan 1318dca321aeSdan#------------------------------------------------------------------------- 1319dca321aeSdan# The next block of tests - pager1-9.* - deal with interactions between 1320dca321aeSdan# the pager and the backup API. Test cases: 1321dca321aeSdan# 1322dca321aeSdan# pager1-9.1.*: Test that a backup completes successfully even if the 1323dca321aeSdan# source db is written to during the backup op. 1324dca321aeSdan# 1325dca321aeSdan# pager1-9.2.*: Test that a backup completes successfully even if the 1326dca321aeSdan# source db is written to and then rolled back during a 1327dca321aeSdan# backup operation. 1328dca321aeSdan# 1329dca321aeSdando_test pager1-9.0.1 { 1330dca321aeSdan faultsim_delete_and_reopen 1331dca321aeSdan db func a_string a_string 1332dca321aeSdan execsql { 1333dca321aeSdan PRAGMA cache_size = 10; 1334dca321aeSdan BEGIN; 1335dca321aeSdan CREATE TABLE ab(a, b, UNIQUE(a, b)); 1336dca321aeSdan INSERT INTO ab VALUES( a_string(200), a_string(300) ); 1337dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1338dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1339dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1340dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1341dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1342dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1343dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1344dca321aeSdan COMMIT; 1345dca321aeSdan } 1346dca321aeSdan} {} 1347dca321aeSdando_test pager1-9.0.2 { 1348dca321aeSdan sqlite3 db2 test.db2 1349dca321aeSdan db2 eval { PRAGMA cache_size = 10 } 1350dca321aeSdan sqlite3_backup B db2 main db main 1351dca321aeSdan list [B step 10000] [B finish] 1352dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1353dca321aeSdando_test pager1-9.0.3 { 1354dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1355dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1356dca321aeSdan 1357dca321aeSdando_test pager1-9.1.1 { 1358dca321aeSdan execsql { UPDATE ab SET a = a_string(201) } 1359dca321aeSdan sqlite3_backup B db2 main db main 1360dca321aeSdan B step 30 1361dca321aeSdan} {SQLITE_OK} 1362dca321aeSdando_test pager1-9.1.2 { 1363dca321aeSdan execsql { UPDATE ab SET b = a_string(301) } 1364dca321aeSdan list [B step 10000] [B finish] 1365dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1366dca321aeSdando_test pager1-9.1.3 { 1367dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1368dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1369dca321aeSdando_test pager1-9.1.4 { execsql { SELECT count(*) FROM ab } } {128} 1370dca321aeSdan 1371dca321aeSdando_test pager1-9.2.1 { 1372dca321aeSdan execsql { UPDATE ab SET a = a_string(202) } 1373dca321aeSdan sqlite3_backup B db2 main db main 1374dca321aeSdan B step 30 1375dca321aeSdan} {SQLITE_OK} 1376dca321aeSdando_test pager1-9.2.2 { 1377dca321aeSdan execsql { 1378dca321aeSdan BEGIN; 1379dca321aeSdan UPDATE ab SET b = a_string(301); 1380dca321aeSdan ROLLBACK; 1381dca321aeSdan } 1382dca321aeSdan list [B step 10000] [B finish] 1383dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1384dca321aeSdando_test pager1-9.2.3 { 1385dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1386dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1387dca321aeSdando_test pager1-9.2.4 { execsql { SELECT count(*) FROM ab } } {128} 1388ec6ffc1aSdandb close 1389ec6ffc1aSdandb2 close 1390ec6ffc1aSdan 1391c396d4afSdando_test pager1-9.3.1 { 1392c396d4afSdan testvfs tv -default 1 1393c396d4afSdan tv sectorsize 4096 1394c396d4afSdan faultsim_delete_and_reopen 1395c396d4afSdan 1396c396d4afSdan execsql { PRAGMA page_size = 1024 } 1397c396d4afSdan for {set ii 0} {$ii < 4} {incr ii} { execsql "CREATE TABLE t${ii}(a, b)" } 1398c396d4afSdan} {} 1399*4a8a6467Sdrhif {[nonzero_reserved_bytes]} { 1400*4a8a6467Sdrh # backup with a page size changes is not possible with the codec 1401*4a8a6467Sdrh # 1402*4a8a6467Sdrh do_test pager1-9.3.2codec { 1403c396d4afSdan sqlite3 db2 test.db2 1404c396d4afSdan execsql { 1405c396d4afSdan PRAGMA page_size = 4096; 1406c396d4afSdan PRAGMA synchronous = OFF; 1407c396d4afSdan CREATE TABLE t1(a, b); 1408c396d4afSdan CREATE TABLE t2(a, b); 1409c396d4afSdan } db2 1410*4a8a6467Sdrh sqlite3_backup B db2 main db main 1411*4a8a6467Sdrh B step 30 1412*4a8a6467Sdrh list [B step 10000] [B finish] 1413*4a8a6467Sdrh } {SQLITE_READONLY SQLITE_READONLY} 1414*4a8a6467Sdrh do_test pager1-9.3.3codec { 1415*4a8a6467Sdrh db2 close 1416*4a8a6467Sdrh db close 1417*4a8a6467Sdrh tv delete 1418*4a8a6467Sdrh file size test.db2 1419*4a8a6467Sdrh } [file size test.db2] 1420*4a8a6467Sdrh} else { 1421*4a8a6467Sdrh do_test pager1-9.3.2 { 1422*4a8a6467Sdrh sqlite3 db2 test.db2 1423*4a8a6467Sdrh execsql { 1424*4a8a6467Sdrh PRAGMA page_size = 4096; 1425*4a8a6467Sdrh PRAGMA synchronous = OFF; 1426*4a8a6467Sdrh CREATE TABLE t1(a, b); 1427*4a8a6467Sdrh CREATE TABLE t2(a, b); 1428*4a8a6467Sdrh } db2 1429c396d4afSdan sqlite3_backup B db2 main db main 1430c396d4afSdan B step 30 1431c396d4afSdan list [B step 10000] [B finish] 1432c396d4afSdan } {SQLITE_DONE SQLITE_OK} 1433c396d4afSdan do_test pager1-9.3.3 { 1434c396d4afSdan db2 close 1435c396d4afSdan db close 1436c396d4afSdan tv delete 1437c396d4afSdan file size test.db2 1438c396d4afSdan } [file size test.db] 1439*4a8a6467Sdrh} 1440c396d4afSdan 1441f412ee2eSdando_test pager1-9.4.1 { 1442f412ee2eSdan faultsim_delete_and_reopen 1443f412ee2eSdan sqlite3 db2 test.db2 1444f412ee2eSdan execsql { 1445f412ee2eSdan PRAGMA page_size = 4096; 1446f412ee2eSdan CREATE TABLE t1(a, b); 1447f412ee2eSdan CREATE TABLE t2(a, b); 1448f412ee2eSdan } db2 1449f412ee2eSdan sqlite3_backup B db2 main db main 1450f412ee2eSdan list [B step 10000] [B finish] 1451f412ee2eSdan} {SQLITE_DONE SQLITE_OK} 1452f412ee2eSdando_test pager1-9.4.2 { 1453f412ee2eSdan list [file size test.db2] [file size test.db] 1454b483eba0Sdan} {1024 0} 145533d85c9cSshanehdb2 close 1456d0b0d4dcSdan 1457ec6ffc1aSdan#------------------------------------------------------------------------- 1458ec6ffc1aSdan# Test that regardless of the value returned by xSectorSize(), the 1459ec6ffc1aSdan# minimum effective sector-size is 512 and the maximum 65536 bytes. 1460ec6ffc1aSdan# 1461ec6ffc1aSdantestvfs tv -default 1 1462ec6ffc1aSdanforeach sectorsize { 1463d7a558a9Sdan 16 1464ec6ffc1aSdan 32 64 128 256 512 1024 2048 1465ec6ffc1aSdan 4096 8192 16384 32768 65536 131072 262144 1466ec6ffc1aSdan} { 1467ec6ffc1aSdan tv sectorsize $sectorsize 14681eaaf93aSdrh tv devchar {} 1469ec6ffc1aSdan set eff $sectorsize 1470ec6ffc1aSdan if {$sectorsize < 512} { set eff 512 } 1471ec6ffc1aSdan if {$sectorsize > 65536} { set eff 65536 } 1472ec6ffc1aSdan 1473d0b0d4dcSdan do_test pager1-10.$sectorsize.1 { 1474ec6ffc1aSdan faultsim_delete_and_reopen 1475d0b0d4dcSdan db func a_string a_string 1476ec6ffc1aSdan execsql { 1477ec6ffc1aSdan PRAGMA journal_mode = PERSIST; 1478ec6ffc1aSdan PRAGMA page_size = 1024; 1479d0b0d4dcSdan BEGIN; 1480ec6ffc1aSdan CREATE TABLE t1(a, b); 1481d0b0d4dcSdan CREATE TABLE t2(a, b); 1482d0b0d4dcSdan CREATE TABLE t3(a, b); 1483d0b0d4dcSdan COMMIT; 1484ec6ffc1aSdan } 1485ec6ffc1aSdan file size test.db-journal 1486d7a558a9Sdan } [expr $sectorsize > 65536 ? 65536 : ($sectorsize<32 ? 512 : $sectorsize)] 1487d0b0d4dcSdan 1488d0b0d4dcSdan do_test pager1-10.$sectorsize.2 { 1489d0b0d4dcSdan execsql { 1490d0b0d4dcSdan INSERT INTO t3 VALUES(a_string(300), a_string(300)); 1491d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 2 */ 1492d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 4 */ 1493d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 8 */ 1494d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 16 */ 1495d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 32 */ 1496ec6ffc1aSdan } 1497d0b0d4dcSdan } {} 1498d0b0d4dcSdan 1499d0b0d4dcSdan do_test pager1-10.$sectorsize.3 { 1500d0b0d4dcSdan db close 1501d0b0d4dcSdan sqlite3 db test.db 1502d0b0d4dcSdan execsql { 1503d0b0d4dcSdan PRAGMA cache_size = 10; 1504d0b0d4dcSdan BEGIN; 1505d0b0d4dcSdan } 1506d0b0d4dcSdan recursive_select 32 t3 {db eval "INSERT INTO t2 VALUES(1, 2)"} 1507d0b0d4dcSdan execsql { 1508d0b0d4dcSdan COMMIT; 1509d0b0d4dcSdan SELECT * FROM t2; 1510d0b0d4dcSdan } 1511d0b0d4dcSdan } {1 2} 1512d0b0d4dcSdan 1513d0b0d4dcSdan do_test pager1-10.$sectorsize.4 { 1514d0b0d4dcSdan execsql { 1515d0b0d4dcSdan CREATE TABLE t6(a, b); 1516d0b0d4dcSdan CREATE TABLE t7(a, b); 1517d0b0d4dcSdan CREATE TABLE t5(a, b); 1518d0b0d4dcSdan DROP TABLE t6; 1519d0b0d4dcSdan DROP TABLE t7; 1520d0b0d4dcSdan } 1521d0b0d4dcSdan execsql { 1522d0b0d4dcSdan BEGIN; 1523d0b0d4dcSdan CREATE TABLE t6(a, b); 1524d0b0d4dcSdan } 1525d0b0d4dcSdan recursive_select 32 t3 {db eval "INSERT INTO t5 VALUES(1, 2)"} 1526d0b0d4dcSdan execsql { 1527d0b0d4dcSdan COMMIT; 1528d0b0d4dcSdan SELECT * FROM t5; 1529d0b0d4dcSdan } 1530d0b0d4dcSdan } {1 2} 1531d0b0d4dcSdan 1532d0b0d4dcSdan} 1533d0b0d4dcSdandb close 1534d0b0d4dcSdan 1535d0b0d4dcSdantv sectorsize 4096 1536d0b0d4dcSdando_test pager1.10.x.1 { 1537d0b0d4dcSdan faultsim_delete_and_reopen 1538d0b0d4dcSdan execsql { 1539f43d7fceSdan PRAGMA auto_vacuum = none; 1540d0b0d4dcSdan PRAGMA page_size = 1024; 1541d0b0d4dcSdan CREATE TABLE t1(x); 1542d0b0d4dcSdan } 1543d0b0d4dcSdan for {set i 0} {$i<30} {incr i} { 1544d0b0d4dcSdan execsql { INSERT INTO t1 VALUES(zeroblob(900)) } 1545d0b0d4dcSdan } 1546d0b0d4dcSdan file size test.db 1547d0b0d4dcSdan} {32768} 1548d0b0d4dcSdando_test pager1.10.x.2 { 1549d0b0d4dcSdan execsql { 1550d0b0d4dcSdan CREATE TABLE t2(x); 1551d0b0d4dcSdan DROP TABLE t2; 1552d0b0d4dcSdan } 1553d0b0d4dcSdan file size test.db 1554d0b0d4dcSdan} {33792} 1555d0b0d4dcSdando_test pager1.10.x.3 { 1556d0b0d4dcSdan execsql { 1557d0b0d4dcSdan BEGIN; 1558d0b0d4dcSdan CREATE TABLE t2(x); 1559d0b0d4dcSdan } 1560d0b0d4dcSdan recursive_select 30 t1 1561d0b0d4dcSdan execsql { 1562d0b0d4dcSdan CREATE TABLE t3(x); 1563d0b0d4dcSdan COMMIT; 1564d0b0d4dcSdan } 1565d0b0d4dcSdan} {} 1566d0b0d4dcSdan 1567ec6ffc1aSdandb close 1568ec6ffc1aSdantv delete 1569ec6ffc1aSdan 1570ec6ffc1aSdantestvfs tv -default 1 1571ec6ffc1aSdanfaultsim_delete_and_reopen 1572ec6ffc1aSdandb func a_string a_string 1573ec6ffc1aSdando_execsql_test pager1-11.1 { 15743f94b609Sdan PRAGMA journal_mode = DELETE; 1575ec6ffc1aSdan PRAGMA cache_size = 10; 1576ec6ffc1aSdan BEGIN; 1577ec6ffc1aSdan CREATE TABLE zz(top PRIMARY KEY); 1578ec6ffc1aSdan INSERT INTO zz VALUES(a_string(222)); 1579ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1580ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1581ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1582ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1583ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1584ec6ffc1aSdan COMMIT; 1585ec6ffc1aSdan BEGIN; 1586ec6ffc1aSdan UPDATE zz SET top = a_string(345); 15873f94b609Sdan} {delete} 1588ec6ffc1aSdan 1589ec6ffc1aSdanproc lockout {method args} { return SQLITE_IOERR } 1590ec6ffc1aSdantv script lockout 1591ec6ffc1aSdantv filter {xWrite xTruncate xSync} 1592ec6ffc1aSdando_catchsql_test pager1-11.2 { COMMIT } {1 {disk I/O error}} 1593ec6ffc1aSdan 1594ec6ffc1aSdantv script {} 1595ec6ffc1aSdando_test pager1-11.3 { 1596ec6ffc1aSdan sqlite3 db2 test.db 1597ec6ffc1aSdan execsql { 1598ec6ffc1aSdan PRAGMA journal_mode = TRUNCATE; 1599ec6ffc1aSdan PRAGMA integrity_check; 1600ec6ffc1aSdan } db2 1601ec6ffc1aSdan} {truncate ok} 1602ec6ffc1aSdando_test pager1-11.4 { 1603ec6ffc1aSdan db2 close 1604f6c61471Sdan file exists test.db-journal 1605ec6ffc1aSdan} {0} 1606ec6ffc1aSdando_execsql_test pager1-11.5 { SELECT count(*) FROM zz } {32} 1607f9b4419dSdandb close 1608f9b4419dSdantv delete 1609ec6ffc1aSdan 1610f9b4419dSdan#------------------------------------------------------------------------- 1611f9b4419dSdan# Test "PRAGMA page_size" 1612f9b4419dSdan# 1613f43d7fceSdantestvfs tv -default 1 1614f43d7fceSdantv sectorsize 1024 1615f9b4419dSdanforeach pagesize { 1616f9b4419dSdan 512 1024 2048 4096 8192 16384 32768 1617f9b4419dSdan} { 1618f9b4419dSdan faultsim_delete_and_reopen 1619f9b4419dSdan 1620f43d7fceSdan # The sector-size (according to the VFS) is 1024 bytes. So if the 1621f43d7fceSdan # page-size requested using "PRAGMA page_size" is greater than the 1622f43d7fceSdan # compile time value of SQLITE_MAX_PAGE_SIZE, then the effective 1623f43d7fceSdan # page-size remains 1024 bytes. 1624f43d7fceSdan # 1625f43d7fceSdan set eff $pagesize 1626f43d7fceSdan if {$eff > $::SQLITE_MAX_PAGE_SIZE} { set eff 1024 } 1627f43d7fceSdan 1628f9b4419dSdan do_test pager1-12.$pagesize.1 { 1629f9b4419dSdan sqlite3 db2 test.db 1630f9b4419dSdan execsql " 1631f9b4419dSdan PRAGMA page_size = $pagesize; 1632f9b4419dSdan CREATE VIEW v AS SELECT * FROM sqlite_master; 1633f9b4419dSdan " db2 1634f9b4419dSdan file size test.db 1635f43d7fceSdan } $eff 1636f9b4419dSdan do_test pager1-12.$pagesize.2 { 1637f9b4419dSdan sqlite3 db2 test.db 1638f9b4419dSdan execsql { 1639f9b4419dSdan SELECT count(*) FROM v; 1640f9b4419dSdan PRAGMA main.page_size; 1641f9b4419dSdan } db2 1642f43d7fceSdan } [list 1 $eff] 1643f9b4419dSdan do_test pager1-12.$pagesize.3 { 1644f9b4419dSdan execsql { 1645f9b4419dSdan SELECT count(*) FROM v; 1646f9b4419dSdan PRAGMA main.page_size; 1647f9b4419dSdan } 1648f43d7fceSdan } [list 1 $eff] 1649f9b4419dSdan db2 close 1650f9b4419dSdan} 1651f43d7fceSdandb close 1652f43d7fceSdantv delete 1653dca321aeSdan 1654d353331aSdan#------------------------------------------------------------------------- 1655d353331aSdan# Test specal "PRAGMA journal_mode=PERSIST" test cases. 1656d353331aSdan# 1657d353331aSdan# pager1-13.1.*: This tests a special case encountered in persistent 1658d353331aSdan# journal mode: If the journal associated with a transaction 1659d353331aSdan# is smaller than the journal file (because a previous 1660d353331aSdan# transaction left a very large non-hot journal file in the 1661d353331aSdan# file-system), then SQLite has to be careful that there is 1662d353331aSdan# not a journal-header left over from a previous transaction 1663d353331aSdan# immediately following the journal content just written. 1664d353331aSdan# If there is, and the process crashes so that the journal 1665d353331aSdan# becomes a hot-journal and must be rolled back by another 1666d353331aSdan# process, there is a danger that the other process may roll 1667d353331aSdan# back the aborted transaction, then continue copying data 1668d353331aSdan# from an older transaction from the remainder of the journal. 1669d353331aSdan# See the syncJournal() function for details. 1670d353331aSdan# 1671d353331aSdan# pager1-13.2.*: Same test as the previous. This time, throw an index into 1672d353331aSdan# the mix to make the integrity-check more likely to catch 1673d353331aSdan# errors. 1674d353331aSdan# 1675d353331aSdantestvfs tv -default 1 1676d353331aSdantv script xSyncCb 1677d353331aSdantv filter xSync 1678d353331aSdanproc xSyncCb {method filename args} { 1679d353331aSdan set t [file tail $filename] 1680d353331aSdan if {$t == "test.db"} faultsim_save 1681d353331aSdan return SQLITE_OK 1682d353331aSdan} 1683d353331aSdanfaultsim_delete_and_reopen 1684d353331aSdandb func a_string a_string 1685e91a54e1Sdan 1686d353331aSdan# The UPDATE statement at the end of this test case creates a really big 1687d353331aSdan# journal. Since the cache-size is only 10 pages, the journal contains 1688d353331aSdan# frequent journal headers. 1689d353331aSdan# 1690d353331aSdando_execsql_test pager1-13.1.1 { 1691d353331aSdan PRAGMA page_size = 1024; 1692d353331aSdan PRAGMA journal_mode = PERSIST; 1693d353331aSdan PRAGMA cache_size = 10; 1694d353331aSdan BEGIN; 1695d353331aSdan CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB); 1696d353331aSdan INSERT INTO t1 VALUES(NULL, a_string(400)); 1697d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 2 */ 1698d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 4 */ 1699d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 8 */ 1700d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 16 */ 1701d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 32 */ 1702d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 64 */ 1703d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 128 */ 1704d353331aSdan COMMIT; 1705d353331aSdan UPDATE t1 SET b = a_string(400); 1706d353331aSdan} {persist} 1707d353331aSdan 1708b2f20bfcSshanehif {$::tcl_platform(platform)!="windows"} { 1709d353331aSdan# Run transactions of increasing sizes. Eventually, one (or more than one) 1710d353331aSdan# of these will write just enough content that one of the old headers created 1711d353331aSdan# by the transaction in the block above lies immediately after the content 1712d353331aSdan# journalled by the current transaction. 1713d353331aSdan# 1714d353331aSdanfor {set nUp 1} {$nUp<64} {incr nUp} { 1715d353331aSdan do_execsql_test pager1-13.1.2.$nUp.1 { 1716d353331aSdan UPDATE t1 SET b = a_string(399) WHERE a <= $nUp 1717d353331aSdan } {} 1718d353331aSdan do_execsql_test pager1-13.1.2.$nUp.2 { PRAGMA integrity_check } {ok} 1719d353331aSdan 1720d353331aSdan # Try to access the snapshot of the file-system. 1721d353331aSdan # 1722d353331aSdan sqlite3 db2 sv_test.db 1723d353331aSdan do_test pager1-13.1.2.$nUp.3 { 1724d353331aSdan execsql { SELECT sum(length(b)) FROM t1 } db2 1725d353331aSdan } [expr {128*400 - ($nUp-1)}] 1726d353331aSdan do_test pager1-13.1.2.$nUp.4 { 1727d353331aSdan execsql { PRAGMA integrity_check } db2 1728d353331aSdan } {ok} 1729d353331aSdan db2 close 1730d353331aSdan} 1731b2f20bfcSshaneh} 1732d353331aSdan 1733b2f20bfcSshanehif {$::tcl_platform(platform)!="windows"} { 1734d353331aSdan# Same test as above. But this time with an index on the table. 1735d353331aSdan# 1736d353331aSdando_execsql_test pager1-13.2.1 { 1737d353331aSdan CREATE INDEX i1 ON t1(b); 1738d353331aSdan UPDATE t1 SET b = a_string(400); 1739d353331aSdan} {} 1740d353331aSdanfor {set nUp 1} {$nUp<64} {incr nUp} { 1741d353331aSdan do_execsql_test pager1-13.2.2.$nUp.1 { 1742d353331aSdan UPDATE t1 SET b = a_string(399) WHERE a <= $nUp 1743d353331aSdan } {} 1744d353331aSdan do_execsql_test pager1-13.2.2.$nUp.2 { PRAGMA integrity_check } {ok} 1745d353331aSdan sqlite3 db2 sv_test.db 1746d353331aSdan do_test pager1-13.2.2.$nUp.3 { 1747d353331aSdan execsql { SELECT sum(length(b)) FROM t1 } db2 1748d353331aSdan } [expr {128*400 - ($nUp-1)}] 1749d353331aSdan do_test pager1-13.2.2.$nUp.4 { 1750d353331aSdan execsql { PRAGMA integrity_check } db2 1751d353331aSdan } {ok} 1752d353331aSdan db2 close 1753d353331aSdan} 1754b2f20bfcSshaneh} 1755d353331aSdan 1756d353331aSdandb close 1757d353331aSdantv delete 1758d353331aSdan 1759d353331aSdan#------------------------------------------------------------------------- 1760d353331aSdan# Test specal "PRAGMA journal_mode=OFF" test cases. 1761d353331aSdan# 1762d353331aSdanfaultsim_delete_and_reopen 1763d353331aSdando_execsql_test pager1-14.1.1 { 1764d353331aSdan PRAGMA journal_mode = OFF; 1765d353331aSdan CREATE TABLE t1(a, b); 1766d353331aSdan BEGIN; 1767d353331aSdan INSERT INTO t1 VALUES(1, 2); 1768d353331aSdan COMMIT; 1769d353331aSdan SELECT * FROM t1; 1770d353331aSdan} {off 1 2} 1771d353331aSdando_catchsql_test pager1-14.1.2 { 1772d353331aSdan BEGIN; 1773d353331aSdan INSERT INTO t1 VALUES(3, 4); 1774d353331aSdan ROLLBACK; 1775d353331aSdan} {0 {}} 1776d353331aSdando_execsql_test pager1-14.1.3 { 1777d353331aSdan SELECT * FROM t1; 1778354bfe03Sdan} {1 2} 1779d353331aSdando_catchsql_test pager1-14.1.4 { 1780d353331aSdan BEGIN; 1781d353331aSdan INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; 1782d353331aSdan INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; 1783f9c8ce3cSdrh} {1 {UNIQUE constraint failed: t1.rowid}} 1784d353331aSdando_execsql_test pager1-14.1.5 { 1785d353331aSdan COMMIT; 1786d353331aSdan SELECT * FROM t1; 1787354bfe03Sdan} {1 2 2 2} 1788d353331aSdan 1789c8ce3972Sdan#------------------------------------------------------------------------- 1790c8ce3972Sdan# Test opening and closing the pager sub-system with different values 1791c8ce3972Sdan# for the sqlite3_vfs.szOsFile variable. 1792c8ce3972Sdan# 1793c8ce3972Sdanfaultsim_delete_and_reopen 1794c8ce3972Sdando_execsql_test pager1-15.0 { 1795c8ce3972Sdan CREATE TABLE tx(y, z); 1796c8ce3972Sdan INSERT INTO tx VALUES('Ayutthaya', 'Beijing'); 1797c8ce3972Sdan INSERT INTO tx VALUES('London', 'Tokyo'); 1798c8ce3972Sdan} {} 1799c8ce3972Sdandb close 1800c8ce3972Sdanfor {set i 0} {$i<513} {incr i 3} { 1801c8ce3972Sdan testvfs tv -default 1 -szosfile $i 1802c8ce3972Sdan sqlite3 db test.db 1803c8ce3972Sdan do_execsql_test pager1-15.$i.1 { 1804c8ce3972Sdan SELECT * FROM tx; 1805c8ce3972Sdan } {Ayutthaya Beijing London Tokyo} 1806c8ce3972Sdan db close 1807c8ce3972Sdan tv delete 1808c8ce3972Sdan} 1809c8ce3972Sdan 1810c8ce3972Sdan#------------------------------------------------------------------------- 1811c8ce3972Sdan# Check that it is not possible to open a database file if the full path 1812c8ce3972Sdan# to the associated journal file will be longer than sqlite3_vfs.mxPathname. 1813c8ce3972Sdan# 1814c8ce3972Sdantestvfs tv -default 1 1815c8ce3972Sdantv script xOpenCb 1816c8ce3972Sdantv filter xOpen 181733f5379cSdanproc xOpenCb {method filename args} { 1818c8ce3972Sdan set ::file_len [string length $filename] 1819c8ce3972Sdan} 1820c8ce3972Sdansqlite3 db test.db 1821c8ce3972Sdandb close 1822c8ce3972Sdantv delete 1823c8ce3972Sdan 1824c8ce3972Sdanfor {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} { 1825c8ce3972Sdan testvfs tv -default 1 -mxpathname $ii 1826c8ce3972Sdan 1827c8ce3972Sdan # The length of the full path to file "test.db-journal" is ($::file_len+8). 1828c8ce3972Sdan # If the configured sqlite3_vfs.mxPathname value greater than or equal to 1829c8ce3972Sdan # this, then the file can be opened. Otherwise, it cannot. 1830c8ce3972Sdan # 1831c8ce3972Sdan if {$ii >= [expr $::file_len+8]} { 1832c8ce3972Sdan set res {0 {}} 1833c8ce3972Sdan } else { 1834c8ce3972Sdan set res {1 {unable to open database file}} 1835c8ce3972Sdan } 1836c8ce3972Sdan 1837c8ce3972Sdan do_test pager1-16.1.$ii { 1838c8ce3972Sdan list [catch { sqlite3 db test.db } msg] $msg 1839c8ce3972Sdan } $res 1840c8ce3972Sdan 1841c8ce3972Sdan catch {db close} 1842c8ce3972Sdan tv delete 1843c8ce3972Sdan} 1844c8ce3972Sdan 1845c8ce3972Sdan 1846c8ce3972Sdan#------------------------------------------------------------------------- 1847c8ce3972Sdan# Test the pagers response to the b-tree layer requesting illegal page 1848c8ce3972Sdan# numbers: 1849c8ce3972Sdan# 1850c8ce3972Sdan# + The locking page, 1851c8ce3972Sdan# + Page 0, 1852c8ce3972Sdan# + A page with a page number greater than (2^31-1). 1853c8ce3972Sdan# 1854f4ba1093Sdan# These tests will not work if SQLITE_DIRECT_OVERFLOW_READ is defined. In 1855f4ba1093Sdan# that case IO errors are sometimes reported instead of SQLITE_CORRUPT. 1856f4ba1093Sdan# 1857f4ba1093Sdanifcapable !direct_read { 1858c8ce3972Sdando_test pager1-18.1 { 1859c8ce3972Sdan faultsim_delete_and_reopen 1860c8ce3972Sdan db func a_string a_string 1861c8ce3972Sdan execsql { 1862c8ce3972Sdan PRAGMA page_size = 1024; 1863c8ce3972Sdan CREATE TABLE t1(a, b); 1864c8ce3972Sdan INSERT INTO t1 VALUES(a_string(500), a_string(200)); 1865c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1866c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1867c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1868c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1869c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1870c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1871c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1872c8ce3972Sdan } 1873c8ce3972Sdan} {} 1874c8ce3972Sdando_test pager1-18.2 { 1875c8ce3972Sdan set root [db one "SELECT rootpage FROM sqlite_master"] 1876c8ce3972Sdan set lockingpage [expr (0x10000/1024) + 1] 1877c8ce3972Sdan execsql { 1878c8ce3972Sdan PRAGMA writable_schema = 1; 1879c8ce3972Sdan UPDATE sqlite_master SET rootpage = $lockingpage; 1880c8ce3972Sdan } 1881c8ce3972Sdan sqlite3 db2 test.db 1882c8ce3972Sdan catchsql { SELECT count(*) FROM t1 } db2 1883c8ce3972Sdan} {1 {database disk image is malformed}} 1884c8ce3972Sdandb2 close 1885a748fdccSdrhdo_test pager1-18.3.1 { 1886c8ce3972Sdan execsql { 1887c8ce3972Sdan CREATE TABLE t2(x); 1888c8ce3972Sdan INSERT INTO t2 VALUES(a_string(5000)); 1889c8ce3972Sdan } 1890c8ce3972Sdan set pgno [expr ([file size test.db] / 1024)-2] 1891c8ce3972Sdan hexio_write test.db [expr ($pgno-1)*1024] 00000000 1892c8ce3972Sdan sqlite3 db2 test.db 1893a748fdccSdrh # even though x is malformed, because typeof() does 1894a748fdccSdrh # not load the content of x, the error is not noticed. 1895a748fdccSdrh catchsql { SELECT typeof(x) FROM t2 } db2 1896a748fdccSdrh} {0 text} 1897a748fdccSdrhdo_test pager1-18.3.2 { 1898a748fdccSdrh # in this case, the value of x is loaded and so the error is 1899a748fdccSdrh # detected 1900a748fdccSdrh catchsql { SELECT length(x||'') FROM t2 } db2 1901a748fdccSdrh} {1 {database disk image is malformed}} 1902a748fdccSdrhdb2 close 1903a748fdccSdrhdo_test pager1-18.3.3 { 1904a748fdccSdrh execsql { 1905a748fdccSdrh DELETE FROM t2; 1906a748fdccSdrh INSERT INTO t2 VALUES(randomblob(5000)); 1907a748fdccSdrh } 1908a748fdccSdrh set pgno [expr ([file size test.db] / 1024)-2] 1909a748fdccSdrh hexio_write test.db [expr ($pgno-1)*1024] 00000000 1910a748fdccSdrh sqlite3 db2 test.db 1911a748fdccSdrh # even though x is malformed, because length() and typeof() do 1912a748fdccSdrh # not load the content of x, the error is not noticed. 1913a748fdccSdrh catchsql { SELECT length(x), typeof(x) FROM t2 } db2 1914a748fdccSdrh} {0 {5000 blob}} 1915a748fdccSdrhdo_test pager1-18.3.4 { 1916a748fdccSdrh # in this case, the value of x is loaded and so the error is 1917a748fdccSdrh # detected 1918a748fdccSdrh catchsql { SELECT length(x||'') FROM t2 } db2 1919c8ce3972Sdan} {1 {database disk image is malformed}} 1920c8ce3972Sdandb2 close 1921c8ce3972Sdando_test pager1-18.4 { 1922c8ce3972Sdan hexio_write test.db [expr ($pgno-1)*1024] 90000000 1923c8ce3972Sdan sqlite3 db2 test.db 1924a748fdccSdrh catchsql { SELECT length(x||'') FROM t2 } db2 1925c8ce3972Sdan} {1 {database disk image is malformed}} 1926c8ce3972Sdandb2 close 1927c8ce3972Sdando_test pager1-18.5 { 1928c8ce3972Sdan sqlite3 db "" 1929c8ce3972Sdan execsql { 1930c8ce3972Sdan CREATE TABLE t1(a, b); 1931c8ce3972Sdan CREATE TABLE t2(a, b); 1932c8ce3972Sdan PRAGMA writable_schema = 1; 1933c8ce3972Sdan UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1'; 1934c8ce3972Sdan PRAGMA writable_schema = 0; 1935c8ce3972Sdan ALTER TABLE t1 RENAME TO x1; 1936c8ce3972Sdan } 1937c8ce3972Sdan catchsql { SELECT * FROM x1 } 1938ba3cbf3dSdan} {1 {database disk image is malformed}} 1939c8ce3972Sdandb close 1940c8ce3972Sdan 1941ba3cbf3dSdando_test pager1-18.6 { 1942ba3cbf3dSdan faultsim_delete_and_reopen 1943ba3cbf3dSdan db func a_string a_string 1944ba3cbf3dSdan execsql { 1945ba3cbf3dSdan PRAGMA page_size = 1024; 1946ba3cbf3dSdan CREATE TABLE t1(x); 1947ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(800)); 1948ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(800)); 1949ba3cbf3dSdan } 1950ba3cbf3dSdan 1951ba3cbf3dSdan set root [db one "SELECT rootpage FROM sqlite_master"] 1952ba3cbf3dSdan db close 1953ba3cbf3dSdan 1954ba3cbf3dSdan hexio_write test.db [expr ($root-1)*1024 + 8] 00000000 1955ba3cbf3dSdan sqlite3 db test.db 1956ba3cbf3dSdan catchsql { SELECT length(x) FROM t1 } 1957ba3cbf3dSdan} {1 {database disk image is malformed}} 1958f4ba1093Sdan} 1959ba3cbf3dSdan 1960ba3cbf3dSdando_test pager1-19.1 { 1961ba3cbf3dSdan sqlite3 db "" 1962ba3cbf3dSdan db func a_string a_string 1963ba3cbf3dSdan execsql { 1964ba3cbf3dSdan PRAGMA page_size = 512; 1965ba3cbf3dSdan PRAGMA auto_vacuum = 1; 1966ba3cbf3dSdan CREATE TABLE t1(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, 1967ba3cbf3dSdan ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, 1968ba3cbf3dSdan ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, 1969ba3cbf3dSdan da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn, 1970ba3cbf3dSdan ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, 1971ba3cbf3dSdan fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, 1972ba3cbf3dSdan ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn, 1973ba3cbf3dSdan ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn, 1974ba3cbf3dSdan ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix, 1975ba3cbf3dSdan ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn, 1976ba3cbf3dSdan ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn, 1977ba3cbf3dSdan la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln, 1978ba3cbf3dSdan ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn 1979ba3cbf3dSdan ); 1980ba3cbf3dSdan CREATE TABLE t2(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, 1981ba3cbf3dSdan ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, 1982ba3cbf3dSdan ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, 1983ba3cbf3dSdan da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn, 1984ba3cbf3dSdan ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, 1985ba3cbf3dSdan fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, 1986ba3cbf3dSdan ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn, 1987ba3cbf3dSdan ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn, 1988ba3cbf3dSdan ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix, 1989ba3cbf3dSdan ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn, 1990ba3cbf3dSdan ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn, 1991ba3cbf3dSdan la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln, 1992ba3cbf3dSdan ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn 1993ba3cbf3dSdan ); 1994ba3cbf3dSdan INSERT INTO t1(aa) VALUES( a_string(100000) ); 1995ba3cbf3dSdan INSERT INTO t2(aa) VALUES( a_string(100000) ); 1996ba3cbf3dSdan VACUUM; 1997ba3cbf3dSdan } 1998ba3cbf3dSdan} {} 1999ba3cbf3dSdan 20006b63ab47Sdan#------------------------------------------------------------------------- 20016b63ab47Sdan# Test a couple of special cases that come up while committing 20026b63ab47Sdan# transactions: 20036b63ab47Sdan# 20046b63ab47Sdan# pager1-20.1.*: Committing an in-memory database transaction when the 20056b63ab47Sdan# database has not been modified at all. 20066b63ab47Sdan# 20076b63ab47Sdan# pager1-20.2.*: As above, but with a normal db in exclusive-locking mode. 20086b63ab47Sdan# 20096b63ab47Sdan# pager1-20.3.*: Committing a transaction in WAL mode where the database has 20106b63ab47Sdan# been modified, but all dirty pages have been flushed to 20116b63ab47Sdan# disk before the commit. 20126b63ab47Sdan# 20136b63ab47Sdando_test pager1-20.1.1 { 20146b63ab47Sdan catch {db close} 20156b63ab47Sdan sqlite3 db :memory: 20166b63ab47Sdan execsql { 20176b63ab47Sdan CREATE TABLE one(two, three); 20186b63ab47Sdan INSERT INTO one VALUES('a', 'b'); 20196b63ab47Sdan } 20206b63ab47Sdan} {} 20216b63ab47Sdando_test pager1-20.1.2 { 20226b63ab47Sdan execsql { 20236b63ab47Sdan BEGIN EXCLUSIVE; 20246b63ab47Sdan COMMIT; 20256b63ab47Sdan } 20266b63ab47Sdan} {} 20276b63ab47Sdan 20286b63ab47Sdando_test pager1-20.2.1 { 20296b63ab47Sdan faultsim_delete_and_reopen 20306b63ab47Sdan execsql { 20316b63ab47Sdan PRAGMA locking_mode = exclusive; 20326b63ab47Sdan PRAGMA journal_mode = persist; 20336b63ab47Sdan CREATE TABLE one(two, three); 20346b63ab47Sdan INSERT INTO one VALUES('a', 'b'); 20356b63ab47Sdan } 20366b63ab47Sdan} {exclusive persist} 20376b63ab47Sdando_test pager1-20.2.2 { 20386b63ab47Sdan execsql { 20396b63ab47Sdan BEGIN EXCLUSIVE; 20406b63ab47Sdan COMMIT; 20416b63ab47Sdan } 20426b63ab47Sdan} {} 20436b63ab47Sdan 20449091f775Sshanehifcapable wal { 20456b63ab47Sdan do_test pager1-20.3.1 { 20466b63ab47Sdan faultsim_delete_and_reopen 20476b63ab47Sdan db func a_string a_string 20486b63ab47Sdan execsql { 20496b63ab47Sdan PRAGMA cache_size = 10; 20506b63ab47Sdan PRAGMA journal_mode = wal; 20516b63ab47Sdan BEGIN; 20526b63ab47Sdan CREATE TABLE t1(x); 20536b63ab47Sdan CREATE TABLE t2(y); 20546b63ab47Sdan INSERT INTO t1 VALUES(a_string(800)); 20556b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 2 */ 20566b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 4 */ 20576b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 8 */ 20586b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 16 */ 20596b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 32 */ 20606b63ab47Sdan COMMIT; 20616b63ab47Sdan } 20626b63ab47Sdan } {wal} 20636b63ab47Sdan do_test pager1-20.3.2 { 20646b63ab47Sdan execsql { 20656b63ab47Sdan BEGIN; 20666b63ab47Sdan INSERT INTO t2 VALUES('xxxx'); 20676b63ab47Sdan } 2068c396d4afSdan recursive_select 32 t1 20696b63ab47Sdan execsql COMMIT 20706b63ab47Sdan } {} 20719091f775Sshaneh} 20726b63ab47Sdan 207389ccf448Sdan#------------------------------------------------------------------------- 207489ccf448Sdan# Test that a WAL database may not be opened if: 207589ccf448Sdan# 207689ccf448Sdan# pager1-21.1.*: The VFS has an iVersion less than 2, or 207789ccf448Sdan# pager1-21.2.*: The VFS does not provide xShmXXX() methods. 207889ccf448Sdan# 20799091f775Sshanehifcapable wal { 208089ccf448Sdan do_test pager1-21.0 { 208189ccf448Sdan faultsim_delete_and_reopen 208289ccf448Sdan execsql { 208389ccf448Sdan PRAGMA journal_mode = WAL; 208489ccf448Sdan CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def'); 208589ccf448Sdan INSERT INTO ko DEFAULT VALUES; 208689ccf448Sdan } 208789ccf448Sdan } {wal} 208889ccf448Sdan do_test pager1-21.1 { 208989ccf448Sdan testvfs tv -noshm 1 209089ccf448Sdan sqlite3 db2 test.db -vfs tv 209189ccf448Sdan catchsql { SELECT * FROM ko } db2 209289ccf448Sdan } {1 {unable to open database file}} 209389ccf448Sdan db2 close 209489ccf448Sdan tv delete 209589ccf448Sdan do_test pager1-21.2 { 209689ccf448Sdan testvfs tv -iversion 1 209789ccf448Sdan sqlite3 db2 test.db -vfs tv 209889ccf448Sdan catchsql { SELECT * FROM ko } db2 209989ccf448Sdan } {1 {unable to open database file}} 210089ccf448Sdan db2 close 210189ccf448Sdan tv delete 21029091f775Sshaneh} 210389ccf448Sdan 210489ccf448Sdan#------------------------------------------------------------------------- 210589ccf448Sdan# Test that a "PRAGMA wal_checkpoint": 210689ccf448Sdan# 210789ccf448Sdan# pager1-22.1.*: is a no-op on a non-WAL db, and 210889ccf448Sdan# pager1-22.2.*: does not cause xSync calls with a synchronous=off db. 210989ccf448Sdan# 21105209132aSdanifcapable wal { 211189ccf448Sdan do_test pager1-22.1.1 { 211289ccf448Sdan faultsim_delete_and_reopen 211389ccf448Sdan execsql { 211489ccf448Sdan CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def'); 211589ccf448Sdan INSERT INTO ko DEFAULT VALUES; 211689ccf448Sdan } 211789ccf448Sdan execsql { PRAGMA wal_checkpoint } 2118bdd9af0fSdan } {0 -1 -1} 211989ccf448Sdan do_test pager1-22.2.1 { 212089ccf448Sdan testvfs tv -default 1 212189ccf448Sdan tv filter xSync 212289ccf448Sdan tv script xSyncCb 212389ccf448Sdan proc xSyncCb {args} {incr ::synccount} 212489ccf448Sdan set ::synccount 0 212589ccf448Sdan sqlite3 db test.db 212689ccf448Sdan execsql { 212789ccf448Sdan PRAGMA synchronous = off; 212889ccf448Sdan PRAGMA journal_mode = WAL; 212989ccf448Sdan INSERT INTO ko DEFAULT VALUES; 213089ccf448Sdan } 213189ccf448Sdan execsql { PRAGMA wal_checkpoint } 213289ccf448Sdan set synccount 213389ccf448Sdan } {0} 213489ccf448Sdan db close 213589ccf448Sdan tv delete 21365209132aSdan} 213789ccf448Sdan 213889ccf448Sdan#------------------------------------------------------------------------- 213989ccf448Sdan# Tests for changing journal mode. 214089ccf448Sdan# 214189ccf448Sdan# pager1-23.1.*: Test that when changing from PERSIST to DELETE mode, 214289ccf448Sdan# the journal file is deleted. 214389ccf448Sdan# 214489ccf448Sdan# pager1-23.2.*: Same test as above, but while a shared lock is held 214589ccf448Sdan# on the database file. 214689ccf448Sdan# 214789ccf448Sdan# pager1-23.3.*: Same test as above, but while a reserved lock is held 214889ccf448Sdan# on the database file. 214989ccf448Sdan# 215089ccf448Sdan# pager1-23.4.*: And, for fun, while holding an exclusive lock. 215189ccf448Sdan# 215289ccf448Sdan# pager1-23.5.*: Try to set various different journal modes with an 215389ccf448Sdan# in-memory database (only MEMORY and OFF should work). 215489ccf448Sdan# 2155d0b0d4dcSdan# pager1-23.6.*: Try to set locking_mode=normal on an in-memory database 2156d0b0d4dcSdan# (doesn't work - in-memory databases always use 2157d0b0d4dcSdan# locking_mode=exclusive). 2158d0b0d4dcSdan# 215989ccf448Sdando_test pager1-23.1.1 { 216089ccf448Sdan faultsim_delete_and_reopen 216189ccf448Sdan execsql { 216289ccf448Sdan PRAGMA journal_mode = PERSIST; 216389ccf448Sdan CREATE TABLE t1(a, b); 216489ccf448Sdan } 216589ccf448Sdan file exists test.db-journal 216689ccf448Sdan} {1} 216789ccf448Sdando_test pager1-23.1.2 { 216889ccf448Sdan execsql { PRAGMA journal_mode = DELETE } 216989ccf448Sdan file exists test.db-journal 217089ccf448Sdan} {0} 217189ccf448Sdan 217289ccf448Sdando_test pager1-23.2.1 { 217389ccf448Sdan execsql { 217489ccf448Sdan PRAGMA journal_mode = PERSIST; 217589ccf448Sdan INSERT INTO t1 VALUES('Canberra', 'ACT'); 217689ccf448Sdan } 217789ccf448Sdan db eval { SELECT * FROM t1 } { 217889ccf448Sdan db eval { PRAGMA journal_mode = DELETE } 217989ccf448Sdan } 218089ccf448Sdan execsql { PRAGMA journal_mode } 218189ccf448Sdan} {delete} 218289ccf448Sdando_test pager1-23.2.2 { 218389ccf448Sdan file exists test.db-journal 218489ccf448Sdan} {0} 218589ccf448Sdan 218689ccf448Sdando_test pager1-23.3.1 { 218789ccf448Sdan execsql { 218889ccf448Sdan PRAGMA journal_mode = PERSIST; 218989ccf448Sdan INSERT INTO t1 VALUES('Darwin', 'NT'); 219089ccf448Sdan BEGIN IMMEDIATE; 219189ccf448Sdan } 219289ccf448Sdan db eval { PRAGMA journal_mode = DELETE } 219389ccf448Sdan execsql { PRAGMA journal_mode } 219489ccf448Sdan} {delete} 219589ccf448Sdando_test pager1-23.3.2 { 219689ccf448Sdan file exists test.db-journal 219789ccf448Sdan} {0} 219889ccf448Sdando_test pager1-23.3.3 { 219989ccf448Sdan execsql COMMIT 220089ccf448Sdan} {} 220189ccf448Sdan 220289ccf448Sdando_test pager1-23.4.1 { 220389ccf448Sdan execsql { 220489ccf448Sdan PRAGMA journal_mode = PERSIST; 220589ccf448Sdan INSERT INTO t1 VALUES('Adelaide', 'SA'); 220689ccf448Sdan BEGIN EXCLUSIVE; 220789ccf448Sdan } 220889ccf448Sdan db eval { PRAGMA journal_mode = DELETE } 220989ccf448Sdan execsql { PRAGMA journal_mode } 221089ccf448Sdan} {delete} 221189ccf448Sdando_test pager1-23.4.2 { 221289ccf448Sdan file exists test.db-journal 221389ccf448Sdan} {0} 221489ccf448Sdando_test pager1-23.4.3 { 221589ccf448Sdan execsql COMMIT 221689ccf448Sdan} {} 221789ccf448Sdan 221889ccf448Sdando_test pager1-23.5.1 { 221989ccf448Sdan faultsim_delete_and_reopen 222089ccf448Sdan sqlite3 db :memory: 222189ccf448Sdan} {} 222289ccf448Sdanforeach {tn mode possible} { 222389ccf448Sdan 2 off 1 222489ccf448Sdan 3 memory 1 222589ccf448Sdan 4 persist 0 222689ccf448Sdan 5 delete 0 222789ccf448Sdan 6 wal 0 222889ccf448Sdan 7 truncate 0 222989ccf448Sdan} { 223089ccf448Sdan do_test pager1-23.5.$tn.1 { 223189ccf448Sdan execsql "PRAGMA journal_mode = off" 223289ccf448Sdan execsql "PRAGMA journal_mode = $mode" 223389ccf448Sdan } [if $possible {list $mode} {list off}] 223489ccf448Sdan do_test pager1-23.5.$tn.2 { 223589ccf448Sdan execsql "PRAGMA journal_mode = memory" 223689ccf448Sdan execsql "PRAGMA journal_mode = $mode" 223789ccf448Sdan } [if $possible {list $mode} {list memory}] 223889ccf448Sdan} 2239d0b0d4dcSdando_test pager1-23.6.1 { 224089ccf448Sdan execsql {PRAGMA locking_mode = normal} 224189ccf448Sdan} {exclusive} 2242d0b0d4dcSdando_test pager1-23.6.2 { 224389ccf448Sdan execsql {PRAGMA locking_mode = exclusive} 224489ccf448Sdan} {exclusive} 2245d0b0d4dcSdando_test pager1-23.6.3 { 224689ccf448Sdan execsql {PRAGMA locking_mode} 224789ccf448Sdan} {exclusive} 2248d0b0d4dcSdando_test pager1-23.6.4 { 224989ccf448Sdan execsql {PRAGMA main.locking_mode} 225089ccf448Sdan} {exclusive} 22516b63ab47Sdan 2252d0b0d4dcSdan#------------------------------------------------------------------------- 2253d0b0d4dcSdan# 2254d0b0d4dcSdando_test pager1-24.1.1 { 2255d0b0d4dcSdan faultsim_delete_and_reopen 2256d0b0d4dcSdan db func a_string a_string 2257d0b0d4dcSdan execsql { 2258d0b0d4dcSdan PRAGMA cache_size = 10; 2259d0b0d4dcSdan PRAGMA auto_vacuum = FULL; 2260d0b0d4dcSdan CREATE TABLE x1(x, y, z, PRIMARY KEY(y, z)); 2261d0b0d4dcSdan CREATE TABLE x2(x, y, z, PRIMARY KEY(y, z)); 2262d0b0d4dcSdan INSERT INTO x2 VALUES(a_string(400), a_string(500), a_string(600)); 2263d0b0d4dcSdan INSERT INTO x2 SELECT a_string(600), a_string(400), a_string(500) FROM x2; 2264d0b0d4dcSdan INSERT INTO x2 SELECT a_string(500), a_string(600), a_string(400) FROM x2; 2265d0b0d4dcSdan INSERT INTO x2 SELECT a_string(400), a_string(500), a_string(600) FROM x2; 2266d0b0d4dcSdan INSERT INTO x2 SELECT a_string(600), a_string(400), a_string(500) FROM x2; 2267d0b0d4dcSdan INSERT INTO x2 SELECT a_string(500), a_string(600), a_string(400) FROM x2; 2268d0b0d4dcSdan INSERT INTO x2 SELECT a_string(400), a_string(500), a_string(600) FROM x2; 2269d0b0d4dcSdan INSERT INTO x1 SELECT * FROM x2; 2270d0b0d4dcSdan } 2271d0b0d4dcSdan} {} 2272d0b0d4dcSdando_test pager1-24.1.2 { 2273d0b0d4dcSdan execsql { 2274d0b0d4dcSdan BEGIN; 2275d0b0d4dcSdan DELETE FROM x1 WHERE rowid<32; 2276d0b0d4dcSdan } 2277c396d4afSdan recursive_select 64 x2 2278d0b0d4dcSdan} {} 2279d0b0d4dcSdando_test pager1-24.1.3 { 2280d0b0d4dcSdan execsql { 2281d0b0d4dcSdan UPDATE x1 SET z = a_string(300) WHERE rowid>40; 2282d0b0d4dcSdan COMMIT; 2283d0b0d4dcSdan PRAGMA integrity_check; 2284d0b0d4dcSdan SELECT count(*) FROM x1; 2285d0b0d4dcSdan } 2286d0b0d4dcSdan} {ok 33} 2287d0b0d4dcSdan 2288d0b0d4dcSdando_test pager1-24.1.4 { 2289d0b0d4dcSdan execsql { 2290d0b0d4dcSdan DELETE FROM x1; 2291d0b0d4dcSdan INSERT INTO x1 SELECT * FROM x2; 2292d0b0d4dcSdan BEGIN; 2293d0b0d4dcSdan DELETE FROM x1 WHERE rowid<32; 2294d0b0d4dcSdan UPDATE x1 SET z = a_string(299) WHERE rowid>40; 2295d0b0d4dcSdan } 2296c396d4afSdan recursive_select 64 x2 {db eval COMMIT} 2297d0b0d4dcSdan execsql { 2298d0b0d4dcSdan PRAGMA integrity_check; 2299d0b0d4dcSdan SELECT count(*) FROM x1; 2300d0b0d4dcSdan } 2301d0b0d4dcSdan} {ok 33} 2302d0b0d4dcSdan 2303d0b0d4dcSdando_test pager1-24.1.5 { 2304d0b0d4dcSdan execsql { 2305d0b0d4dcSdan DELETE FROM x1; 2306d0b0d4dcSdan INSERT INTO x1 SELECT * FROM x2; 2307d0b0d4dcSdan } 2308c396d4afSdan recursive_select 64 x2 { db eval {CREATE TABLE x3(x, y, z)} } 2309d0b0d4dcSdan execsql { SELECT * FROM x3 } 2310d0b0d4dcSdan} {} 2311d0b0d4dcSdan 2312d0b0d4dcSdan#------------------------------------------------------------------------- 2313d0b0d4dcSdan# 2314d0b0d4dcSdando_test pager1-25-1 { 2315d0b0d4dcSdan faultsim_delete_and_reopen 2316d0b0d4dcSdan execsql { 2317d0b0d4dcSdan BEGIN; 2318d0b0d4dcSdan SAVEPOINT abc; 2319d0b0d4dcSdan CREATE TABLE t1(a, b); 2320d0b0d4dcSdan ROLLBACK TO abc; 2321d0b0d4dcSdan COMMIT; 2322d0b0d4dcSdan } 2323d0b0d4dcSdan db close 2324d0b0d4dcSdan} {} 2325d0b0d4dcSdando_test pager1-25-2 { 2326d0b0d4dcSdan faultsim_delete_and_reopen 2327d0b0d4dcSdan execsql { 2328d0b0d4dcSdan SAVEPOINT abc; 2329d0b0d4dcSdan CREATE TABLE t1(a, b); 2330d0b0d4dcSdan ROLLBACK TO abc; 2331d0b0d4dcSdan COMMIT; 2332d0b0d4dcSdan } 2333d0b0d4dcSdan db close 2334d0b0d4dcSdan} {} 23356b63ab47Sdan 2336c396d4afSdan#------------------------------------------------------------------------- 2337c396d4afSdan# Sector-size tests. 2338c396d4afSdan# 2339c396d4afSdando_test pager1-26.1 { 2340c396d4afSdan testvfs tv -default 1 2341c396d4afSdan tv sectorsize 4096 2342c396d4afSdan faultsim_delete_and_reopen 2343c396d4afSdan db func a_string a_string 2344c396d4afSdan execsql { 2345c396d4afSdan PRAGMA page_size = 512; 2346c396d4afSdan CREATE TABLE tbl(a PRIMARY KEY, b UNIQUE); 2347c396d4afSdan BEGIN; 2348c396d4afSdan INSERT INTO tbl VALUES(a_string(25), a_string(600)); 2349c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2350c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2351c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2352c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2353c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2354c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2355c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2356c396d4afSdan COMMIT; 2357c396d4afSdan } 2358c396d4afSdan} {} 2359c396d4afSdando_execsql_test pager1-26.1 { 2360c396d4afSdan UPDATE tbl SET b = a_string(550); 2361c396d4afSdan} {} 2362c396d4afSdandb close 2363c396d4afSdantv delete 2364c396d4afSdan 2365c396d4afSdan#------------------------------------------------------------------------- 236622b328b2Sdan# 2367c396d4afSdando_test pager1.27.1 { 2368c396d4afSdan faultsim_delete_and_reopen 2369c396d4afSdan sqlite3_pager_refcounts db 2370c396d4afSdan execsql { 2371c396d4afSdan BEGIN; 2372c396d4afSdan CREATE TABLE t1(a, b); 2373c396d4afSdan } 2374c396d4afSdan sqlite3_pager_refcounts db 2375c396d4afSdan execsql COMMIT 2376c396d4afSdan} {} 2377c396d4afSdan 237822b328b2Sdan#------------------------------------------------------------------------- 237922b328b2Sdan# Test that attempting to open a write-transaction with 238022b328b2Sdan# locking_mode=exclusive in WAL mode fails if there are other clients on 238122b328b2Sdan# the same database. 238222b328b2Sdan# 238322b328b2Sdancatch { db close } 23849091f775Sshanehifcapable wal { 238522b328b2Sdan do_multiclient_test tn { 238622b328b2Sdan do_test pager1-28.$tn.1 { 238722b328b2Sdan sql1 { 238822b328b2Sdan PRAGMA journal_mode = WAL; 238922b328b2Sdan CREATE TABLE t1(a, b); 239022b328b2Sdan INSERT INTO t1 VALUES('a', 'b'); 239122b328b2Sdan } 239222b328b2Sdan } {wal} 239322b328b2Sdan do_test pager1-28.$tn.2 { sql2 { SELECT * FROM t1 } } {a b} 239422b328b2Sdan 239522b328b2Sdan do_test pager1-28.$tn.3 { sql1 { PRAGMA locking_mode=exclusive } } {exclusive} 239622b328b2Sdan do_test pager1-28.$tn.4 { 239722b328b2Sdan csql1 { BEGIN; INSERT INTO t1 VALUES('c', 'd'); } 239822b328b2Sdan } {1 {database is locked}} 239922b328b2Sdan code2 { db2 close ; sqlite3 db2 test.db } 240022b328b2Sdan do_test pager1-28.$tn.4 { 240122b328b2Sdan sql1 { INSERT INTO t1 VALUES('c', 'd'); COMMIT } 240222b328b2Sdan } {} 240322b328b2Sdan } 24049091f775Sshaneh} 24055653e4daSdan 24065653e4daSdan#------------------------------------------------------------------------- 24075653e4daSdan# Normally, when changing from journal_mode=PERSIST to DELETE the pager 24085653e4daSdan# attempts to delete the journal file. However, if it cannot obtain a 24095653e4daSdan# RESERVED lock on the database file, this step is skipped. 24105653e4daSdan# 24115653e4daSdando_multiclient_test tn { 24125653e4daSdan do_test pager1-28.$tn.1 { 24135653e4daSdan sql1 { 24145653e4daSdan PRAGMA journal_mode = PERSIST; 24155653e4daSdan CREATE TABLE t1(a, b); 24165653e4daSdan INSERT INTO t1 VALUES('a', 'b'); 24175653e4daSdan } 24185653e4daSdan } {persist} 24195653e4daSdan do_test pager1-28.$tn.2 { file exists test.db-journal } 1 24205653e4daSdan do_test pager1-28.$tn.3 { sql1 { PRAGMA journal_mode = DELETE } } delete 24215653e4daSdan do_test pager1-28.$tn.4 { file exists test.db-journal } 0 24225653e4daSdan 24235653e4daSdan do_test pager1-28.$tn.5 { 24245653e4daSdan sql1 { 24255653e4daSdan PRAGMA journal_mode = PERSIST; 24265653e4daSdan INSERT INTO t1 VALUES('c', 'd'); 24275653e4daSdan } 24285653e4daSdan } {persist} 24295653e4daSdan do_test pager1-28.$tn.6 { file exists test.db-journal } 1 24305653e4daSdan do_test pager1-28.$tn.7 { 24315653e4daSdan sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); } 24325653e4daSdan } {} 24335653e4daSdan do_test pager1-28.$tn.8 { file exists test.db-journal } 1 24345653e4daSdan do_test pager1-28.$tn.9 { sql1 { PRAGMA journal_mode = DELETE } } delete 24355653e4daSdan do_test pager1-28.$tn.10 { file exists test.db-journal } 1 24365653e4daSdan 24375653e4daSdan do_test pager1-28.$tn.11 { sql2 COMMIT } {} 24385653e4daSdan do_test pager1-28.$tn.12 { file exists test.db-journal } 0 24395653e4daSdan 24405653e4daSdan do_test pager1-28-$tn.13 { 24415653e4daSdan code1 { set channel [db incrblob -readonly t1 a 2] } 24425653e4daSdan sql1 { 24435653e4daSdan PRAGMA journal_mode = PERSIST; 24445653e4daSdan INSERT INTO t1 VALUES('g', 'h'); 24455653e4daSdan } 24465653e4daSdan } {persist} 24475653e4daSdan do_test pager1-28.$tn.14 { file exists test.db-journal } 1 24485653e4daSdan do_test pager1-28.$tn.15 { 24495653e4daSdan sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); } 24505653e4daSdan } {} 24515653e4daSdan do_test pager1-28.$tn.16 { sql1 { PRAGMA journal_mode = DELETE } } delete 24525653e4daSdan do_test pager1-28.$tn.17 { file exists test.db-journal } 1 24535653e4daSdan 24545653e4daSdan do_test pager1-28.$tn.17 { csql2 { COMMIT } } {1 {database is locked}} 24555653e4daSdan do_test pager1-28-$tn.18 { code1 { read $channel } } c 24565653e4daSdan do_test pager1-28-$tn.19 { code1 { close $channel } } {} 24575653e4daSdan do_test pager1-28.$tn.20 { sql2 { COMMIT } } {} 24585653e4daSdan} 24595653e4daSdan 24601879b088Sdando_test pager1-29.1 { 24611879b088Sdan faultsim_delete_and_reopen 24621879b088Sdan execsql { 24631879b088Sdan PRAGMA page_size = 1024; 24641879b088Sdan PRAGMA auto_vacuum = full; 24651879b088Sdan PRAGMA locking_mode=exclusive; 24661879b088Sdan CREATE TABLE t1(a, b); 24671879b088Sdan INSERT INTO t1 VALUES(1, 2); 24681879b088Sdan } 24691879b088Sdan file size test.db 24701879b088Sdan} [expr 1024*3] 2471*4a8a6467Sdrhif {[nonzero_reserved_bytes]} { 2472*4a8a6467Sdrh # VACUUM with size changes is not possible with the codec. 2473*4a8a6467Sdrh do_test pager1-29.2 { 2474*4a8a6467Sdrh catchsql { 2475*4a8a6467Sdrh PRAGMA page_size = 4096; 2476*4a8a6467Sdrh VACUUM; 2477*4a8a6467Sdrh } 2478*4a8a6467Sdrh } {1 {attempt to write a readonly database}} 2479*4a8a6467Sdrh} else { 24801879b088Sdan do_test pager1-29.2 { 24811879b088Sdan execsql { 24821879b088Sdan PRAGMA page_size = 4096; 24831879b088Sdan VACUUM; 24841879b088Sdan } 24851879b088Sdan file size test.db 24861879b088Sdan } [expr 4096*3] 2487*4a8a6467Sdrh} 24881879b088Sdan 2489e08c2066Sdan#------------------------------------------------------------------------- 2490e08c2066Sdan# Test that if an empty database file (size 0 bytes) is opened in 2491e08c2066Sdan# exclusive-locking mode, any journal file is deleted from the file-system 2492e08c2066Sdan# without being rolled back. And that the RESERVED lock obtained while 2493e08c2066Sdan# doing this is not released. 2494e08c2066Sdan# 2495e08c2066Sdando_test pager1-30.1 { 2496e08c2066Sdan db close 2497fda06befSmistachkin delete_file test.db 2498fda06befSmistachkin delete_file test.db-journal 2499e08c2066Sdan set fd [open test.db-journal w] 2500e08c2066Sdan seek $fd [expr 512+1032*2] 2501e08c2066Sdan puts -nonewline $fd x 2502e08c2066Sdan close $fd 2503e08c2066Sdan 2504e08c2066Sdan sqlite3 db test.db 2505e08c2066Sdan execsql { 2506e08c2066Sdan PRAGMA locking_mode=EXCLUSIVE; 2507e08c2066Sdan SELECT count(*) FROM sqlite_master; 2508e08c2066Sdan PRAGMA lock_status; 2509e08c2066Sdan } 2510e08c2066Sdan} {exclusive 0 main reserved temp closed} 2511e08c2066Sdan 2512e08c2066Sdan#------------------------------------------------------------------------- 2513e08c2066Sdan# Test that if the "page-size" field in a journal-header is 0, the journal 2514e08c2066Sdan# file can still be rolled back. This is required for backward compatibility - 2515e08c2066Sdan# versions of SQLite prior to 3.5.8 always set this field to zero. 2516e08c2066Sdan# 251733f5379cSdanif {$tcl_platform(platform)=="unix"} { 2518e08c2066Sdando_test pager1-31.1 { 2519e08c2066Sdan faultsim_delete_and_reopen 2520e08c2066Sdan execsql { 2521e08c2066Sdan PRAGMA cache_size = 10; 2522e08c2066Sdan PRAGMA page_size = 1024; 2523e08c2066Sdan CREATE TABLE t1(x, y, UNIQUE(x, y)); 2524e08c2066Sdan INSERT INTO t1 VALUES(randomblob(1500), randomblob(1500)); 2525e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2526e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2527e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2528e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2529e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2530e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2531e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2532e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2533e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2534e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2535e08c2066Sdan BEGIN; 2536e08c2066Sdan UPDATE t1 SET y = randomblob(1499); 2537e08c2066Sdan } 2538fda06befSmistachkin copy_file test.db test.db2 2539fda06befSmistachkin copy_file test.db-journal test.db2-journal 2540e08c2066Sdan 2541e08c2066Sdan hexio_write test.db2-journal 24 00000000 2542e08c2066Sdan sqlite3 db2 test.db2 2543e08c2066Sdan execsql { PRAGMA integrity_check } db2 2544e08c2066Sdan} {ok} 254533f5379cSdan} 2546e08c2066Sdan 254731e80976Sdrh#------------------------------------------------------------------------- 254831e80976Sdrh# Test that a database file can be "pre-hinted" to a certain size and that 254931e80976Sdrh# subsequent spilling of the pager cache does not result in the database 255031e80976Sdrh# file being shrunk. 255131e80976Sdrh# 255231e80976Sdrhcatch {db close} 255331e80976Sdrhforcedelete test.db 255431e80976Sdrh 255531e80976Sdrhdo_test pager1-32.1 { 255631e80976Sdrh sqlite3 db test.db 255731e80976Sdrh execsql { 255831e80976Sdrh CREATE TABLE t1(x, y); 255931e80976Sdrh } 256031e80976Sdrh db close 256131e80976Sdrh sqlite3 db test.db 256231e80976Sdrh execsql { 256331e80976Sdrh BEGIN; 256431e80976Sdrh INSERT INTO t1 VALUES(1, randomblob(10000)); 256531e80976Sdrh } 25662f7820d8Sdrh file_control_chunksize_test db main 1024 256731e80976Sdrh file_control_sizehint_test db main 20971520; # 20MB 256831e80976Sdrh execsql { 256931e80976Sdrh PRAGMA cache_size = 10; 257031e80976Sdrh INSERT INTO t1 VALUES(1, randomblob(10000)); 257131e80976Sdrh INSERT INTO t1 VALUES(2, randomblob(10000)); 257231e80976Sdrh INSERT INTO t1 SELECT x+2, randomblob(10000) from t1; 257331e80976Sdrh INSERT INTO t1 SELECT x+4, randomblob(10000) from t1; 257431e80976Sdrh INSERT INTO t1 SELECT x+8, randomblob(10000) from t1; 257531e80976Sdrh INSERT INTO t1 SELECT x+16, randomblob(10000) from t1; 257631e80976Sdrh SELECT count(*) FROM t1; 257731e80976Sdrh COMMIT; 257831e80976Sdrh } 257931e80976Sdrh db close 258031e80976Sdrh file size test.db 258131e80976Sdrh} {20971520} 258231e80976Sdrh 258331e80976Sdrh# Cleanup 20MB file left by the previous test. 258431e80976Sdrhforcedelete test.db 25855653e4daSdan 25869fc5b4a5Sdan#------------------------------------------------------------------------- 25879fc5b4a5Sdan# Test that if a transaction is committed in journal_mode=DELETE mode, 25889fc5b4a5Sdan# and the call to unlink() returns an ENOENT error, the COMMIT does not 25899fc5b4a5Sdan# succeed. 25909fc5b4a5Sdan# 25919fc5b4a5Sdanif {$::tcl_platform(platform)=="unix"} { 25929fc5b4a5Sdan do_test pager1-33.1 { 25939fc5b4a5Sdan sqlite3 db test.db 25949fc5b4a5Sdan execsql { 25959fc5b4a5Sdan CREATE TABLE t1(x); 25969fc5b4a5Sdan INSERT INTO t1 VALUES('one'); 25979fc5b4a5Sdan INSERT INTO t1 VALUES('two'); 25989fc5b4a5Sdan BEGIN; 25999fc5b4a5Sdan INSERT INTO t1 VALUES('three'); 26009fc5b4a5Sdan INSERT INTO t1 VALUES('four'); 26019fc5b4a5Sdan } 26029fc5b4a5Sdan forcedelete bak-journal 26039fc5b4a5Sdan file rename test.db-journal bak-journal 26049fc5b4a5Sdan 26059fc5b4a5Sdan catchsql COMMIT 26069fc5b4a5Sdan } {1 {disk I/O error}} 26079fc5b4a5Sdan 26089fc5b4a5Sdan do_test pager1-33.2 { 26099fc5b4a5Sdan file rename bak-journal test.db-journal 26109fc5b4a5Sdan execsql { SELECT * FROM t1 } 26119fc5b4a5Sdan } {one two} 26129fc5b4a5Sdan} 26139fc5b4a5Sdan 2614d7a558a9Sdan#------------------------------------------------------------------------- 2615d7a558a9Sdan# Test that appending pages to the database file then moving those pages 2616d7a558a9Sdan# to the free-list before the transaction is committed does not cause 2617d7a558a9Sdan# an error. 2618d7a558a9Sdan# 2619d7a558a9Sdanforeach {tn pragma strsize} { 26209b4c59faSdrh 1 { PRAGMA mmap_size = 0 } 2400 2621d7a558a9Sdan 2 { } 2400 26229b4c59faSdrh 3 { PRAGMA mmap_size = 0 } 4400 2623d7a558a9Sdan 4 { } 4400 2624d7a558a9Sdan} { 2625d7a558a9Sdan reset_db 2626d7a558a9Sdan db func a_string a_string 2627d7a558a9Sdan db eval $pragma 2628d7a558a9Sdan do_execsql_test 34.$tn.1 { 2629d7a558a9Sdan CREATE TABLE t1(a, b); 2630d7a558a9Sdan INSERT INTO t1 VALUES(1, 2); 2631d7a558a9Sdan } 2632d7a558a9Sdan do_execsql_test 34.$tn.2 { 2633d7a558a9Sdan BEGIN; 2634d7a558a9Sdan INSERT INTO t1 VALUES(2, a_string($strsize)); 2635d7a558a9Sdan DELETE FROM t1 WHERE oid=2; 2636d7a558a9Sdan COMMIT; 2637d7a558a9Sdan PRAGMA integrity_check; 2638d7a558a9Sdan } {ok} 2639d7a558a9Sdan} 2640d7a558a9Sdan 2641d7a558a9Sdan#------------------------------------------------------------------------- 2642d7a558a9Sdan# 2643d7a558a9Sdanreset_db 2644d7a558a9Sdando_test 35 { 2645d7a558a9Sdan sqlite3 db test.db 2646d7a558a9Sdan 2647d7a558a9Sdan execsql { 2648d7a558a9Sdan CREATE TABLE t1(x, y); 2649d7a558a9Sdan PRAGMA journal_mode = WAL; 2650d7a558a9Sdan INSERT INTO t1 VALUES(1, 2); 2651d7a558a9Sdan } 2652d7a558a9Sdan 2653d7a558a9Sdan execsql { 2654d7a558a9Sdan BEGIN; 2655d7a558a9Sdan CREATE TABLE t2(a, b); 2656d7a558a9Sdan } 2657d7a558a9Sdan 2658d7a558a9Sdan hexio_write test.db-shm [expr 16*1024] [string repeat 0055 8192] 2659d7a558a9Sdan catchsql ROLLBACK 2660d7a558a9Sdan} {0 {}} 2661d7a558a9Sdan 2662d7a558a9Sdando_multiclient_test tn { 2663d7a558a9Sdan sql1 { 2664d7a558a9Sdan PRAGMA auto_vacuum = 0; 2665d7a558a9Sdan CREATE TABLE t1(x, y); 2666d7a558a9Sdan INSERT INTO t1 VALUES(1, 2); 2667d7a558a9Sdan } 2668d7a558a9Sdan 2669d7a558a9Sdan do_test 36.$tn.1 { 2670d7a558a9Sdan sql2 { PRAGMA max_page_count = 2 } 2671d7a558a9Sdan list [catch { sql2 { CREATE TABLE t2(x) } } msg] $msg 2672d7a558a9Sdan } {1 {database or disk is full}} 2673d7a558a9Sdan 2674d7a558a9Sdan sql1 { PRAGMA checkpoint_fullfsync = 1 } 2675d7a558a9Sdan sql1 { CREATE TABLE t2(x) } 2676d7a558a9Sdan 2677d7a558a9Sdan do_test 36.$tn.2 { 2678d7a558a9Sdan sql2 { INSERT INTO t2 VALUES('xyz') } 2679d7a558a9Sdan list [catch { sql2 { CREATE TABLE t3(x) } } msg] $msg 2680d7a558a9Sdan } {1 {database or disk is full}} 2681d7a558a9Sdan} 2682d7a558a9Sdan 2683d7a558a9Sdanforcedelete test1 test2 2684d7a558a9Sdanforeach {tn uri} { 2685d7a558a9Sdan 1 {file:?mode=memory&cache=shared} 2686d7a558a9Sdan 2 {file:one?mode=memory&cache=shared} 2687d7a558a9Sdan 3 {file:test1?cache=shared} 2688d7a558a9Sdan 4 {file:test2?another=parameter&yet=anotherone} 2689d7a558a9Sdan} { 2690d7a558a9Sdan do_test 37.$tn { 2691d7a558a9Sdan catch { db close } 2692d7a558a9Sdan sqlite3_shutdown 2693d7a558a9Sdan sqlite3_config_uri 1 2694d7a558a9Sdan sqlite3 db $uri 2695abd6d84aSdan 2696d7a558a9Sdan db eval { 2697d7a558a9Sdan CREATE TABLE t1(x); 2698d7a558a9Sdan INSERT INTO t1 VALUES(1); 2699d7a558a9Sdan SELECT * FROM t1; 2700d7a558a9Sdan } 2701d7a558a9Sdan } {1} 2702abd6d84aSdan 2703abd6d84aSdan do_execsql_test 37.$tn.2 { 2704abd6d84aSdan VACUUM; 2705abd6d84aSdan SELECT * FROM t1; 2706abd6d84aSdan } {1} 2707abd6d84aSdan 2708d7a558a9Sdan db close 2709d7a558a9Sdan sqlite3_shutdown 2710d7a558a9Sdan sqlite3_config_uri 0 2711d7a558a9Sdan} 2712d7a558a9Sdan 2713d7a558a9Sdando_test 38.1 { 2714d7a558a9Sdan catch { db close } 2715d7a558a9Sdan forcedelete test.db 2716d7a558a9Sdan set fd [open test.db w] 2717d7a558a9Sdan puts $fd "hello world" 2718d7a558a9Sdan close $fd 2719d7a558a9Sdan sqlite3 db test.db 2720d7a558a9Sdan catchsql { CREATE TABLE t1(x) } 2721d7a558a9Sdan} {1 {file is encrypted or is not a database}} 2722d7a558a9Sdando_test 38.2 { 2723d7a558a9Sdan catch { db close } 2724d7a558a9Sdan forcedelete test.db 2725d7a558a9Sdan} {} 2726d7a558a9Sdan 2727d7a558a9Sdando_test 39.1 { 2728d7a558a9Sdan sqlite3 db test.db 2729d7a558a9Sdan execsql { 2730d7a558a9Sdan PRAGMA auto_vacuum = 1; 2731d7a558a9Sdan CREATE TABLE t1(x); 2732d7a558a9Sdan INSERT INTO t1 VALUES('xxx'); 2733d7a558a9Sdan INSERT INTO t1 VALUES('two'); 2734d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(400)); 2735d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(400)); 2736d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(400)); 2737d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(400)); 2738d7a558a9Sdan BEGIN; 2739d7a558a9Sdan UPDATE t1 SET x = 'one' WHERE rowid=1; 2740d7a558a9Sdan } 2741d7a558a9Sdan set ::stmt [sqlite3_prepare db "SELECT * FROM t1 ORDER BY rowid" -1 dummy] 2742d7a558a9Sdan sqlite3_step $::stmt 2743d7a558a9Sdan sqlite3_column_text $::stmt 0 2744d7a558a9Sdan} {one} 2745d7a558a9Sdando_test 39.2 { 2746d7a558a9Sdan execsql { CREATE TABLE t2(x) } 2747d7a558a9Sdan sqlite3_step $::stmt 2748d7a558a9Sdan sqlite3_column_text $::stmt 0 2749d7a558a9Sdan} {two} 2750d7a558a9Sdando_test 39.3 { 2751d7a558a9Sdan sqlite3_finalize $::stmt 2752d7a558a9Sdan execsql COMMIT 2753d7a558a9Sdan} {} 2754d7a558a9Sdan 2755d7a558a9Sdando_execsql_test 39.4 { 2756d7a558a9Sdan PRAGMA auto_vacuum = 2; 2757d7a558a9Sdan CREATE TABLE t3(x); 2758d7a558a9Sdan CREATE TABLE t4(x); 2759d7a558a9Sdan 2760d7a558a9Sdan DROP TABLE t2; 2761d7a558a9Sdan DROP TABLE t3; 2762d7a558a9Sdan DROP TABLE t4; 2763d7a558a9Sdan} 2764d7a558a9Sdando_test 39.5 { 2765d7a558a9Sdan db close 2766d7a558a9Sdan sqlite3 db test.db 2767d7a558a9Sdan execsql { 2768d7a558a9Sdan PRAGMA cache_size = 1; 2769d7a558a9Sdan PRAGMA incremental_vacuum; 2770d7a558a9Sdan PRAGMA integrity_check; 2771d7a558a9Sdan } 2772d7a558a9Sdan} {ok} 2773d7a558a9Sdan 2774d7a558a9Sdando_test 40.1 { 2775d7a558a9Sdan reset_db 2776d7a558a9Sdan execsql { 2777d7a558a9Sdan PRAGMA auto_vacuum = 1; 2778d7a558a9Sdan CREATE TABLE t1(x PRIMARY KEY); 2779d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(1200)); 2780d7a558a9Sdan PRAGMA page_count; 2781d7a558a9Sdan } 2782d7a558a9Sdan} {6} 2783d7a558a9Sdando_test 40.2 { 2784d7a558a9Sdan execsql { 2785d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(1200)); 2786d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(1200)); 2787d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(1200)); 2788d7a558a9Sdan } 2789d7a558a9Sdan} {} 2790d7a558a9Sdando_test 40.3 { 2791d7a558a9Sdan db close 2792d7a558a9Sdan sqlite3 db test.db 2793d7a558a9Sdan execsql { 2794d7a558a9Sdan PRAGMA cache_size = 1; 2795d7a558a9Sdan CREATE TABLE t2(x); 2796d7a558a9Sdan PRAGMA integrity_check; 2797d7a558a9Sdan } 2798d7a558a9Sdan} {ok} 2799d7a558a9Sdan 2800d7a558a9Sdando_test 41.1 { 2801d7a558a9Sdan reset_db 2802d7a558a9Sdan execsql { 2803d7a558a9Sdan CREATE TABLE t1(x PRIMARY KEY); 2804d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(200)); 2805d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2806d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2807d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2808d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2809d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2810d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2811d7a558a9Sdan } 2812d7a558a9Sdan} {} 2813d7a558a9Sdando_test 41.2 { 2814d7a558a9Sdan testvfs tv -default 1 2815d7a558a9Sdan tv sectorsize 16384; 2816d7a558a9Sdan tv devchar [list] 2817d7a558a9Sdan db close 2818d7a558a9Sdan sqlite3 db test.db 2819d7a558a9Sdan execsql { 2820d7a558a9Sdan PRAGMA cache_size = 1; 2821d7a558a9Sdan DELETE FROM t1 WHERE rowid%4; 2822d7a558a9Sdan PRAGMA integrity_check; 2823d7a558a9Sdan } 2824d7a558a9Sdan} {ok} 2825abd6d84aSdandb close 2826abd6d84aSdantv delete 2827d7a558a9Sdan 2828abd6d84aSdanset pending_prev [sqlite3_test_control_pending_byte 0x1000000] 2829abd6d84aSdando_test 42.1 { 2830abd6d84aSdan reset_db 2831abd6d84aSdan execsql { 2832abd6d84aSdan CREATE TABLE t1(x, y); 2833abd6d84aSdan INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); 2834abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2835abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2836abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2837abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2838abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2839abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2840abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2841abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2842abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2843abd6d84aSdan } 2844abd6d84aSdan db close 2845abd6d84aSdan sqlite3_test_control_pending_byte 0x0010000 2846abd6d84aSdan sqlite3 db test.db 28479b4c59faSdrh db eval { PRAGMA mmap_size = 0 } 2848abd6d84aSdan catchsql { SELECT sum(length(y)) FROM t1 } 2849abd6d84aSdan} {1 {database disk image is malformed}} 2850abd6d84aSdando_test 42.2 { 2851abd6d84aSdan reset_db 2852abd6d84aSdan execsql { 2853abd6d84aSdan CREATE TABLE t1(x, y); 2854abd6d84aSdan INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); 2855abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2856abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2857abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2858abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2859abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2860abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2861abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2862abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2863abd6d84aSdan } 2864abd6d84aSdan db close 2865abd6d84aSdan 2866abd6d84aSdan testvfs tv -default 1 2867abd6d84aSdan tv sectorsize 16384; 2868abd6d84aSdan tv devchar [list] 2869abd6d84aSdan sqlite3 db test.db -vfs tv 2870abd6d84aSdan execsql { UPDATE t1 SET x = randomblob(200) } 2871abd6d84aSdan} {} 2872abd6d84aSdandb close 2873abd6d84aSdantv delete 2874abd6d84aSdansqlite3_test_control_pending_byte $pending_prev 2875abd6d84aSdan 2876abd6d84aSdando_test 43.1 { 2877abd6d84aSdan reset_db 2878abd6d84aSdan execsql { 2879abd6d84aSdan CREATE TABLE t1(x, y); 2880abd6d84aSdan INSERT INTO t1 VALUES(1, 2); 2881abd6d84aSdan CREATE TABLE t2(x, y); 2882abd6d84aSdan INSERT INTO t2 VALUES(1, 2); 2883abd6d84aSdan CREATE TABLE t3(x, y); 2884abd6d84aSdan INSERT INTO t3 VALUES(1, 2); 2885abd6d84aSdan } 2886abd6d84aSdan db close 2887abd6d84aSdan sqlite3 db test.db 2888abd6d84aSdan 28899b4c59faSdrh db eval { PRAGMA mmap_size = 0 } 2890abd6d84aSdan db eval { SELECT * FROM t1 } 2891abd6d84aSdan sqlite3_db_status db CACHE_MISS 0 2892abd6d84aSdan} {0 2 0} 2893abd6d84aSdan 2894abd6d84aSdando_test 43.2 { 2895abd6d84aSdan db eval { SELECT * FROM t2 } 2896abd6d84aSdan sqlite3_db_status db CACHE_MISS 1 2897abd6d84aSdan} {0 3 0} 2898abd6d84aSdan 2899abd6d84aSdando_test 43.3 { 2900abd6d84aSdan db eval { SELECT * FROM t3 } 2901abd6d84aSdan sqlite3_db_status db CACHE_MISS 0 2902abd6d84aSdan} {0 1 0} 2903d7a558a9Sdan 2904d353331aSdanfinish_test 2905