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