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 2069aedc8dSdanif {[atomic_batch_write test.db]} { 2169aedc8dSdan finish_test 2269aedc8dSdan return 2369aedc8dSdan} 24a32536b4Sdanifcapable !incrblob { 25a32536b4Sdan finish_test 26a32536b4Sdan return 27a32536b4Sdan} 2869aedc8dSdan 2968928b6cSdan# Do not use a codec for tests in this file, as the database file is 3068928b6cSdan# manipulated directly using tcl scripts (using the [hexio_write] command). 3168928b6cSdan# 3268928b6cSdando_not_use_codec 33e91a54e1Sdan 34b0ac3e3aSdan# 35b0ac3e3aSdan# pager1-1.*: Test inter-process locking (clients in multiple processes). 36b0ac3e3aSdan# 37b0ac3e3aSdan# pager1-2.*: Test intra-process locking (multiple clients in this process). 38b0ac3e3aSdan# 39b0ac3e3aSdan# pager1-3.*: Savepoint related tests. 40b0ac3e3aSdan# 411f4cb65aSdan# pager1-4.*: Hot-journal related tests. 421f4cb65aSdan# 43de4996e2Sdan# pager1-5.*: Cases related to multi-file commits. 44de4996e2Sdan# 45146ed78bSdan# pager1-6.*: Cases related to "PRAGMA max_page_count" 46146ed78bSdan# 47153eda0aSdan# pager1-7.*: Cases specific to "PRAGMA journal_mode=TRUNCATE" 48153eda0aSdan# 490e986f51Sdan# pager1-8.*: Cases using temporary and in-memory databases. 500e986f51Sdan# 51dca321aeSdan# pager1-9.*: Tests related to the backup API. 52dca321aeSdan# 53ec6ffc1aSdan# pager1-10.*: Test that the assumed file-system sector-size is limited to 54ec6ffc1aSdan# 64KB. 55ec6ffc1aSdan# 56d353331aSdan# pager1-12.*: Tests involving "PRAGMA page_size" 57d353331aSdan# 58d353331aSdan# pager1-13.*: Cases specific to "PRAGMA journal_mode=PERSIST" 59d353331aSdan# 60d353331aSdan# pager1-14.*: Cases specific to "PRAGMA journal_mode=OFF" 61ec6ffc1aSdan# 62c8ce3972Sdan# pager1-15.*: Varying sqlite3_vfs.szOsFile 63c8ce3972Sdan# 64c8ce3972Sdan# pager1-16.*: Varying sqlite3_vfs.mxPathname 65c8ce3972Sdan# 66c8ce3972Sdan# pager1-17.*: Tests related to "PRAGMA omit_readlock" 6733f111dcSdrh# (The omit_readlock pragma has been removed and so have 6833f111dcSdrh# these tests.) 69c8ce3972Sdan# 70c8ce3972Sdan# pager1-18.*: Test that the pager layer responds correctly if the b-tree 71c8ce3972Sdan# requests an invalid page number (due to db corruption). 72c8ce3972Sdan# 73b0ac3e3aSdan 74c396d4afSdanproc recursive_select {id table {script {}}} { 75c396d4afSdan set cnt 0 76c396d4afSdan db eval "SELECT rowid, * FROM $table WHERE rowid = ($id-1)" { 77c396d4afSdan recursive_select $rowid $table $script 78c396d4afSdan incr cnt 79c396d4afSdan } 80c396d4afSdan if {$cnt==0} { eval $script } 81c396d4afSdan} 82c396d4afSdan 8353f04f3bSdanset a_string_counter 1 8453f04f3bSdanproc a_string {n} { 8553f04f3bSdan global a_string_counter 8653f04f3bSdan incr a_string_counter 8753f04f3bSdan string range [string repeat "${a_string_counter}." $n] 1 $n 8853f04f3bSdan} 8953f04f3bSdandb func a_string a_string 9053f04f3bSdan 91a4a9095eSdando_multiclient_test tn { 92e91a54e1Sdan 93e91a54e1Sdan # Create and populate a database table using connection [db]. Check 94e91a54e1Sdan # that connections [db2] and [db3] can see the schema and content. 95e91a54e1Sdan # 96e91a54e1Sdan do_test pager1-$tn.1 { 97e91a54e1Sdan sql1 { 98e91a54e1Sdan CREATE TABLE t1(a PRIMARY KEY, b); 99e91a54e1Sdan CREATE INDEX i1 ON t1(b); 100d353331aSdan INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); 101e91a54e1Sdan } 102e91a54e1Sdan } {} 103e91a54e1Sdan do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two} 104e91a54e1Sdan do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two} 105e91a54e1Sdan 106e91a54e1Sdan # Open a transaction and add a row using [db]. This puts [db] in 107e91a54e1Sdan # RESERVED state. Check that connections [db2] and [db3] can still 108e91a54e1Sdan # read the database content as it was before the transaction was 109e91a54e1Sdan # opened. [db] should see the inserted row. 110e91a54e1Sdan # 111e91a54e1Sdan do_test pager1-$tn.4 { 112e91a54e1Sdan sql1 { 113e91a54e1Sdan BEGIN; 114e91a54e1Sdan INSERT INTO t1 VALUES(3, 'three'); 115e91a54e1Sdan } 116e91a54e1Sdan } {} 117e91a54e1Sdan do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two} 118e91a54e1Sdan do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} 119e91a54e1Sdan 120e91a54e1Sdan # [db] still has an open write transaction. Check that this prevents 121e91a54e1Sdan # other connections (specifically [db2]) from writing to the database. 122e91a54e1Sdan # 123e91a54e1Sdan # Even if [db2] opens a transaction first, it may not write to the 124e91a54e1Sdan # database. After the attempt to write the db within a transaction, 125e91a54e1Sdan # [db2] is left with an open transaction, but not a read-lock on 126e91a54e1Sdan # the main database. So it does not prevent [db] from committing. 127e91a54e1Sdan # 128e91a54e1Sdan do_test pager1-$tn.8 { 129e91a54e1Sdan csql2 { UPDATE t1 SET a = a + 10 } 130e91a54e1Sdan } {1 {database is locked}} 131e91a54e1Sdan do_test pager1-$tn.9 { 132e91a54e1Sdan csql2 { 133e91a54e1Sdan BEGIN; 134e91a54e1Sdan UPDATE t1 SET a = a + 10; 135e91a54e1Sdan } 136e91a54e1Sdan } {1 {database is locked}} 137e91a54e1Sdan 138e91a54e1Sdan # Have [db] commit its transactions. Check the other connections can 139e91a54e1Sdan # now see the new database content. 140e91a54e1Sdan # 141e91a54e1Sdan do_test pager1-$tn.10 { sql1 { COMMIT } } {} 142e91a54e1Sdan do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} 143e91a54e1Sdan do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 144e91a54e1Sdan do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 145e91a54e1Sdan 146e91a54e1Sdan # Check that, as noted above, [db2] really did keep an open transaction 147e91a54e1Sdan # after the attempt to write the database failed. 148e91a54e1Sdan # 149e91a54e1Sdan do_test pager1-$tn.14 { 150e91a54e1Sdan csql2 { BEGIN } 151e91a54e1Sdan } {1 {cannot start a transaction within a transaction}} 152e91a54e1Sdan do_test pager1-$tn.15 { sql2 { ROLLBACK } } {} 153e91a54e1Sdan 154e91a54e1Sdan # Have [db2] open a transaction and take a read-lock on the database. 155e91a54e1Sdan # Check that this prevents [db] from writing to the database (outside 156e91a54e1Sdan # of any transaction). After this fails, check that [db3] can read 157e91a54e1Sdan # the db (showing that [db] did not take a PENDING lock etc.) 158e91a54e1Sdan # 159e91a54e1Sdan do_test pager1-$tn.15 { 160e91a54e1Sdan sql2 { BEGIN; SELECT * FROM t1; } 161e91a54e1Sdan } {1 one 2 two 3 three} 162e91a54e1Sdan do_test pager1-$tn.16 { 163e91a54e1Sdan csql1 { UPDATE t1 SET a = a + 10 } 164e91a54e1Sdan } {1 {database is locked}} 165e91a54e1Sdan do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 166e91a54e1Sdan 167e91a54e1Sdan # This time, have [db] open a transaction before writing the database. 168e91a54e1Sdan # This works - [db] gets a RESERVED lock which does not conflict with 169e91a54e1Sdan # the SHARED lock [db2] is holding. 170e91a54e1Sdan # 171e91a54e1Sdan do_test pager1-$tn.18 { 172e91a54e1Sdan sql1 { 173e91a54e1Sdan BEGIN; 174e91a54e1Sdan UPDATE t1 SET a = a + 10; 175e91a54e1Sdan } 176e91a54e1Sdan } {} 177e91a54e1Sdan do_test pager1-$tn-19 { 178e91a54e1Sdan sql1 { PRAGMA lock_status } 179e91a54e1Sdan } {main reserved temp closed} 180e91a54e1Sdan do_test pager1-$tn-20 { 181e91a54e1Sdan sql2 { PRAGMA lock_status } 182e91a54e1Sdan } {main shared temp closed} 183e91a54e1Sdan 184e91a54e1Sdan # Check that all connections can still read the database. Only [db] sees 185e91a54e1Sdan # the updated content (as the transaction has not been committed yet). 186e91a54e1Sdan # 187e91a54e1Sdan do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} 188e91a54e1Sdan do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 189e91a54e1Sdan do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 190e91a54e1Sdan 191e91a54e1Sdan # Because [db2] still has the SHARED lock, [db] is unable to commit the 192e91a54e1Sdan # transaction. If it tries, an error is returned and the connection 193e91a54e1Sdan # upgrades to a PENDING lock. 194e91a54e1Sdan # 195e91a54e1Sdan # Once this happens, [db] can read the database and see the new content, 196e91a54e1Sdan # [db2] (still holding SHARED) can still read the old content, but [db3] 197e91a54e1Sdan # (not holding any lock) is prevented by [db]'s PENDING from reading 198e91a54e1Sdan # the database. 199e91a54e1Sdan # 200e91a54e1Sdan do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}} 201e91a54e1Sdan do_test pager1-$tn-25 { 202e91a54e1Sdan sql1 { PRAGMA lock_status } 203e91a54e1Sdan } {main pending temp closed} 204e91a54e1Sdan do_test pager1-$tn.26 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} 205e91a54e1Sdan do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 206e91a54e1Sdan do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} 207e91a54e1Sdan 208e91a54e1Sdan # Have [db2] commit its read transaction, releasing the SHARED lock it 209e91a54e1Sdan # is holding. Now, neither [db2] nor [db3] may read the database (as [db] 210e91a54e1Sdan # is still holding a PENDING). 211e91a54e1Sdan # 212e91a54e1Sdan do_test pager1-$tn.29 { sql2 { COMMIT } } {} 213e91a54e1Sdan do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}} 214e91a54e1Sdan do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} 215e91a54e1Sdan 216e91a54e1Sdan # [db] is now able to commit the transaction. Once the transaction is 217e91a54e1Sdan # committed, all three connections can read the new content. 218e91a54e1Sdan # 219e91a54e1Sdan do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {} 220e91a54e1Sdan do_test pager1-$tn.26 { sql1 { COMMIT } } {} 221e91a54e1Sdan do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three} 222e91a54e1Sdan do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three} 223e91a54e1Sdan do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three} 224d353331aSdan 225d353331aSdan # Install a busy-handler for connection [db]. 226d353331aSdan # 227d353331aSdan set ::nbusy [list] 228d353331aSdan proc busy {n} { 229d353331aSdan lappend ::nbusy $n 230d353331aSdan if {$n>5} { sql2 COMMIT } 231d353331aSdan return 0 232d353331aSdan } 233d353331aSdan db busy busy 234d353331aSdan 235d353331aSdan do_test pager1-$tn.29 { 236d353331aSdan sql1 { BEGIN ; INSERT INTO t1 VALUES('x', 'y') } 237d353331aSdan } {} 238d353331aSdan do_test pager1-$tn.30 { 239d353331aSdan sql2 { BEGIN ; SELECT * FROM t1 } 240d353331aSdan } {21 one 22 two 23 three} 241d353331aSdan do_test pager1-$tn.31 { sql1 COMMIT } {} 242d353331aSdan do_test pager1-$tn.32 { set ::nbusy } {0 1 2 3 4 5 6} 243e91a54e1Sdan} 244e91a54e1Sdan 24553f04f3bSdan#------------------------------------------------------------------------- 24653f04f3bSdan# Savepoint related test cases. 24753f04f3bSdan# 248dca321aeSdan# pager1-3.1.2.*: Force a savepoint rollback to cause the database file 249dca321aeSdan# to grow. 250dca321aeSdan# 251273f3f0dSdan# pager1-3.1.3.*: Use a journal created in synchronous=off mode as part 252273f3f0dSdan# of a savepoint rollback. 253273f3f0dSdan# 2540e986f51Sdando_test pager1-3.1.1 { 255b0ac3e3aSdan faultsim_delete_and_reopen 256b0ac3e3aSdan execsql { 257b0ac3e3aSdan CREATE TABLE t1(a PRIMARY KEY, b); 258b0ac3e3aSdan CREATE TABLE counter( 259b0ac3e3aSdan i CHECK (i<5), 260b0ac3e3aSdan u CHECK (u<10) 261b0ac3e3aSdan ); 262b0ac3e3aSdan INSERT INTO counter VALUES(0, 0); 263b0ac3e3aSdan CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN 264b0ac3e3aSdan UPDATE counter SET i = i+1; 265b0ac3e3aSdan END; 266b0ac3e3aSdan CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN 267b0ac3e3aSdan UPDATE counter SET u = u+1; 268b0ac3e3aSdan END; 269b0ac3e3aSdan } 270b0ac3e3aSdan execsql { SELECT * FROM counter } 271b0ac3e3aSdan} {0 0} 272b0ac3e3aSdan 2730e986f51Sdando_execsql_test pager1-3.1.2 { 274d353331aSdan PRAGMA cache_size = 10; 275b0ac3e3aSdan BEGIN; 276b0ac3e3aSdan INSERT INTO t1 VALUES(1, randomblob(1500)); 277b0ac3e3aSdan INSERT INTO t1 VALUES(2, randomblob(1500)); 278b0ac3e3aSdan INSERT INTO t1 VALUES(3, randomblob(1500)); 279b0ac3e3aSdan SELECT * FROM counter; 280b0ac3e3aSdan} {3 0} 2810e986f51Sdando_catchsql_test pager1-3.1.3 { 282b0ac3e3aSdan INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1 28392e21ef0Sdrh} {1 {CHECK constraint failed: i<5}} 284b0ac3e3aSdando_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0} 285b0ac3e3aSdando_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3} 286b0ac3e3aSdando_execsql_test pager1-3.6 { COMMIT } {} 287b0ac3e3aSdan 288273f3f0dSdanforeach {tn sql tcl} { 289d353331aSdan 7 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 0 } { 290273f3f0dSdan testvfs tv -default 1 291273f3f0dSdan tv devchar safe_append 292273f3f0dSdan } 293d353331aSdan 8 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 2 } { 294d353331aSdan testvfs tv -default 1 295d353331aSdan tv devchar sequential 296d353331aSdan } 297d353331aSdan 9 { PRAGMA synchronous = FULL } { } 298d353331aSdan 10 { PRAGMA synchronous = NORMAL } { } 299d353331aSdan 11 { PRAGMA synchronous = OFF } { } 300d353331aSdan 12 { PRAGMA synchronous = FULL ; PRAGMA fullfsync = 1 } { } 301d353331aSdan 13 { PRAGMA synchronous = FULL } { 302d353331aSdan testvfs tv -default 1 303d353331aSdan tv devchar sequential 304d353331aSdan } 3056b63ab47Sdan 14 { PRAGMA locking_mode = EXCLUSIVE } { 3066b63ab47Sdan } 307273f3f0dSdan} { 308273f3f0dSdan do_test pager1-3.$tn.1 { 309273f3f0dSdan eval $tcl 310dca321aeSdan faultsim_delete_and_reopen 311dca321aeSdan db func a_string a_string 312273f3f0dSdan execsql $sql 313dca321aeSdan execsql { 314dca321aeSdan PRAGMA auto_vacuum = 2; 315dca321aeSdan PRAGMA cache_size = 10; 316dca321aeSdan CREATE TABLE z(x INTEGER PRIMARY KEY, y); 317dca321aeSdan BEGIN; 318dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 319dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 2 320dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 4 321dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 8 322dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 16 323dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 32 324dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 64 325dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 128 326dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 256 327dca321aeSdan COMMIT; 328dca321aeSdan } 329dca321aeSdan execsql { PRAGMA auto_vacuum } 330dca321aeSdan } {2} 331273f3f0dSdan do_execsql_test pager1-3.$tn.2 { 332dca321aeSdan BEGIN; 333dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 334dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 335dca321aeSdan SAVEPOINT one; 336273f3f0dSdan UPDATE z SET y = NULL WHERE x>256; 337dca321aeSdan PRAGMA incremental_vacuum; 338dca321aeSdan SELECT count(*) FROM z WHERE x < 100; 339dca321aeSdan ROLLBACK TO one; 340dca321aeSdan COMMIT; 341dca321aeSdan } {99} 342dca321aeSdan 343273f3f0dSdan do_execsql_test pager1-3.$tn.3 { 344273f3f0dSdan BEGIN; 345273f3f0dSdan SAVEPOINT one; 346273f3f0dSdan UPDATE z SET y = y||x; 347273f3f0dSdan ROLLBACK TO one; 348273f3f0dSdan COMMIT; 349273f3f0dSdan SELECT count(*) FROM z; 350273f3f0dSdan } {258} 351273f3f0dSdan 352273f3f0dSdan do_execsql_test pager1-3.$tn.4 { 353273f3f0dSdan SAVEPOINT one; 354273f3f0dSdan UPDATE z SET y = y||x; 355273f3f0dSdan ROLLBACK TO one; 356273f3f0dSdan } {} 357273f3f0dSdan do_execsql_test pager1-3.$tn.5 { 358273f3f0dSdan SELECT count(*) FROM z; 359273f3f0dSdan RELEASE one; 360273f3f0dSdan PRAGMA integrity_check; 361273f3f0dSdan } {258 ok} 362273f3f0dSdan 36378f1e538Sdan do_execsql_test pager1-3.$tn.6 { 36478f1e538Sdan SAVEPOINT one; 36578f1e538Sdan RELEASE one; 36678f1e538Sdan } {} 36778f1e538Sdan 368273f3f0dSdan db close 369273f3f0dSdan catch { tv delete } 370273f3f0dSdan} 371273f3f0dSdan 37253f04f3bSdan#------------------------------------------------------------------------- 37353f04f3bSdan# Hot journal rollback related test cases. 37453f04f3bSdan# 37553f04f3bSdan# pager1.4.1.*: Test that the pager module deletes very small invalid 37653f04f3bSdan# journal files. 37753f04f3bSdan# 37853f04f3bSdan# pager1.4.2.*: Test that if the master journal pointer at the end of a 37953f04f3bSdan# hot-journal file appears to be corrupt (checksum does not 38053f04f3bSdan# compute) the associated journal is rolled back (and no 38153f04f3bSdan# xAccess() call to check for the presence of any master 38253f04f3bSdan# journal file is made). 38353f04f3bSdan# 384de4996e2Sdan# pager1.4.3.*: Test that the contents of a hot-journal are ignored if the 385de4996e2Sdan# page-size or sector-size in the journal header appear to 386de4996e2Sdan# be invalid (too large, too small or not a power of 2). 387de4996e2Sdan# 388e08341c6Sdan# pager1.4.4.*: Test hot-journal rollback of journal file with a master 389e08341c6Sdan# journal pointer generated in various "PRAGMA synchronous" 390e08341c6Sdan# modes. 391e08341c6Sdan# 392e08341c6Sdan# pager1.4.5.*: Test that hot-journal rollback stops if it encounters a 393e08341c6Sdan# journal-record for which the checksum fails. 394e08341c6Sdan# 395ec6ffc1aSdan# pager1.4.6.*: Test that when rolling back a hot-journal that contains a 396ec6ffc1aSdan# master journal pointer, the master journal file is deleted 397ec6ffc1aSdan# after all the hot-journals that refer to it are deleted. 398ec6ffc1aSdan# 399c8ce3972Sdan# pager1.4.7.*: Test that if a hot-journal file exists but a client can 400c8ce3972Sdan# open it for reading only, the database cannot be accessed and 401c8ce3972Sdan# SQLITE_CANTOPEN is returned. 402c8ce3972Sdan# 40353f04f3bSdando_test pager1.4.1.1 { 40453f04f3bSdan faultsim_delete_and_reopen 40553f04f3bSdan execsql { 40653f04f3bSdan CREATE TABLE x(y, z); 40753f04f3bSdan INSERT INTO x VALUES(1, 2); 40853f04f3bSdan } 40953f04f3bSdan set fd [open test.db-journal w] 41053f04f3bSdan puts -nonewline $fd "helloworld" 41153f04f3bSdan close $fd 41253f04f3bSdan file exists test.db-journal 41353f04f3bSdan} {1} 41453f04f3bSdando_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2} 41553f04f3bSdando_test pager1.4.1.3 { file exists test.db-journal } {0} 41653f04f3bSdan 41753f04f3bSdan# Set up a [testvfs] to snapshot the file-system just before SQLite 41853f04f3bSdan# deletes the master-journal to commit a multi-file transaction. 41953f04f3bSdan# 42053f04f3bSdan# In subsequent test cases, invoking [faultsim_restore_and_reopen] sets 42153f04f3bSdan# up the file system to contain two databases, two hot-journal files and 42253f04f3bSdan# a master-journal. 42353f04f3bSdan# 42453f04f3bSdando_test pager1.4.2.1 { 42553f04f3bSdan testvfs tstvfs -default 1 42653f04f3bSdan tstvfs filter xDelete 42753f04f3bSdan tstvfs script xDeleteCallback 42853f04f3bSdan proc xDeleteCallback {method file args} { 42953f04f3bSdan set file [file tail $file] 43053f04f3bSdan if { [string match *mj* $file] } { faultsim_save } 43153f04f3bSdan } 43253f04f3bSdan faultsim_delete_and_reopen 43353f04f3bSdan db func a_string a_string 43453f04f3bSdan execsql { 43553f04f3bSdan ATTACH 'test.db2' AS aux; 43653f04f3bSdan PRAGMA journal_mode = DELETE; 43753f04f3bSdan PRAGMA main.cache_size = 10; 43853f04f3bSdan PRAGMA aux.cache_size = 10; 43953f04f3bSdan CREATE TABLE t1(a UNIQUE, b UNIQUE); 44053f04f3bSdan CREATE TABLE aux.t2(a UNIQUE, b UNIQUE); 44153f04f3bSdan INSERT INTO t1 VALUES(a_string(200), a_string(300)); 44253f04f3bSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 44353f04f3bSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 44453f04f3bSdan INSERT INTO t2 SELECT * FROM t1; 44553f04f3bSdan BEGIN; 44653f04f3bSdan INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1; 44753f04f3bSdan INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1; 44853f04f3bSdan INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1; 44953f04f3bSdan INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1; 45053f04f3bSdan REPLACE INTO t2 SELECT * FROM t1; 45153f04f3bSdan COMMIT; 45253f04f3bSdan } 45353f04f3bSdan db close 45453f04f3bSdan tstvfs delete 45553f04f3bSdan} {} 456b2f20bfcSshaneh 457b2f20bfcSshanehif {$::tcl_platform(platform)!="windows"} { 45853f04f3bSdando_test pager1.4.2.2 { 45953f04f3bSdan faultsim_restore_and_reopen 46053f04f3bSdan execsql { 46153f04f3bSdan SELECT count(*) FROM t1; 46253f04f3bSdan PRAGMA integrity_check; 46353f04f3bSdan } 46453f04f3bSdan} {4 ok} 46553f04f3bSdando_test pager1.4.2.3 { 46653f04f3bSdan faultsim_restore_and_reopen 467fda06befSmistachkin foreach f [glob test.db-mj*] { forcedelete $f } 46853f04f3bSdan execsql { 46953f04f3bSdan SELECT count(*) FROM t1; 47053f04f3bSdan PRAGMA integrity_check; 47153f04f3bSdan } 47253f04f3bSdan} {64 ok} 47353f04f3bSdando_test pager1.4.2.4 { 47453f04f3bSdan faultsim_restore_and_reopen 4750971140bSdrh hexio_write test.db-journal [expr [file size test.db-journal]-30] 123456 47653f04f3bSdan execsql { 47753f04f3bSdan SELECT count(*) FROM t1; 47853f04f3bSdan PRAGMA integrity_check; 47953f04f3bSdan } 48053f04f3bSdan} {4 ok} 48153f04f3bSdando_test pager1.4.2.5 { 48253f04f3bSdan faultsim_restore_and_reopen 4830971140bSdrh hexio_write test.db-journal [expr [file size test.db-journal]-30] 123456 484fda06befSmistachkin foreach f [glob test.db-mj*] { forcedelete $f } 48553f04f3bSdan execsql { 48653f04f3bSdan SELECT count(*) FROM t1; 48753f04f3bSdan PRAGMA integrity_check; 48853f04f3bSdan } 48953f04f3bSdan} {4 ok} 490b2f20bfcSshaneh} 49153f04f3bSdan 492de4996e2Sdando_test pager1.4.3.1 { 493de4996e2Sdan testvfs tstvfs -default 1 494de4996e2Sdan tstvfs filter xSync 495de4996e2Sdan tstvfs script xSyncCallback 496de4996e2Sdan proc xSyncCallback {method file args} { 497de4996e2Sdan set file [file tail $file] 498de4996e2Sdan if { 0==[string match *journal $file] } { faultsim_save } 499de4996e2Sdan } 500de4996e2Sdan faultsim_delete_and_reopen 501de4996e2Sdan execsql { 502de4996e2Sdan PRAGMA journal_mode = DELETE; 503de4996e2Sdan CREATE TABLE t1(a, b); 504de4996e2Sdan INSERT INTO t1 VALUES(1, 2); 505de4996e2Sdan INSERT INTO t1 VALUES(3, 4); 506de4996e2Sdan } 507de4996e2Sdan db close 508de4996e2Sdan tstvfs delete 509de4996e2Sdan} {} 510de4996e2Sdan 511de4996e2Sdanforeach {tn ofst value result} { 512de4996e2Sdan 2 20 31 {1 2 3 4} 513de4996e2Sdan 3 20 32 {1 2 3 4} 514de4996e2Sdan 4 20 33 {1 2 3 4} 515de4996e2Sdan 5 20 65536 {1 2 3 4} 516de4996e2Sdan 6 20 131072 {1 2 3 4} 517de4996e2Sdan 518de4996e2Sdan 7 24 511 {1 2 3 4} 519de4996e2Sdan 8 24 513 {1 2 3 4} 520b2eced5dSdrh 9 24 131072 {1 2 3 4} 521de4996e2Sdan 522de4996e2Sdan 10 32 65536 {1 2} 523de4996e2Sdan} { 524de4996e2Sdan do_test pager1.4.3.$tn { 525de4996e2Sdan faultsim_restore_and_reopen 526de4996e2Sdan hexio_write test.db-journal $ofst [format %.8x $value] 527de4996e2Sdan execsql { SELECT * FROM t1 } 528de4996e2Sdan } $result 529de4996e2Sdan} 530de4996e2Sdandb close 531de4996e2Sdan 532e08341c6Sdan# Set up a VFS that snapshots the file-system just before a master journal 533e08341c6Sdan# file is deleted to commit a multi-file transaction. Specifically, the 534e08341c6Sdan# file-system is saved just before the xDelete() call to remove the 535e08341c6Sdan# master journal file from the file-system. 536e08341c6Sdan# 5376aa18c95Smistachkinset pwd [get_pwd] 538e08341c6Sdantestvfs tv -default 1 539e08341c6Sdantv script copy_on_mj_delete 540e08341c6Sdanset ::mj_filename_length 0 5418e6cf0a7Sdrhset ::mj_delete_cnt 0 542e08341c6Sdanproc copy_on_mj_delete {method filename args} { 543e08341c6Sdan if {[string match *mj* [file tail $filename]]} { 544c5484654Smistachkin # 545c5484654Smistachkin # NOTE: Is the file name relative? If so, add the length of the current 546c5484654Smistachkin # directory. 547c5484654Smistachkin # 548c5484654Smistachkin if {[is_relative_file $filename]} { 549c5484654Smistachkin set ::mj_filename_length \ 550c5484654Smistachkin [expr {[string length $filename] + [string length $::pwd]}] 551c5484654Smistachkin } else { 552e08341c6Sdan set ::mj_filename_length [string length $filename] 553c5484654Smistachkin } 554e08341c6Sdan faultsim_save 5558e6cf0a7Sdrh incr ::mj_delete_cnt 556e08341c6Sdan } 557e08341c6Sdan return SQLITE_OK 558e08341c6Sdan} 559e08341c6Sdan 560e08341c6Sdanforeach {tn1 tcl} { 561e08341c6Sdan 1 { set prefix "test.db" } 562e08341c6Sdan 2 { 563e08341c6Sdan # This test depends on the underlying VFS being able to open paths 564e08341c6Sdan # 512 bytes in length. The idea is to create a hot-journal file that 565e08341c6Sdan # contains a master-journal pointer so large that it could contain 566e08341c6Sdan # a valid page record (if the file page-size is 512 bytes). So as to 567e08341c6Sdan # make sure SQLite doesn't get confused by this. 568e08341c6Sdan # 569e08341c6Sdan set nPadding [expr 511 - $::mj_filename_length] 57033d85c9cSshaneh if {$tcl_platform(platform)=="windows"} { 57133d85c9cSshaneh # TBD need to figure out how to do this correctly for Windows!!! 57233d85c9cSshaneh set nPadding [expr 255 - $::mj_filename_length] 57333d85c9cSshaneh } 574e08341c6Sdan 575e08341c6Sdan # We cannot just create a really long database file name to open, as 576e08341c6Sdan # Linux limits a single component of a path to 255 bytes by default 577e08341c6Sdan # (and presumably other systems have limits too). So create a directory 578e08341c6Sdan # hierarchy to work in. 579e08341c6Sdan # 580e08341c6Sdan set dirname "d123456789012345678901234567890/" 581e08341c6Sdan set nDir [expr $nPadding / 32] 582e08341c6Sdan if { $nDir } { 583e08341c6Sdan set p [string repeat $dirname $nDir] 584e08341c6Sdan file mkdir $p 585e08341c6Sdan cd $p 586e08341c6Sdan } 587e08341c6Sdan 588e08341c6Sdan set padding [string repeat x [expr $nPadding %32]] 589e08341c6Sdan set prefix "test.db${padding}" 590e08341c6Sdan } 591e08341c6Sdan} { 592e08341c6Sdan eval $tcl 5938e6cf0a7Sdrh foreach {tn2 sql usesMJ} { 594e08341c6Sdan o { 595e08341c6Sdan PRAGMA main.synchronous=OFF; 596e08341c6Sdan PRAGMA aux.synchronous=OFF; 5973f94b609Sdan PRAGMA journal_mode = DELETE; 5988e6cf0a7Sdrh } 0 599e08341c6Sdan o512 { 600e08341c6Sdan PRAGMA main.synchronous=OFF; 601e08341c6Sdan PRAGMA aux.synchronous=OFF; 602e08341c6Sdan PRAGMA main.page_size = 512; 603e08341c6Sdan PRAGMA aux.page_size = 512; 6043f94b609Sdan PRAGMA journal_mode = DELETE; 6058e6cf0a7Sdrh } 0 606e08341c6Sdan n { 607e08341c6Sdan PRAGMA main.synchronous=NORMAL; 608e08341c6Sdan PRAGMA aux.synchronous=NORMAL; 6093f94b609Sdan PRAGMA journal_mode = DELETE; 6108e6cf0a7Sdrh } 1 611e08341c6Sdan f { 612e08341c6Sdan PRAGMA main.synchronous=FULL; 613e08341c6Sdan PRAGMA aux.synchronous=FULL; 6143f94b609Sdan PRAGMA journal_mode = DELETE; 6158e6cf0a7Sdrh } 1 6168e6cf0a7Sdrh w1 { 6178e6cf0a7Sdrh PRAGMA main.synchronous=NORMAL; 6188e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6198e6cf0a7Sdrh PRAGMA journal_mode = WAL; 6208e6cf0a7Sdrh } 0 6218e6cf0a7Sdrh w2 { 6228e6cf0a7Sdrh PRAGMA main.synchronous=NORMAL; 6238e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6248e6cf0a7Sdrh PRAGMA main.journal_mode=DELETE; 6258e6cf0a7Sdrh PRAGMA aux.journal_mode=WAL; 6268e6cf0a7Sdrh } 0 6278e6cf0a7Sdrh o1a { 6288e6cf0a7Sdrh PRAGMA main.synchronous=FULL; 6298e6cf0a7Sdrh PRAGMA aux.synchronous=OFF; 6308e6cf0a7Sdrh PRAGMA journal_mode=DELETE; 6318e6cf0a7Sdrh } 0 6328e6cf0a7Sdrh o1b { 6338e6cf0a7Sdrh PRAGMA main.synchronous=OFF; 6348e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6358e6cf0a7Sdrh PRAGMA journal_mode=DELETE; 6368e6cf0a7Sdrh } 0 6378e6cf0a7Sdrh m1 { 6388e6cf0a7Sdrh PRAGMA main.synchronous=NORMAL; 6398e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6408e6cf0a7Sdrh PRAGMA main.journal_mode=DELETE; 6418e6cf0a7Sdrh PRAGMA aux.journal_mode = MEMORY; 6428e6cf0a7Sdrh } 0 6438e6cf0a7Sdrh t1 { 6448e6cf0a7Sdrh PRAGMA main.synchronous=NORMAL; 6458e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6468e6cf0a7Sdrh PRAGMA main.journal_mode=DELETE; 6478e6cf0a7Sdrh PRAGMA aux.journal_mode = TRUNCATE; 6488e6cf0a7Sdrh } 1 6498e6cf0a7Sdrh p1 { 6508e6cf0a7Sdrh PRAGMA main.synchronous=NORMAL; 6518e6cf0a7Sdrh PRAGMA aux.synchronous=NORMAL; 6528e6cf0a7Sdrh PRAGMA main.journal_mode=DELETE; 6538e6cf0a7Sdrh PRAGMA aux.journal_mode = PERSIST; 6548e6cf0a7Sdrh } 1 655e08341c6Sdan } { 656e08341c6Sdan 657e08341c6Sdan set tn "${tn1}.${tn2}" 658e08341c6Sdan 659e08341c6Sdan # Set up a connection to have two databases, test.db (main) and 660e08341c6Sdan # test.db2 (aux). Then run a multi-file transaction on them. The 661e08341c6Sdan # VFS will snapshot the file-system just before the master-journal 662e08341c6Sdan # file is deleted to commit the transaction. 663e08341c6Sdan # 664e08341c6Sdan tv filter xDelete 665e08341c6Sdan do_test pager1-4.4.$tn.1 { 6668e6cf0a7Sdrh set ::mj_delete_cnt 0 667e08341c6Sdan faultsim_delete_and_reopen $prefix 668e08341c6Sdan execsql " 669e08341c6Sdan ATTACH '${prefix}2' AS aux; 670e08341c6Sdan $sql 671e08341c6Sdan CREATE TABLE a(x); 672e08341c6Sdan CREATE TABLE aux.b(x); 673e08341c6Sdan INSERT INTO a VALUES('double-you'); 674e08341c6Sdan INSERT INTO a VALUES('why'); 675e08341c6Sdan INSERT INTO a VALUES('zed'); 676e08341c6Sdan INSERT INTO b VALUES('won'); 677e08341c6Sdan INSERT INTO b VALUES('too'); 678e08341c6Sdan INSERT INTO b VALUES('free'); 679e08341c6Sdan " 680e08341c6Sdan execsql { 681e08341c6Sdan BEGIN; 682e08341c6Sdan INSERT INTO a SELECT * FROM b WHERE rowid<=3; 683e08341c6Sdan INSERT INTO b SELECT * FROM a WHERE rowid<=3; 684e08341c6Sdan COMMIT; 685e08341c6Sdan } 686e08341c6Sdan } {} 687e08341c6Sdan tv filter {} 688e08341c6Sdan 6898e6cf0a7Sdrh # Verify that a master journal was deleted only for those cases where 6908e6cf0a7Sdrh # master journals really ought to be used 6918e6cf0a7Sdrh # 6928e6cf0a7Sdrh do_test pager1-4.4.$tn.1b { 6938e6cf0a7Sdrh set ::mj_delete_cnt 6948e6cf0a7Sdrh } $usesMJ 6958e6cf0a7Sdrh 696e08341c6Sdan # Check that the transaction was committed successfully. 697e08341c6Sdan # 698e08341c6Sdan do_execsql_test pager1-4.4.$tn.2 { 699e08341c6Sdan SELECT * FROM a 700e08341c6Sdan } {double-you why zed won too free} 701e08341c6Sdan do_execsql_test pager1-4.4.$tn.3 { 702e08341c6Sdan SELECT * FROM b 703e08341c6Sdan } {won too free double-you why zed} 704e08341c6Sdan 7058e6cf0a7Sdrh if {$usesMJ} { 706e08341c6Sdan # Restore the file-system and reopen the databases. Check that it now 707e08341c6Sdan # appears that the transaction was not committed (because the file-system 708e08341c6Sdan # was restored to the state where it had not been). 709e08341c6Sdan # 710e08341c6Sdan do_test pager1-4.4.$tn.4 { 711e08341c6Sdan faultsim_restore_and_reopen $prefix 712e08341c6Sdan execsql "ATTACH '${prefix}2' AS aux" 713e08341c6Sdan } {} 714e08341c6Sdan do_execsql_test pager1-4.4.$tn.5 {SELECT * FROM a} {double-you why zed} 715e08341c6Sdan do_execsql_test pager1-4.4.$tn.6 {SELECT * FROM b} {won too free} 7168e6cf0a7Sdrh } 717e08341c6Sdan 718e08341c6Sdan # Restore the file-system again. This time, before reopening the databases, 719e08341c6Sdan # delete the master-journal file from the file-system. It now appears that 720e08341c6Sdan # the transaction was committed (no master-journal file == no rollback). 721e08341c6Sdan # 722e08341c6Sdan do_test pager1-4.4.$tn.7 { 7238e6cf0a7Sdrh if {$::mj_delete_cnt>0} { 724e08341c6Sdan faultsim_restore_and_reopen $prefix 725fda06befSmistachkin foreach f [glob ${prefix}-mj*] { forcedelete $f } 7268e6cf0a7Sdrh } else { 7278e6cf0a7Sdrh db close 7288e6cf0a7Sdrh sqlite3 db $prefix 7298e6cf0a7Sdrh } 730e08341c6Sdan execsql "ATTACH '${prefix}2' AS aux" 7318e6cf0a7Sdrh glob -nocomplain ${prefix}-mj* 732e08341c6Sdan } {} 733e08341c6Sdan do_execsql_test pager1-4.4.$tn.8 { 734e08341c6Sdan SELECT * FROM a 735e08341c6Sdan } {double-you why zed won too free} 736e08341c6Sdan do_execsql_test pager1-4.4.$tn.9 { 737e08341c6Sdan SELECT * FROM b 738e08341c6Sdan } {won too free double-you why zed} 739e08341c6Sdan } 740e08341c6Sdan 741e08341c6Sdan cd $pwd 742e08341c6Sdan} 743e08341c6Sdandb close 744e08341c6Sdantv delete 745fda06befSmistachkinforcedelete $dirname 7460e986f51Sdan 7470e986f51Sdan# Set up a VFS to make a copy of the file-system just before deleting a 7480e986f51Sdan# journal file to commit a transaction. The transaction modifies exactly 7490e986f51Sdan# two database pages (and page 1 - the change counter). 7500e986f51Sdan# 7510e986f51Sdantestvfs tv -default 1 7520e986f51Sdantv sectorsize 512 7530e986f51Sdantv script copy_on_journal_delete 7540e986f51Sdantv filter xDelete 7550e986f51Sdanproc copy_on_journal_delete {method filename args} { 7560e986f51Sdan if {[string match *journal $filename]} faultsim_save 7570e986f51Sdan return SQLITE_OK 7580e986f51Sdan} 7590e986f51Sdanfaultsim_delete_and_reopen 7600e986f51Sdando_execsql_test pager1.4.5.1 { 7613f94b609Sdan PRAGMA journal_mode = DELETE; 7620e986f51Sdan PRAGMA page_size = 1024; 7630e986f51Sdan CREATE TABLE t1(a, b); 7640e986f51Sdan CREATE TABLE t2(a, b); 7650e986f51Sdan INSERT INTO t1 VALUES('I', 'II'); 7660e986f51Sdan INSERT INTO t2 VALUES('III', 'IV'); 7670e986f51Sdan BEGIN; 7680e986f51Sdan INSERT INTO t1 VALUES(1, 2); 7690e986f51Sdan INSERT INTO t2 VALUES(3, 4); 7700e986f51Sdan COMMIT; 7713f94b609Sdan} {delete} 7720e986f51Sdantv filter {} 7730e986f51Sdan 7740e986f51Sdan# Check the transaction was committed: 7750e986f51Sdan# 7760e986f51Sdando_execsql_test pager1.4.5.2 { 7770e986f51Sdan SELECT * FROM t1; 7780e986f51Sdan SELECT * FROM t2; 7790e986f51Sdan} {I II 1 2 III IV 3 4} 7800e986f51Sdan 781ec6ffc1aSdan# Now try four tests: 7820e986f51Sdan# 7830e986f51Sdan# pager1-4.5.3: Restore the file-system. Check that the whole transaction 7840e986f51Sdan# is rolled back. 7850e986f51Sdan# 7860e986f51Sdan# pager1-4.5.4: Restore the file-system. Corrupt the first record in the 7870e986f51Sdan# journal. Check the transaction is not rolled back. 7880e986f51Sdan# 7890e986f51Sdan# pager1-4.5.5: Restore the file-system. Corrupt the second record in the 7900e986f51Sdan# journal. Check that the first record in the transaction is 7910e986f51Sdan# played back, but not the second. 7920e986f51Sdan# 79310f5a50eSdan# pager1-4.5.6: Restore the file-system. Try to open the database with a 79410f5a50eSdan# readonly connection. This should fail, as a read-only 79510f5a50eSdan# connection cannot roll back the database file. 79610f5a50eSdan# 7970e986f51Sdanfaultsim_restore_and_reopen 7980e986f51Sdando_execsql_test pager1.4.5.3 { 7990e986f51Sdan SELECT * FROM t1; 8000e986f51Sdan SELECT * FROM t2; 8010e986f51Sdan} {I II III IV} 8020e986f51Sdanfaultsim_restore_and_reopen 8030e986f51Sdanhexio_write test.db-journal [expr 512+4+1024 - 202] 0123456789ABCDEF 8040e986f51Sdando_execsql_test pager1.4.5.4 { 8050e986f51Sdan SELECT * FROM t1; 8060e986f51Sdan SELECT * FROM t2; 8070e986f51Sdan} {I II 1 2 III IV 3 4} 8080e986f51Sdanfaultsim_restore_and_reopen 8090e986f51Sdanhexio_write test.db-journal [expr 512+4+1024+4+4+1024 - 202] 0123456789ABCDEF 8100e986f51Sdando_execsql_test pager1.4.5.5 { 8110e986f51Sdan SELECT * FROM t1; 8120e986f51Sdan SELECT * FROM t2; 8130e986f51Sdan} {I II III IV 3 4} 8140e986f51Sdan 81510f5a50eSdanfaultsim_restore_and_reopen 81610f5a50eSdandb close 81710f5a50eSdansqlite3 db test.db -readonly 1 81810f5a50eSdando_catchsql_test pager1.4.5.6 { 81910f5a50eSdan SELECT * FROM t1; 82010f5a50eSdan SELECT * FROM t2; 821b83c21e6Sdan} {1 {attempt to write a readonly database}} 822ec6ffc1aSdandb close 823ec6ffc1aSdan 824ec6ffc1aSdan# Snapshot the file-system just before multi-file commit. Save the name 825ec6ffc1aSdan# of the master journal file in $::mj_filename. 826ec6ffc1aSdan# 827ec6ffc1aSdantv script copy_on_mj_delete 828ec6ffc1aSdantv filter xDelete 829ec6ffc1aSdanproc copy_on_mj_delete {method filename args} { 830ec6ffc1aSdan if {[string match *mj* [file tail $filename]]} { 831ec6ffc1aSdan set ::mj_filename $filename 832ec6ffc1aSdan faultsim_save 833ec6ffc1aSdan } 834ec6ffc1aSdan return SQLITE_OK 835ec6ffc1aSdan} 836ec6ffc1aSdando_test pager1.4.6.1 { 837ec6ffc1aSdan faultsim_delete_and_reopen 838ec6ffc1aSdan execsql { 8393f94b609Sdan PRAGMA journal_mode = DELETE; 840ec6ffc1aSdan ATTACH 'test.db2' AS two; 841ec6ffc1aSdan CREATE TABLE t1(a, b); 842ec6ffc1aSdan CREATE TABLE two.t2(a, b); 843ec6ffc1aSdan INSERT INTO t1 VALUES(1, 't1.1'); 844ec6ffc1aSdan INSERT INTO t2 VALUES(1, 't2.1'); 845ec6ffc1aSdan BEGIN; 846ec6ffc1aSdan UPDATE t1 SET b = 't1.2'; 847ec6ffc1aSdan UPDATE t2 SET b = 't2.2'; 848ec6ffc1aSdan COMMIT; 849ec6ffc1aSdan } 850ec6ffc1aSdan tv filter {} 851ec6ffc1aSdan db close 852ec6ffc1aSdan} {} 853ec6ffc1aSdan 854ec6ffc1aSdanfaultsim_restore_and_reopen 855ec6ffc1aSdando_execsql_test pager1.4.6.2 { SELECT * FROM t1 } {1 t1.1} 856ec6ffc1aSdando_test pager1.4.6.3 { file exists $::mj_filename } {1} 857ec6ffc1aSdando_execsql_test pager1.4.6.4 { 858ec6ffc1aSdan ATTACH 'test.db2' AS two; 859ec6ffc1aSdan SELECT * FROM t2; 860ec6ffc1aSdan} {1 t2.1} 861ec6ffc1aSdando_test pager1.4.6.5 { file exists $::mj_filename } {0} 862ec6ffc1aSdan 863ec6ffc1aSdanfaultsim_restore_and_reopen 864ec6ffc1aSdandb close 865ec6ffc1aSdando_test pager1.4.6.8 { 866ec6ffc1aSdan set ::mj_filename1 $::mj_filename 867ec6ffc1aSdan tv filter xDelete 868ec6ffc1aSdan sqlite3 db test.db2 869ec6ffc1aSdan execsql { 8703f94b609Sdan PRAGMA journal_mode = DELETE; 871ec6ffc1aSdan ATTACH 'test.db3' AS three; 872ec6ffc1aSdan CREATE TABLE three.t3(a, b); 873ec6ffc1aSdan INSERT INTO t3 VALUES(1, 't3.1'); 874ec6ffc1aSdan BEGIN; 875ec6ffc1aSdan UPDATE t2 SET b = 't2.3'; 876ec6ffc1aSdan UPDATE t3 SET b = 't3.3'; 877ec6ffc1aSdan COMMIT; 878ec6ffc1aSdan } 879ec6ffc1aSdan expr {$::mj_filename1 != $::mj_filename} 880ec6ffc1aSdan} {1} 881ec6ffc1aSdanfaultsim_restore_and_reopen 882ec6ffc1aSdantv filter {} 883ec6ffc1aSdan 884ec6ffc1aSdan# The file-system now contains: 885ec6ffc1aSdan# 886ec6ffc1aSdan# * three databases 887ec6ffc1aSdan# * three hot-journal files 888ec6ffc1aSdan# * two master-journal files. 889ec6ffc1aSdan# 890ec6ffc1aSdan# The hot-journals associated with test.db2 and test.db3 point to 891ec6ffc1aSdan# master journal $::mj_filename. The hot-journal file associated with 892ec6ffc1aSdan# test.db points to master journal $::mj_filename1. So reading from 893ec6ffc1aSdan# test.db should delete $::mj_filename1. 894ec6ffc1aSdan# 895ec6ffc1aSdando_test pager1.4.6.9 { 896ec6ffc1aSdan lsort [glob test.db*] 897ec6ffc1aSdan} [lsort [list \ 898ec6ffc1aSdan test.db test.db2 test.db3 \ 899ec6ffc1aSdan test.db-journal test.db2-journal test.db3-journal \ 900ec6ffc1aSdan [file tail $::mj_filename] [file tail $::mj_filename1] 901ec6ffc1aSdan]] 902ec6ffc1aSdan 903ec6ffc1aSdan# The master-journal $::mj_filename1 contains pointers to test.db and 904ec6ffc1aSdan# test.db2. However the hot-journal associated with test.db2 points to 905ec6ffc1aSdan# a different master-journal. Therefore, reading from test.db only should 906ec6ffc1aSdan# be enough to cause SQLite to delete $::mj_filename1. 907ec6ffc1aSdan# 908ec6ffc1aSdando_test pager1.4.6.10 { file exists $::mj_filename } {1} 909ec6ffc1aSdando_test pager1.4.6.11 { file exists $::mj_filename1 } {1} 910ec6ffc1aSdando_execsql_test pager1.4.6.12 { SELECT * FROM t1 } {1 t1.1} 911ec6ffc1aSdando_test pager1.4.6.13 { file exists $::mj_filename } {1} 912ec6ffc1aSdando_test pager1.4.6.14 { file exists $::mj_filename1 } {0} 913ec6ffc1aSdan 914ec6ffc1aSdando_execsql_test pager1.4.6.12 { 915ec6ffc1aSdan ATTACH 'test.db2' AS two; 916ec6ffc1aSdan SELECT * FROM t2; 917ec6ffc1aSdan} {1 t2.1} 918ec6ffc1aSdando_test pager1.4.6.13 { file exists $::mj_filename } {1} 919ec6ffc1aSdando_execsql_test pager1.4.6.14 { 920ec6ffc1aSdan ATTACH 'test.db3' AS three; 921ec6ffc1aSdan SELECT * FROM t3; 922ec6ffc1aSdan} {1 t3.1} 923ec6ffc1aSdando_test pager1.4.6.15 { file exists $::mj_filename } {0} 92410f5a50eSdan 9250e986f51Sdandb close 9260e986f51Sdantv delete 927e08341c6Sdan 928c8ce3972Sdantestvfs tv -default 1 929c8ce3972Sdantv sectorsize 512 930c8ce3972Sdantv script copy_on_journal_delete 931c8ce3972Sdantv filter xDelete 932c8ce3972Sdanproc copy_on_journal_delete {method filename args} { 933c8ce3972Sdan if {[string match *journal $filename]} faultsim_save 934c8ce3972Sdan return SQLITE_OK 935c8ce3972Sdan} 936c8ce3972Sdanfaultsim_delete_and_reopen 937c8ce3972Sdando_execsql_test pager1.4.7.1 { 9383f94b609Sdan PRAGMA journal_mode = DELETE; 939c8ce3972Sdan CREATE TABLE t1(x PRIMARY KEY, y); 940c8ce3972Sdan CREATE INDEX i1 ON t1(y); 941c8ce3972Sdan INSERT INTO t1 VALUES('I', 'one'); 942c8ce3972Sdan INSERT INTO t1 VALUES('II', 'four'); 943c8ce3972Sdan INSERT INTO t1 VALUES('III', 'nine'); 944c8ce3972Sdan BEGIN; 945c8ce3972Sdan INSERT INTO t1 VALUES('IV', 'sixteen'); 946c8ce3972Sdan INSERT INTO t1 VALUES('V' , 'twentyfive'); 947c8ce3972Sdan COMMIT; 9483f94b609Sdan} {delete} 949c8ce3972Sdantv filter {} 950c8ce3972Sdandb close 951c8ce3972Sdantv delete 952e1186ab2Sdrhcatch { 953e1186ab2Sdrh test_syscall install fchmod 954e1186ab2Sdrh test_syscall fault 1 1 955e1186ab2Sdrh} 956c8ce3972Sdando_test pager1.4.7.2 { 957c8ce3972Sdan faultsim_restore_and_reopen 958c8ce3972Sdan catch {file attributes test.db-journal -permissions r--------} 959c8ce3972Sdan catch {file attributes test.db-journal -readonly 1} 960c8ce3972Sdan catchsql { SELECT * FROM t1 } 961c8ce3972Sdan} {1 {unable to open database file}} 962e1186ab2Sdrhcatch { 963e1186ab2Sdrh test_syscall reset 964e1186ab2Sdrh test_syscall fault 0 0 965e1186ab2Sdrh} 966c8ce3972Sdando_test pager1.4.7.3 { 967c8ce3972Sdan db close 968c8ce3972Sdan catch {file attributes test.db-journal -permissions rw-rw-rw-} 969c8ce3972Sdan catch {file attributes test.db-journal -readonly 0} 970fda06befSmistachkin delete_file test.db-journal 971c8ce3972Sdan file exists test.db-journal 972c8ce3972Sdan} {0} 973421377e6Sdrhdo_test pager1.4.8.1 { 974421377e6Sdrh catch {file attributes test.db -permissions r--------} 975421377e6Sdrh catch {file attributes test.db -readonly 1} 976421377e6Sdrh sqlite3 db test.db 977421377e6Sdrh db eval { SELECT * FROM t1 } 978421377e6Sdrh sqlite3_db_readonly db main 979421377e6Sdrh} {1} 980421377e6Sdrhdo_test pager1.4.8.2 { 981421377e6Sdrh sqlite3_db_readonly db xyz 982421377e6Sdrh} {-1} 983421377e6Sdrhdo_test pager1.4.8.3 { 984421377e6Sdrh db close 985421377e6Sdrh catch {file attributes test.db -readonly 0} 986db0ad5f2Sdan catch {file attributes test.db -permissions rw-rw-rw-} msg 987421377e6Sdrh sqlite3 db test.db 988421377e6Sdrh db eval { SELECT * FROM t1 } 989421377e6Sdrh sqlite3_db_readonly db main 990421377e6Sdrh} {0} 991c8ce3972Sdan 992de4996e2Sdan#------------------------------------------------------------------------- 993146ed78bSdan# The following tests deal with multi-file commits. 994de4996e2Sdan# 995146ed78bSdan# pager1-5.1.*: The case where a multi-file cannot be committed because 996146ed78bSdan# another connection is holding a SHARED lock on one of the 997146ed78bSdan# files. After the SHARED lock is removed, the COMMIT succeeds. 998146ed78bSdan# 999146ed78bSdan# pager1-5.2.*: Multi-file commits with journal_mode=memory. 1000146ed78bSdan# 1001146ed78bSdan# pager1-5.3.*: Multi-file commits with journal_mode=memory. 1002146ed78bSdan# 1003146ed78bSdan# pager1-5.4.*: Check that with synchronous=normal, the master-journal file 1004146ed78bSdan# name is added to a journal file immediately after the last 1005146ed78bSdan# journal record. But with synchronous=full, extra unused space 1006146ed78bSdan# is allocated between the last journal record and the 1007146ed78bSdan# master-journal file name so that the master-journal file 1008146ed78bSdan# name does not lie on the same sector as the last journal file 1009146ed78bSdan# record. 1010146ed78bSdan# 1011e08341c6Sdan# pager1-5.5.*: Check that in journal_mode=PERSIST mode, a journal file is 1012e08341c6Sdan# truncated to zero bytes when a multi-file transaction is 1013e08341c6Sdan# committed (instead of the first couple of bytes being zeroed). 1014e08341c6Sdan# 1015146ed78bSdan# 1016146ed78bSdando_test pager1-5.1.1 { 1017146ed78bSdan faultsim_delete_and_reopen 1018146ed78bSdan execsql { 1019146ed78bSdan ATTACH 'test.db2' AS aux; 1020146ed78bSdan CREATE TABLE t1(a, b); 1021146ed78bSdan CREATE TABLE aux.t2(a, b); 1022146ed78bSdan INSERT INTO t1 VALUES(17, 'Lenin'); 1023146ed78bSdan INSERT INTO t1 VALUES(22, 'Stalin'); 1024146ed78bSdan INSERT INTO t1 VALUES(53, 'Khrushchev'); 1025146ed78bSdan } 1026146ed78bSdan} {} 1027146ed78bSdando_test pager1-5.1.2 { 1028146ed78bSdan execsql { 1029146ed78bSdan BEGIN; 1030146ed78bSdan INSERT INTO t1 VALUES(64, 'Brezhnev'); 1031146ed78bSdan INSERT INTO t2 SELECT * FROM t1; 1032146ed78bSdan } 1033146ed78bSdan sqlite3 db2 test.db2 1034146ed78bSdan execsql { 1035146ed78bSdan BEGIN; 1036146ed78bSdan SELECT * FROM t2; 1037146ed78bSdan } db2 1038146ed78bSdan} {} 1039146ed78bSdando_test pager1-5.1.3 { 1040146ed78bSdan catchsql COMMIT 1041146ed78bSdan} {1 {database is locked}} 1042146ed78bSdando_test pager1-5.1.4 { 1043146ed78bSdan execsql COMMIT db2 1044146ed78bSdan execsql COMMIT 1045146ed78bSdan execsql { SELECT * FROM t2 } db2 1046146ed78bSdan} {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev} 1047146ed78bSdando_test pager1-5.1.5 { 1048146ed78bSdan db2 close 1049146ed78bSdan} {} 1050146ed78bSdan 1051146ed78bSdando_test pager1-5.2.1 { 1052146ed78bSdan execsql { 1053146ed78bSdan PRAGMA journal_mode = memory; 1054146ed78bSdan BEGIN; 1055146ed78bSdan INSERT INTO t1 VALUES(84, 'Andropov'); 1056146ed78bSdan INSERT INTO t2 VALUES(84, 'Andropov'); 1057146ed78bSdan COMMIT; 1058146ed78bSdan } 1059146ed78bSdan} {memory} 1060146ed78bSdando_test pager1-5.3.1 { 1061146ed78bSdan execsql { 1062146ed78bSdan PRAGMA journal_mode = off; 1063146ed78bSdan BEGIN; 1064146ed78bSdan INSERT INTO t1 VALUES(85, 'Gorbachev'); 1065146ed78bSdan INSERT INTO t2 VALUES(85, 'Gorbachev'); 1066146ed78bSdan COMMIT; 1067146ed78bSdan } 1068146ed78bSdan} {off} 1069146ed78bSdan 1070146ed78bSdando_test pager1-5.4.1 { 1071146ed78bSdan db close 1072146ed78bSdan testvfs tv 1073146ed78bSdan sqlite3 db test.db -vfs tv 1074146ed78bSdan execsql { ATTACH 'test.db2' AS aux } 1075146ed78bSdan 1076146ed78bSdan tv filter xDelete 1077146ed78bSdan tv script max_journal_size 1078146ed78bSdan tv sectorsize 512 1079146ed78bSdan set ::max_journal 0 1080146ed78bSdan proc max_journal_size {method args} { 1081146ed78bSdan set sz 0 1082146ed78bSdan catch { set sz [file size test.db-journal] } 1083146ed78bSdan if {$sz > $::max_journal} { 1084146ed78bSdan set ::max_journal $sz 1085146ed78bSdan } 1086146ed78bSdan return SQLITE_OK 1087146ed78bSdan } 1088146ed78bSdan execsql { 1089146ed78bSdan PRAGMA journal_mode = DELETE; 1090146ed78bSdan PRAGMA synchronous = NORMAL; 1091146ed78bSdan BEGIN; 1092146ed78bSdan INSERT INTO t1 VALUES(85, 'Gorbachev'); 1093146ed78bSdan INSERT INTO t2 VALUES(85, 'Gorbachev'); 1094146ed78bSdan COMMIT; 1095146ed78bSdan } 10967f9026ddSdan 10977f9026ddSdan # The size of the journal file is now: 10987f9026ddSdan # 10997f9026ddSdan # 1) 512 byte header + 11007f9026ddSdan # 2) 2 * (1024+8) byte records + 11017f9026ddSdan # 3) 20+N bytes of master-journal pointer, where N is the size of 11027f9026ddSdan # the master-journal name encoded as utf-8 with no nul term. 11037f9026ddSdan # 11047f9026ddSdan set mj_pointer [expr { 1105c5484654Smistachkin 20 + [string length "test.db-mjXXXXXX9XX"] 11067f9026ddSdan }] 1107c5484654Smistachkin # 1108c5484654Smistachkin # NOTE: For item 3 above, if the current SQLite VFS lacks the concept of a 1109c5484654Smistachkin # current directory, the length of the current directory name plus 1 1110c5484654Smistachkin # character for the directory separator character are NOT counted as 1111c5484654Smistachkin # part of the total size; otherwise, they are. 1112c5484654Smistachkin # 1113c5484654Smistachkin ifcapable curdir { 11146aa18c95Smistachkin set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}] 1115c5484654Smistachkin } 11167f9026ddSdan expr {$::max_journal==(512+2*(1024+8)+$mj_pointer)} 11177f9026ddSdan} 1 1118146ed78bSdando_test pager1-5.4.2 { 1119146ed78bSdan set ::max_journal 0 1120146ed78bSdan execsql { 1121146ed78bSdan PRAGMA synchronous = full; 1122146ed78bSdan BEGIN; 1123146ed78bSdan DELETE FROM t1 WHERE b = 'Lenin'; 1124146ed78bSdan DELETE FROM t2 WHERE b = 'Lenin'; 1125146ed78bSdan COMMIT; 1126146ed78bSdan } 11277f9026ddSdan 11287f9026ddSdan # In synchronous=full mode, the master-journal pointer is not written 11297f9026ddSdan # directly after the last record in the journal file. Instead, it is 11307f9026ddSdan # written starting at the next (in this case 512 byte) sector boundary. 11317f9026ddSdan # 11327f9026ddSdan set mj_pointer [expr { 1133c5484654Smistachkin 20 + [string length "test.db-mjXXXXXX9XX"] 11347f9026ddSdan }] 1135c5484654Smistachkin # 1136c5484654Smistachkin # NOTE: If the current SQLite VFS lacks the concept of a current directory, 1137c5484654Smistachkin # the length of the current directory name plus 1 character for the 1138c5484654Smistachkin # directory separator character are NOT counted as part of the total 1139c5484654Smistachkin # size; otherwise, they are. 1140c5484654Smistachkin # 1141c5484654Smistachkin ifcapable curdir { 11426aa18c95Smistachkin set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}] 1143c5484654Smistachkin } 11447f9026ddSdan expr {$::max_journal==(((512+2*(1024+8)+511)/512)*512 + $mj_pointer)} 11457f9026ddSdan} 1 1146146ed78bSdandb close 1147146ed78bSdantv delete 1148146ed78bSdan 1149146ed78bSdando_test pager1-5.5.1 { 1150146ed78bSdan sqlite3 db test.db 1151146ed78bSdan execsql { 1152146ed78bSdan ATTACH 'test.db2' AS aux; 1153146ed78bSdan PRAGMA journal_mode = PERSIST; 1154146ed78bSdan CREATE TABLE t3(a, b); 1155146ed78bSdan INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1; 1156d5aa9262Sdrh UPDATE t3 SET b = randomblob(1501); 1157146ed78bSdan } 1158146ed78bSdan expr [file size test.db-journal] > 15000 1159146ed78bSdan} {1} 1160146ed78bSdando_test pager1-5.5.2 { 1161146ed78bSdan execsql { 1162146ed78bSdan PRAGMA synchronous = full; 1163146ed78bSdan BEGIN; 1164146ed78bSdan DELETE FROM t1 WHERE b = 'Stalin'; 1165146ed78bSdan DELETE FROM t2 WHERE b = 'Stalin'; 1166146ed78bSdan COMMIT; 1167146ed78bSdan } 1168146ed78bSdan file size test.db-journal 1169146ed78bSdan} {0} 1170146ed78bSdan 1171146ed78bSdan 1172146ed78bSdan#------------------------------------------------------------------------- 1173146ed78bSdan# The following tests work with "PRAGMA max_page_count" 1174146ed78bSdan# 1175146ed78bSdando_test pager1-6.1 { 1176146ed78bSdan faultsim_delete_and_reopen 1177146ed78bSdan execsql { 1178f43d7fceSdan PRAGMA auto_vacuum = none; 1179146ed78bSdan PRAGMA max_page_count = 10; 1180146ed78bSdan CREATE TABLE t2(a, b); 1181146ed78bSdan CREATE TABLE t3(a, b); 1182146ed78bSdan CREATE TABLE t4(a, b); 1183146ed78bSdan CREATE TABLE t5(a, b); 1184146ed78bSdan CREATE TABLE t6(a, b); 1185146ed78bSdan CREATE TABLE t7(a, b); 1186146ed78bSdan CREATE TABLE t8(a, b); 1187146ed78bSdan CREATE TABLE t9(a, b); 1188146ed78bSdan CREATE TABLE t10(a, b); 1189146ed78bSdan } 1190146ed78bSdan} {10} 1191d353331aSdando_catchsql_test pager1-6.2 { 1192d353331aSdan CREATE TABLE t11(a, b) 1193146ed78bSdan} {1 {database or disk is full}} 1194d353331aSdando_execsql_test pager1-6.4 { PRAGMA max_page_count } {10} 1195d353331aSdando_execsql_test pager1-6.5 { PRAGMA max_page_count = 15 } {15} 1196d353331aSdando_execsql_test pager1-6.6 { CREATE TABLE t11(a, b) } {} 1197d353331aSdando_execsql_test pager1-6.7 { 1198d353331aSdan BEGIN; 1199d353331aSdan INSERT INTO t11 VALUES(1, 2); 1200d353331aSdan PRAGMA max_page_count = 13; 1201d353331aSdan} {13} 1202d353331aSdando_execsql_test pager1-6.8 { 1203d353331aSdan INSERT INTO t11 VALUES(3, 4); 1204d353331aSdan PRAGMA max_page_count = 10; 1205d353331aSdan} {11} 1206d353331aSdando_execsql_test pager1-6.9 { COMMIT } {} 1207de4996e2Sdan 120860ac3f42Sdrhdo_execsql_test pager1-6.10 { PRAGMA max_page_count = 10 } {11} 120922b328b2Sdando_execsql_test pager1-6.11 { SELECT * FROM t11 } {1 2 3 4} 121022b328b2Sdando_execsql_test pager1-6.12 { PRAGMA max_page_count } {11} 121122b328b2Sdan 1212153eda0aSdan 1213153eda0aSdan#------------------------------------------------------------------------- 1214153eda0aSdan# The following tests work with "PRAGMA journal_mode=TRUNCATE" and 1215153eda0aSdan# "PRAGMA locking_mode=EXCLUSIVE". 1216153eda0aSdan# 1217153eda0aSdan# Each test is specified with 5 variables. As follows: 1218153eda0aSdan# 1219153eda0aSdan# $tn: Test Number. Used as part of the [do_test] test names. 1220153eda0aSdan# $sql: SQL to execute. 1221153eda0aSdan# $res: Expected result of executing $sql. 1222153eda0aSdan# $js: The expected size of the journal file, in bytes, after executing 1223153eda0aSdan# the SQL script. Or -1 if the journal is not expected to exist. 1224153eda0aSdan# $ws: The expected size of the WAL file, in bytes, after executing 1225153eda0aSdan# the SQL script. Or -1 if the WAL is not expected to exist. 1226153eda0aSdan# 122738e1a279Sdanifcapable wal { 1228153eda0aSdan faultsim_delete_and_reopen 1229153eda0aSdan foreach {tn sql res js ws} [subst { 1230153eda0aSdan 1231153eda0aSdan 1 { 1232153eda0aSdan CREATE TABLE t1(a, b); 1233153eda0aSdan PRAGMA auto_vacuum=OFF; 1234153eda0aSdan PRAGMA synchronous=NORMAL; 1235153eda0aSdan PRAGMA page_size=1024; 1236153eda0aSdan PRAGMA locking_mode=EXCLUSIVE; 1237153eda0aSdan PRAGMA journal_mode=TRUNCATE; 1238153eda0aSdan INSERT INTO t1 VALUES(1, 2); 1239153eda0aSdan } {exclusive truncate} 0 -1 1240153eda0aSdan 1241153eda0aSdan 2 { 1242153eda0aSdan BEGIN IMMEDIATE; 1243153eda0aSdan SELECT * FROM t1; 1244153eda0aSdan COMMIT; 1245153eda0aSdan } {1 2} 0 -1 1246153eda0aSdan 1247153eda0aSdan 3 { 1248153eda0aSdan BEGIN; 1249153eda0aSdan SELECT * FROM t1; 1250153eda0aSdan COMMIT; 1251153eda0aSdan } {1 2} 0 -1 1252153eda0aSdan 1253153eda0aSdan 4 { PRAGMA journal_mode = WAL } wal -1 -1 1254153eda0aSdan 5 { INSERT INTO t1 VALUES(3, 4) } {} -1 [wal_file_size 1 1024] 12558c408004Sdan 6 { PRAGMA locking_mode = NORMAL } exclusive -1 [wal_file_size 1 1024] 1256153eda0aSdan 7 { INSERT INTO t1 VALUES(5, 6); } {} -1 [wal_file_size 2 1024] 1257153eda0aSdan 1258153eda0aSdan 8 { PRAGMA journal_mode = TRUNCATE } truncate 0 -1 1259153eda0aSdan 9 { INSERT INTO t1 VALUES(7, 8) } {} 0 -1 1260153eda0aSdan 10 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8} 0 -1 1261153eda0aSdan 1262153eda0aSdan }] { 1263153eda0aSdan do_execsql_test pager1-7.1.$tn.1 $sql $res 1264153eda0aSdan catch { set J -1 ; set J [file size test.db-journal] } 1265153eda0aSdan catch { set W -1 ; set W [file size test.db-wal] } 1266153eda0aSdan do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws] 1267153eda0aSdan } 126838e1a279Sdan} 1269153eda0aSdan 127089ccf448Sdando_test pager1-7.2.1 { 127189ccf448Sdan faultsim_delete_and_reopen 127289ccf448Sdan execsql { 127389ccf448Sdan PRAGMA locking_mode = EXCLUSIVE; 127489ccf448Sdan CREATE TABLE t1(a, b); 127589ccf448Sdan BEGIN; 127689ccf448Sdan PRAGMA journal_mode = delete; 127789ccf448Sdan PRAGMA journal_mode = truncate; 127889ccf448Sdan } 127989ccf448Sdan} {exclusive delete truncate} 128089ccf448Sdando_test pager1-7.2.2 { 128189ccf448Sdan execsql { INSERT INTO t1 VALUES(1, 2) } 128289ccf448Sdan execsql { PRAGMA journal_mode = persist } 128389ccf448Sdan} {truncate} 128489ccf448Sdando_test pager1-7.2.3 { 128589ccf448Sdan execsql { COMMIT } 128689ccf448Sdan execsql { 128789ccf448Sdan PRAGMA journal_mode = persist; 128889ccf448Sdan PRAGMA journal_size_limit; 128989ccf448Sdan } 129089ccf448Sdan} {persist -1} 129189ccf448Sdan 1292d353331aSdan#------------------------------------------------------------------------- 1293d353331aSdan# The following tests, pager1-8.*, test that the special filenames 1294d353331aSdan# ":memory:" and "" open temporary databases. 1295d353331aSdan# 12960e986f51Sdanforeach {tn filename} { 12970e986f51Sdan 1 :memory: 12980e986f51Sdan 2 "" 12990e986f51Sdan} { 13000e986f51Sdan do_test pager1-8.$tn.1 { 1301153eda0aSdan faultsim_delete_and_reopen 1302153eda0aSdan db close 13030e986f51Sdan sqlite3 db $filename 1304153eda0aSdan execsql { 1305c8ce3972Sdan PRAGMA auto_vacuum = 1; 1306153eda0aSdan CREATE TABLE x1(x); 1307153eda0aSdan INSERT INTO x1 VALUES('Charles'); 1308153eda0aSdan INSERT INTO x1 VALUES('James'); 1309153eda0aSdan INSERT INTO x1 VALUES('Mary'); 1310153eda0aSdan SELECT * FROM x1; 1311153eda0aSdan } 1312153eda0aSdan } {Charles James Mary} 13130e986f51Sdan 13140e986f51Sdan do_test pager1-8.$tn.2 { 13150e986f51Sdan sqlite3 db2 $filename 13160e986f51Sdan catchsql { SELECT * FROM x1 } db2 1317153eda0aSdan } {1 {no such table: x1}} 1318153eda0aSdan 13190e986f51Sdan do_execsql_test pager1-8.$tn.3 { 13200e986f51Sdan BEGIN; 13210e986f51Sdan INSERT INTO x1 VALUES('William'); 13220e986f51Sdan INSERT INTO x1 VALUES('Anne'); 13230e986f51Sdan ROLLBACK; 13240e986f51Sdan } {} 13250e986f51Sdan} 13260e986f51Sdan 1327dca321aeSdan#------------------------------------------------------------------------- 1328dca321aeSdan# The next block of tests - pager1-9.* - deal with interactions between 1329dca321aeSdan# the pager and the backup API. Test cases: 1330dca321aeSdan# 1331dca321aeSdan# pager1-9.1.*: Test that a backup completes successfully even if the 1332dca321aeSdan# source db is written to during the backup op. 1333dca321aeSdan# 1334dca321aeSdan# pager1-9.2.*: Test that a backup completes successfully even if the 1335dca321aeSdan# source db is written to and then rolled back during a 1336dca321aeSdan# backup operation. 1337dca321aeSdan# 1338dca321aeSdando_test pager1-9.0.1 { 1339dca321aeSdan faultsim_delete_and_reopen 1340dca321aeSdan db func a_string a_string 1341dca321aeSdan execsql { 1342dca321aeSdan PRAGMA cache_size = 10; 1343dca321aeSdan BEGIN; 1344dca321aeSdan CREATE TABLE ab(a, b, UNIQUE(a, b)); 1345dca321aeSdan INSERT INTO ab VALUES( a_string(200), a_string(300) ); 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 INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1350dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1351dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1352dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1353dca321aeSdan COMMIT; 1354dca321aeSdan } 1355dca321aeSdan} {} 1356dca321aeSdando_test pager1-9.0.2 { 1357dca321aeSdan sqlite3 db2 test.db2 1358dca321aeSdan db2 eval { PRAGMA cache_size = 10 } 1359dca321aeSdan sqlite3_backup B db2 main db main 1360dca321aeSdan list [B step 10000] [B finish] 1361dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1362dca321aeSdando_test pager1-9.0.3 { 1363dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1364dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1365dca321aeSdan 1366dca321aeSdando_test pager1-9.1.1 { 1367dca321aeSdan execsql { UPDATE ab SET a = a_string(201) } 1368dca321aeSdan sqlite3_backup B db2 main db main 1369dca321aeSdan B step 30 1370dca321aeSdan} {SQLITE_OK} 1371dca321aeSdando_test pager1-9.1.2 { 1372dca321aeSdan execsql { UPDATE ab SET b = a_string(301) } 1373dca321aeSdan list [B step 10000] [B finish] 1374dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1375dca321aeSdando_test pager1-9.1.3 { 1376dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1377dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1378dca321aeSdando_test pager1-9.1.4 { execsql { SELECT count(*) FROM ab } } {128} 1379dca321aeSdan 1380dca321aeSdando_test pager1-9.2.1 { 1381dca321aeSdan execsql { UPDATE ab SET a = a_string(202) } 1382dca321aeSdan sqlite3_backup B db2 main db main 1383dca321aeSdan B step 30 1384dca321aeSdan} {SQLITE_OK} 1385dca321aeSdando_test pager1-9.2.2 { 1386dca321aeSdan execsql { 1387dca321aeSdan BEGIN; 1388dca321aeSdan UPDATE ab SET b = a_string(301); 1389dca321aeSdan ROLLBACK; 1390dca321aeSdan } 1391dca321aeSdan list [B step 10000] [B finish] 1392dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1393dca321aeSdando_test pager1-9.2.3 { 1394dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1395dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1396dca321aeSdando_test pager1-9.2.4 { execsql { SELECT count(*) FROM ab } } {128} 1397ec6ffc1aSdandb close 1398ec6ffc1aSdandb2 close 1399ec6ffc1aSdan 1400c396d4afSdando_test pager1-9.3.1 { 1401c396d4afSdan testvfs tv -default 1 1402c396d4afSdan tv sectorsize 4096 1403c396d4afSdan faultsim_delete_and_reopen 1404c396d4afSdan 1405c396d4afSdan execsql { PRAGMA page_size = 1024 } 1406c396d4afSdan for {set ii 0} {$ii < 4} {incr ii} { execsql "CREATE TABLE t${ii}(a, b)" } 1407c396d4afSdan} {} 14084a8a6467Sdrhif {[nonzero_reserved_bytes]} { 14094a8a6467Sdrh # backup with a page size changes is not possible with the codec 14104a8a6467Sdrh # 14114a8a6467Sdrh do_test pager1-9.3.2codec { 1412c396d4afSdan sqlite3 db2 test.db2 1413c396d4afSdan execsql { 1414c396d4afSdan PRAGMA page_size = 4096; 1415c396d4afSdan PRAGMA synchronous = OFF; 1416c396d4afSdan CREATE TABLE t1(a, b); 1417c396d4afSdan CREATE TABLE t2(a, b); 1418c396d4afSdan } db2 14194a8a6467Sdrh sqlite3_backup B db2 main db main 14204a8a6467Sdrh B step 30 14214a8a6467Sdrh list [B step 10000] [B finish] 14224a8a6467Sdrh } {SQLITE_READONLY SQLITE_READONLY} 14234a8a6467Sdrh do_test pager1-9.3.3codec { 14244a8a6467Sdrh db2 close 14254a8a6467Sdrh db close 14264a8a6467Sdrh tv delete 14274a8a6467Sdrh file size test.db2 14284a8a6467Sdrh } [file size test.db2] 14294a8a6467Sdrh} else { 14304a8a6467Sdrh do_test pager1-9.3.2 { 14314a8a6467Sdrh sqlite3 db2 test.db2 14324a8a6467Sdrh execsql { 14334a8a6467Sdrh PRAGMA page_size = 4096; 14344a8a6467Sdrh PRAGMA synchronous = OFF; 14354a8a6467Sdrh CREATE TABLE t1(a, b); 14364a8a6467Sdrh CREATE TABLE t2(a, b); 14374a8a6467Sdrh } db2 1438c396d4afSdan sqlite3_backup B db2 main db main 1439c396d4afSdan B step 30 1440c396d4afSdan list [B step 10000] [B finish] 1441c396d4afSdan } {SQLITE_DONE SQLITE_OK} 1442c396d4afSdan do_test pager1-9.3.3 { 1443c396d4afSdan db2 close 1444c396d4afSdan db close 1445c396d4afSdan tv delete 1446c396d4afSdan file size test.db2 1447c396d4afSdan } [file size test.db] 14484a8a6467Sdrh} 1449c396d4afSdan 1450f412ee2eSdando_test pager1-9.4.1 { 1451f412ee2eSdan faultsim_delete_and_reopen 1452f412ee2eSdan sqlite3 db2 test.db2 1453f412ee2eSdan execsql { 1454f412ee2eSdan PRAGMA page_size = 4096; 1455f412ee2eSdan CREATE TABLE t1(a, b); 1456f412ee2eSdan CREATE TABLE t2(a, b); 1457f412ee2eSdan } db2 1458f412ee2eSdan sqlite3_backup B db2 main db main 1459f412ee2eSdan list [B step 10000] [B finish] 1460f412ee2eSdan} {SQLITE_DONE SQLITE_OK} 1461f412ee2eSdando_test pager1-9.4.2 { 1462f412ee2eSdan list [file size test.db2] [file size test.db] 1463b483eba0Sdan} {1024 0} 146433d85c9cSshanehdb2 close 1465d0b0d4dcSdan 1466ec6ffc1aSdan#------------------------------------------------------------------------- 1467ec6ffc1aSdan# Test that regardless of the value returned by xSectorSize(), the 1468ec6ffc1aSdan# minimum effective sector-size is 512 and the maximum 65536 bytes. 1469ec6ffc1aSdan# 1470ec6ffc1aSdantestvfs tv -default 1 1471ec6ffc1aSdanforeach sectorsize { 1472d7a558a9Sdan 16 1473ec6ffc1aSdan 32 64 128 256 512 1024 2048 1474ec6ffc1aSdan 4096 8192 16384 32768 65536 131072 262144 1475ec6ffc1aSdan} { 1476ec6ffc1aSdan tv sectorsize $sectorsize 14771eaaf93aSdrh tv devchar {} 1478ec6ffc1aSdan set eff $sectorsize 1479ec6ffc1aSdan if {$sectorsize < 512} { set eff 512 } 1480ec6ffc1aSdan if {$sectorsize > 65536} { set eff 65536 } 1481ec6ffc1aSdan 1482d0b0d4dcSdan do_test pager1-10.$sectorsize.1 { 1483ec6ffc1aSdan faultsim_delete_and_reopen 1484d0b0d4dcSdan db func a_string a_string 1485ec6ffc1aSdan execsql { 1486ec6ffc1aSdan PRAGMA journal_mode = PERSIST; 1487ec6ffc1aSdan PRAGMA page_size = 1024; 1488d0b0d4dcSdan BEGIN; 1489ec6ffc1aSdan CREATE TABLE t1(a, b); 1490d0b0d4dcSdan CREATE TABLE t2(a, b); 1491d0b0d4dcSdan CREATE TABLE t3(a, b); 1492d0b0d4dcSdan COMMIT; 1493ec6ffc1aSdan } 1494ec6ffc1aSdan file size test.db-journal 1495d7a558a9Sdan } [expr $sectorsize > 65536 ? 65536 : ($sectorsize<32 ? 512 : $sectorsize)] 1496d0b0d4dcSdan 1497d0b0d4dcSdan do_test pager1-10.$sectorsize.2 { 1498d0b0d4dcSdan execsql { 1499d0b0d4dcSdan INSERT INTO t3 VALUES(a_string(300), a_string(300)); 1500d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 2 */ 1501d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 4 */ 1502d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 8 */ 1503d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 16 */ 1504d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 32 */ 1505ec6ffc1aSdan } 1506d0b0d4dcSdan } {} 1507d0b0d4dcSdan 1508d0b0d4dcSdan do_test pager1-10.$sectorsize.3 { 1509d0b0d4dcSdan db close 1510d0b0d4dcSdan sqlite3 db test.db 1511d0b0d4dcSdan execsql { 1512d0b0d4dcSdan PRAGMA cache_size = 10; 1513d0b0d4dcSdan BEGIN; 1514d0b0d4dcSdan } 1515d0b0d4dcSdan recursive_select 32 t3 {db eval "INSERT INTO t2 VALUES(1, 2)"} 1516d0b0d4dcSdan execsql { 1517d0b0d4dcSdan COMMIT; 1518d0b0d4dcSdan SELECT * FROM t2; 1519d0b0d4dcSdan } 1520d0b0d4dcSdan } {1 2} 1521d0b0d4dcSdan 1522d0b0d4dcSdan do_test pager1-10.$sectorsize.4 { 1523d0b0d4dcSdan execsql { 1524d0b0d4dcSdan CREATE TABLE t6(a, b); 1525d0b0d4dcSdan CREATE TABLE t7(a, b); 1526d0b0d4dcSdan CREATE TABLE t5(a, b); 1527d0b0d4dcSdan DROP TABLE t6; 1528d0b0d4dcSdan DROP TABLE t7; 1529d0b0d4dcSdan } 1530d0b0d4dcSdan execsql { 1531d0b0d4dcSdan BEGIN; 1532d0b0d4dcSdan CREATE TABLE t6(a, b); 1533d0b0d4dcSdan } 1534d0b0d4dcSdan recursive_select 32 t3 {db eval "INSERT INTO t5 VALUES(1, 2)"} 1535d0b0d4dcSdan execsql { 1536d0b0d4dcSdan COMMIT; 1537d0b0d4dcSdan SELECT * FROM t5; 1538d0b0d4dcSdan } 1539d0b0d4dcSdan } {1 2} 1540d0b0d4dcSdan 1541d0b0d4dcSdan} 1542d0b0d4dcSdandb close 1543d0b0d4dcSdan 1544d0b0d4dcSdantv sectorsize 4096 1545d0b0d4dcSdando_test pager1.10.x.1 { 1546d0b0d4dcSdan faultsim_delete_and_reopen 1547d0b0d4dcSdan execsql { 1548f43d7fceSdan PRAGMA auto_vacuum = none; 1549d0b0d4dcSdan PRAGMA page_size = 1024; 1550d0b0d4dcSdan CREATE TABLE t1(x); 1551d0b0d4dcSdan } 1552d0b0d4dcSdan for {set i 0} {$i<30} {incr i} { 1553d0b0d4dcSdan execsql { INSERT INTO t1 VALUES(zeroblob(900)) } 1554d0b0d4dcSdan } 1555d0b0d4dcSdan file size test.db 1556d0b0d4dcSdan} {32768} 1557d0b0d4dcSdando_test pager1.10.x.2 { 1558d0b0d4dcSdan execsql { 1559d0b0d4dcSdan CREATE TABLE t2(x); 1560d0b0d4dcSdan DROP TABLE t2; 1561d0b0d4dcSdan } 1562d0b0d4dcSdan file size test.db 1563d0b0d4dcSdan} {33792} 1564d0b0d4dcSdando_test pager1.10.x.3 { 1565d0b0d4dcSdan execsql { 1566d0b0d4dcSdan BEGIN; 1567d0b0d4dcSdan CREATE TABLE t2(x); 1568d0b0d4dcSdan } 1569d0b0d4dcSdan recursive_select 30 t1 1570d0b0d4dcSdan execsql { 1571d0b0d4dcSdan CREATE TABLE t3(x); 1572d0b0d4dcSdan COMMIT; 1573d0b0d4dcSdan } 1574d0b0d4dcSdan} {} 1575d0b0d4dcSdan 1576ec6ffc1aSdandb close 1577ec6ffc1aSdantv delete 1578ec6ffc1aSdan 1579ec6ffc1aSdantestvfs tv -default 1 1580ec6ffc1aSdanfaultsim_delete_and_reopen 1581ec6ffc1aSdandb func a_string a_string 1582ec6ffc1aSdando_execsql_test pager1-11.1 { 15833f94b609Sdan PRAGMA journal_mode = DELETE; 1584ec6ffc1aSdan PRAGMA cache_size = 10; 1585ec6ffc1aSdan BEGIN; 1586ec6ffc1aSdan CREATE TABLE zz(top PRIMARY KEY); 1587ec6ffc1aSdan INSERT INTO zz VALUES(a_string(222)); 1588ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1589ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1590ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1591ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1592ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1593ec6ffc1aSdan COMMIT; 1594ec6ffc1aSdan BEGIN; 1595ec6ffc1aSdan UPDATE zz SET top = a_string(345); 15963f94b609Sdan} {delete} 1597ec6ffc1aSdan 1598ec6ffc1aSdanproc lockout {method args} { return SQLITE_IOERR } 1599ec6ffc1aSdantv script lockout 1600ec6ffc1aSdantv filter {xWrite xTruncate xSync} 1601ec6ffc1aSdando_catchsql_test pager1-11.2 { COMMIT } {1 {disk I/O error}} 1602ec6ffc1aSdan 1603ec6ffc1aSdantv script {} 1604ec6ffc1aSdando_test pager1-11.3 { 1605ec6ffc1aSdan sqlite3 db2 test.db 1606ec6ffc1aSdan execsql { 1607ec6ffc1aSdan PRAGMA journal_mode = TRUNCATE; 1608ec6ffc1aSdan PRAGMA integrity_check; 1609ec6ffc1aSdan } db2 1610ec6ffc1aSdan} {truncate ok} 1611ec6ffc1aSdando_test pager1-11.4 { 1612ec6ffc1aSdan db2 close 1613f6c61471Sdan file exists test.db-journal 1614ec6ffc1aSdan} {0} 1615ec6ffc1aSdando_execsql_test pager1-11.5 { SELECT count(*) FROM zz } {32} 1616f9b4419dSdandb close 1617f9b4419dSdantv delete 1618ec6ffc1aSdan 1619f9b4419dSdan#------------------------------------------------------------------------- 1620f9b4419dSdan# Test "PRAGMA page_size" 1621f9b4419dSdan# 1622f43d7fceSdantestvfs tv -default 1 1623f43d7fceSdantv sectorsize 1024 1624f9b4419dSdanforeach pagesize { 1625f9b4419dSdan 512 1024 2048 4096 8192 16384 32768 1626f9b4419dSdan} { 1627f9b4419dSdan faultsim_delete_and_reopen 1628f9b4419dSdan 1629f43d7fceSdan # The sector-size (according to the VFS) is 1024 bytes. So if the 1630f43d7fceSdan # page-size requested using "PRAGMA page_size" is greater than the 1631f43d7fceSdan # compile time value of SQLITE_MAX_PAGE_SIZE, then the effective 1632f43d7fceSdan # page-size remains 1024 bytes. 1633f43d7fceSdan # 1634f43d7fceSdan set eff $pagesize 1635f43d7fceSdan if {$eff > $::SQLITE_MAX_PAGE_SIZE} { set eff 1024 } 1636f43d7fceSdan 1637f9b4419dSdan do_test pager1-12.$pagesize.1 { 1638f9b4419dSdan sqlite3 db2 test.db 1639f9b4419dSdan execsql " 1640f9b4419dSdan PRAGMA page_size = $pagesize; 1641f9b4419dSdan CREATE VIEW v AS SELECT * FROM sqlite_master; 1642f9b4419dSdan " db2 1643f9b4419dSdan file size test.db 1644f43d7fceSdan } $eff 1645f9b4419dSdan do_test pager1-12.$pagesize.2 { 1646f9b4419dSdan sqlite3 db2 test.db 1647f9b4419dSdan execsql { 1648f9b4419dSdan SELECT count(*) FROM v; 1649f9b4419dSdan PRAGMA main.page_size; 1650f9b4419dSdan } db2 1651f43d7fceSdan } [list 1 $eff] 1652f9b4419dSdan do_test pager1-12.$pagesize.3 { 1653f9b4419dSdan execsql { 1654f9b4419dSdan SELECT count(*) FROM v; 1655f9b4419dSdan PRAGMA main.page_size; 1656f9b4419dSdan } 1657f43d7fceSdan } [list 1 $eff] 1658f9b4419dSdan db2 close 1659f9b4419dSdan} 1660f43d7fceSdandb close 1661f43d7fceSdantv delete 1662dca321aeSdan 1663d353331aSdan#------------------------------------------------------------------------- 1664d353331aSdan# Test specal "PRAGMA journal_mode=PERSIST" test cases. 1665d353331aSdan# 1666d353331aSdan# pager1-13.1.*: This tests a special case encountered in persistent 1667d353331aSdan# journal mode: If the journal associated with a transaction 1668d353331aSdan# is smaller than the journal file (because a previous 1669d353331aSdan# transaction left a very large non-hot journal file in the 1670d353331aSdan# file-system), then SQLite has to be careful that there is 1671d353331aSdan# not a journal-header left over from a previous transaction 1672d353331aSdan# immediately following the journal content just written. 1673d353331aSdan# If there is, and the process crashes so that the journal 1674d353331aSdan# becomes a hot-journal and must be rolled back by another 1675d353331aSdan# process, there is a danger that the other process may roll 1676d353331aSdan# back the aborted transaction, then continue copying data 1677d353331aSdan# from an older transaction from the remainder of the journal. 1678d353331aSdan# See the syncJournal() function for details. 1679d353331aSdan# 1680d353331aSdan# pager1-13.2.*: Same test as the previous. This time, throw an index into 1681d353331aSdan# the mix to make the integrity-check more likely to catch 1682d353331aSdan# errors. 1683d353331aSdan# 1684d353331aSdantestvfs tv -default 1 1685d353331aSdantv script xSyncCb 1686d353331aSdantv filter xSync 1687d353331aSdanproc xSyncCb {method filename args} { 1688d353331aSdan set t [file tail $filename] 1689d353331aSdan if {$t == "test.db"} faultsim_save 1690d353331aSdan return SQLITE_OK 1691d353331aSdan} 1692d353331aSdanfaultsim_delete_and_reopen 1693d353331aSdandb func a_string a_string 1694e91a54e1Sdan 1695d353331aSdan# The UPDATE statement at the end of this test case creates a really big 1696d353331aSdan# journal. Since the cache-size is only 10 pages, the journal contains 1697d353331aSdan# frequent journal headers. 1698d353331aSdan# 1699d353331aSdando_execsql_test pager1-13.1.1 { 1700d353331aSdan PRAGMA page_size = 1024; 1701d353331aSdan PRAGMA journal_mode = PERSIST; 1702d353331aSdan PRAGMA cache_size = 10; 1703d353331aSdan BEGIN; 1704d353331aSdan CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB); 1705d353331aSdan INSERT INTO t1 VALUES(NULL, a_string(400)); 1706d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 2 */ 1707d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 4 */ 1708d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 8 */ 1709d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 16 */ 1710d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 32 */ 1711d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 64 */ 1712d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 128 */ 1713d353331aSdan COMMIT; 1714d353331aSdan UPDATE t1 SET b = a_string(400); 1715d353331aSdan} {persist} 1716d353331aSdan 1717b2f20bfcSshanehif {$::tcl_platform(platform)!="windows"} { 1718d353331aSdan# Run transactions of increasing sizes. Eventually, one (or more than one) 1719d353331aSdan# of these will write just enough content that one of the old headers created 1720d353331aSdan# by the transaction in the block above lies immediately after the content 1721d353331aSdan# journalled by the current transaction. 1722d353331aSdan# 1723d353331aSdanfor {set nUp 1} {$nUp<64} {incr nUp} { 1724d353331aSdan do_execsql_test pager1-13.1.2.$nUp.1 { 1725d353331aSdan UPDATE t1 SET b = a_string(399) WHERE a <= $nUp 1726d353331aSdan } {} 1727d353331aSdan do_execsql_test pager1-13.1.2.$nUp.2 { PRAGMA integrity_check } {ok} 1728d353331aSdan 1729d353331aSdan # Try to access the snapshot of the file-system. 1730d353331aSdan # 1731d353331aSdan sqlite3 db2 sv_test.db 1732d353331aSdan do_test pager1-13.1.2.$nUp.3 { 1733d353331aSdan execsql { SELECT sum(length(b)) FROM t1 } db2 1734d353331aSdan } [expr {128*400 - ($nUp-1)}] 1735d353331aSdan do_test pager1-13.1.2.$nUp.4 { 1736d353331aSdan execsql { PRAGMA integrity_check } db2 1737d353331aSdan } {ok} 1738d353331aSdan db2 close 1739d353331aSdan} 1740b2f20bfcSshaneh} 1741d353331aSdan 1742b2f20bfcSshanehif {$::tcl_platform(platform)!="windows"} { 1743d353331aSdan# Same test as above. But this time with an index on the table. 1744d353331aSdan# 1745d353331aSdando_execsql_test pager1-13.2.1 { 1746d353331aSdan CREATE INDEX i1 ON t1(b); 1747d353331aSdan UPDATE t1 SET b = a_string(400); 1748d353331aSdan} {} 1749d353331aSdanfor {set nUp 1} {$nUp<64} {incr nUp} { 1750d353331aSdan do_execsql_test pager1-13.2.2.$nUp.1 { 1751d353331aSdan UPDATE t1 SET b = a_string(399) WHERE a <= $nUp 1752d353331aSdan } {} 1753d353331aSdan do_execsql_test pager1-13.2.2.$nUp.2 { PRAGMA integrity_check } {ok} 1754d353331aSdan sqlite3 db2 sv_test.db 1755d353331aSdan do_test pager1-13.2.2.$nUp.3 { 1756d353331aSdan execsql { SELECT sum(length(b)) FROM t1 } db2 1757d353331aSdan } [expr {128*400 - ($nUp-1)}] 1758d353331aSdan do_test pager1-13.2.2.$nUp.4 { 1759d353331aSdan execsql { PRAGMA integrity_check } db2 1760d353331aSdan } {ok} 1761d353331aSdan db2 close 1762d353331aSdan} 1763b2f20bfcSshaneh} 1764d353331aSdan 1765d353331aSdandb close 1766d353331aSdantv delete 1767d353331aSdan 1768d353331aSdan#------------------------------------------------------------------------- 1769d353331aSdan# Test specal "PRAGMA journal_mode=OFF" test cases. 1770d353331aSdan# 177175570853Sdan# Do not run these tests for SQLITE_ENABLE_ZIPVFS builds. Such builds 177275570853Sdan# cause the pager to enter the error state if a statement transaction 177375570853Sdan# cannot be rolled back due to a prior "PRAGMA journal_mode=OFF". Which 177475570853Sdan# causes these tests to fail. 177575570853Sdan# 177675570853Sdanif {[info commands zip_register]==""} { 1777d353331aSdanfaultsim_delete_and_reopen 1778d353331aSdando_execsql_test pager1-14.1.1 { 1779d353331aSdan PRAGMA journal_mode = OFF; 1780d353331aSdan CREATE TABLE t1(a, b); 1781d353331aSdan BEGIN; 1782d353331aSdan INSERT INTO t1 VALUES(1, 2); 1783d353331aSdan COMMIT; 1784d353331aSdan SELECT * FROM t1; 1785d353331aSdan} {off 1 2} 1786d353331aSdando_catchsql_test pager1-14.1.2 { 1787d353331aSdan BEGIN; 1788d353331aSdan INSERT INTO t1 VALUES(3, 4); 1789d353331aSdan ROLLBACK; 1790d353331aSdan} {0 {}} 1791d353331aSdando_execsql_test pager1-14.1.3 { 1792d353331aSdan SELECT * FROM t1; 1793354bfe03Sdan} {1 2} 1794d353331aSdando_catchsql_test pager1-14.1.4 { 1795d353331aSdan BEGIN; 1796d353331aSdan INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; 1797d353331aSdan INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; 1798f9c8ce3cSdrh} {1 {UNIQUE constraint failed: t1.rowid}} 1799d353331aSdando_execsql_test pager1-14.1.5 { 1800d353331aSdan COMMIT; 180175570853Sdan} 180275570853Sdando_execsql_test pager1-14.1.6 { 1803d353331aSdan SELECT * FROM t1; 1804354bfe03Sdan} {1 2 2 2} 180575570853Sdan} 1806d353331aSdan 1807c8ce3972Sdan#------------------------------------------------------------------------- 1808c8ce3972Sdan# Test opening and closing the pager sub-system with different values 1809c8ce3972Sdan# for the sqlite3_vfs.szOsFile variable. 1810c8ce3972Sdan# 1811c8ce3972Sdanfaultsim_delete_and_reopen 1812c8ce3972Sdando_execsql_test pager1-15.0 { 1813c8ce3972Sdan CREATE TABLE tx(y, z); 1814c8ce3972Sdan INSERT INTO tx VALUES('Ayutthaya', 'Beijing'); 1815c8ce3972Sdan INSERT INTO tx VALUES('London', 'Tokyo'); 1816c8ce3972Sdan} {} 1817c8ce3972Sdandb close 1818c8ce3972Sdanfor {set i 0} {$i<513} {incr i 3} { 1819c8ce3972Sdan testvfs tv -default 1 -szosfile $i 1820c8ce3972Sdan sqlite3 db test.db 1821c8ce3972Sdan do_execsql_test pager1-15.$i.1 { 1822c8ce3972Sdan SELECT * FROM tx; 1823c8ce3972Sdan } {Ayutthaya Beijing London Tokyo} 1824c8ce3972Sdan db close 1825c8ce3972Sdan tv delete 1826c8ce3972Sdan} 1827c8ce3972Sdan 1828c8ce3972Sdan#------------------------------------------------------------------------- 1829c8ce3972Sdan# Check that it is not possible to open a database file if the full path 1830c8ce3972Sdan# to the associated journal file will be longer than sqlite3_vfs.mxPathname. 1831c8ce3972Sdan# 1832c8ce3972Sdantestvfs tv -default 1 1833c8ce3972Sdantv script xOpenCb 1834c8ce3972Sdantv filter xOpen 183533f5379cSdanproc xOpenCb {method filename args} { 1836c8ce3972Sdan set ::file_len [string length $filename] 1837c8ce3972Sdan} 1838c8ce3972Sdansqlite3 db test.db 1839c8ce3972Sdandb close 1840c8ce3972Sdantv delete 1841c8ce3972Sdan 1842c8ce3972Sdanfor {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} { 1843c8ce3972Sdan testvfs tv -default 1 -mxpathname $ii 1844c8ce3972Sdan 1845c8ce3972Sdan # The length of the full path to file "test.db-journal" is ($::file_len+8). 1846c8ce3972Sdan # If the configured sqlite3_vfs.mxPathname value greater than or equal to 1847c8ce3972Sdan # this, then the file can be opened. Otherwise, it cannot. 1848c8ce3972Sdan # 1849c8ce3972Sdan if {$ii >= [expr $::file_len+8]} { 1850c8ce3972Sdan set res {0 {}} 1851c8ce3972Sdan } else { 1852c8ce3972Sdan set res {1 {unable to open database file}} 1853c8ce3972Sdan } 1854c8ce3972Sdan 1855c8ce3972Sdan do_test pager1-16.1.$ii { 1856c8ce3972Sdan list [catch { sqlite3 db test.db } msg] $msg 1857c8ce3972Sdan } $res 1858c8ce3972Sdan 1859c8ce3972Sdan catch {db close} 1860c8ce3972Sdan tv delete 1861c8ce3972Sdan} 1862c8ce3972Sdan 1863c8ce3972Sdan 1864c8ce3972Sdan#------------------------------------------------------------------------- 1865c8ce3972Sdan# Test the pagers response to the b-tree layer requesting illegal page 1866c8ce3972Sdan# numbers: 1867c8ce3972Sdan# 1868c8ce3972Sdan# + The locking page, 1869c8ce3972Sdan# + Page 0, 1870c8ce3972Sdan# + A page with a page number greater than (2^31-1). 1871c8ce3972Sdan# 1872f4ba1093Sdan# These tests will not work if SQLITE_DIRECT_OVERFLOW_READ is defined. In 1873f4ba1093Sdan# that case IO errors are sometimes reported instead of SQLITE_CORRUPT. 1874f4ba1093Sdan# 1875f4ba1093Sdanifcapable !direct_read { 1876c8ce3972Sdando_test pager1-18.1 { 1877c8ce3972Sdan faultsim_delete_and_reopen 1878c8ce3972Sdan db func a_string a_string 1879c8ce3972Sdan execsql { 1880c8ce3972Sdan PRAGMA page_size = 1024; 1881c8ce3972Sdan CREATE TABLE t1(a, b); 1882c8ce3972Sdan INSERT INTO t1 VALUES(a_string(500), a_string(200)); 1883c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1884c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1885c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1886c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1887c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1888c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1889c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1890c8ce3972Sdan } 1891c8ce3972Sdan} {} 1892c8ce3972Sdando_test pager1-18.2 { 1893c8ce3972Sdan set root [db one "SELECT rootpage FROM sqlite_master"] 1894c8ce3972Sdan set lockingpage [expr (0x10000/1024) + 1] 18956ab91a7aSdrh sqlite3_db_config db DEFENSIVE 0 1896c8ce3972Sdan execsql { 1897c8ce3972Sdan PRAGMA writable_schema = 1; 1898c8ce3972Sdan UPDATE sqlite_master SET rootpage = $lockingpage; 1899c8ce3972Sdan } 1900c8ce3972Sdan sqlite3 db2 test.db 1901c8ce3972Sdan catchsql { SELECT count(*) FROM t1 } db2 1902c8ce3972Sdan} {1 {database disk image is malformed}} 1903c8ce3972Sdandb2 close 1904a748fdccSdrhdo_test pager1-18.3.1 { 1905c8ce3972Sdan execsql { 1906c8ce3972Sdan CREATE TABLE t2(x); 1907c8ce3972Sdan INSERT INTO t2 VALUES(a_string(5000)); 1908c8ce3972Sdan } 1909c8ce3972Sdan set pgno [expr ([file size test.db] / 1024)-2] 1910c8ce3972Sdan hexio_write test.db [expr ($pgno-1)*1024] 00000000 1911c8ce3972Sdan sqlite3 db2 test.db 1912a748fdccSdrh # even though x is malformed, because typeof() does 1913a748fdccSdrh # not load the content of x, the error is not noticed. 1914a748fdccSdrh catchsql { SELECT typeof(x) FROM t2 } db2 1915a748fdccSdrh} {0 text} 1916a748fdccSdrhdo_test pager1-18.3.2 { 1917a748fdccSdrh # in this case, the value of x is loaded and so the error is 1918a748fdccSdrh # detected 1919a748fdccSdrh catchsql { SELECT length(x||'') FROM t2 } db2 1920a748fdccSdrh} {1 {database disk image is malformed}} 1921a748fdccSdrhdb2 close 1922a748fdccSdrhdo_test pager1-18.3.3 { 1923a748fdccSdrh execsql { 1924a748fdccSdrh DELETE FROM t2; 1925a748fdccSdrh INSERT INTO t2 VALUES(randomblob(5000)); 1926a748fdccSdrh } 1927a748fdccSdrh set pgno [expr ([file size test.db] / 1024)-2] 1928a748fdccSdrh hexio_write test.db [expr ($pgno-1)*1024] 00000000 1929a748fdccSdrh sqlite3 db2 test.db 1930a748fdccSdrh # even though x is malformed, because length() and typeof() do 1931a748fdccSdrh # not load the content of x, the error is not noticed. 1932a748fdccSdrh catchsql { SELECT length(x), typeof(x) FROM t2 } db2 1933a748fdccSdrh} {0 {5000 blob}} 1934a748fdccSdrhdo_test pager1-18.3.4 { 1935a748fdccSdrh # in this case, the value of x is loaded and so the error is 1936a748fdccSdrh # detected 1937a748fdccSdrh catchsql { SELECT length(x||'') FROM t2 } db2 1938c8ce3972Sdan} {1 {database disk image is malformed}} 1939c8ce3972Sdandb2 close 1940c8ce3972Sdando_test pager1-18.4 { 1941c8ce3972Sdan hexio_write test.db [expr ($pgno-1)*1024] 90000000 1942c8ce3972Sdan sqlite3 db2 test.db 1943a748fdccSdrh catchsql { SELECT length(x||'') FROM t2 } db2 1944c8ce3972Sdan} {1 {database disk image is malformed}} 1945c8ce3972Sdandb2 close 1946ca439a49Sdrhextra_schema_checks 0 194737f3ac8fSdanifcapable altertable { 1948c8ce3972Sdan do_test pager1-18.5 { 1949c8ce3972Sdan sqlite3 db "" 19506ab91a7aSdrh sqlite3_db_config db DEFENSIVE 0 1951c8ce3972Sdan execsql { 1952c8ce3972Sdan CREATE TABLE t1(a, b); 1953c8ce3972Sdan CREATE TABLE t2(a, b); 1954c8ce3972Sdan PRAGMA writable_schema = 1; 1955c8ce3972Sdan UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1'; 1956c8ce3972Sdan PRAGMA writable_schema = 0; 1957c8ce3972Sdan ALTER TABLE t1 RENAME TO x1; 1958c8ce3972Sdan } 1959c8ce3972Sdan catchsql { SELECT * FROM x1 } 1960ba3cbf3dSdan } {1 {database disk image is malformed}} 1961c8ce3972Sdan db close 196237f3ac8fSdan} 1963ca439a49Sdrhextra_schema_checks 1 1964c8ce3972Sdan 1965ba3cbf3dSdando_test pager1-18.6 { 1966ba3cbf3dSdan faultsim_delete_and_reopen 1967ba3cbf3dSdan db func a_string a_string 1968ba3cbf3dSdan execsql { 1969ba3cbf3dSdan PRAGMA page_size = 1024; 1970ba3cbf3dSdan CREATE TABLE t1(x); 1971ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(800)); 1972ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(800)); 1973ba3cbf3dSdan } 1974ba3cbf3dSdan 1975ba3cbf3dSdan set root [db one "SELECT rootpage FROM sqlite_master"] 1976ba3cbf3dSdan db close 1977ba3cbf3dSdan 1978ba3cbf3dSdan hexio_write test.db [expr ($root-1)*1024 + 8] 00000000 1979ba3cbf3dSdan sqlite3 db test.db 1980ba3cbf3dSdan catchsql { SELECT length(x) FROM t1 } 1981ba3cbf3dSdan} {1 {database disk image is malformed}} 1982f4ba1093Sdan} 1983ba3cbf3dSdan 1984ba3cbf3dSdando_test pager1-19.1 { 1985ba3cbf3dSdan sqlite3 db "" 1986ba3cbf3dSdan db func a_string a_string 1987ba3cbf3dSdan execsql { 1988ba3cbf3dSdan PRAGMA page_size = 512; 1989ba3cbf3dSdan PRAGMA auto_vacuum = 1; 1990ba3cbf3dSdan CREATE TABLE t1(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, 1991ba3cbf3dSdan ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, 1992ba3cbf3dSdan ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, 1993ba3cbf3dSdan da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn, 1994ba3cbf3dSdan ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, 1995ba3cbf3dSdan fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, 1996ba3cbf3dSdan ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn, 1997ba3cbf3dSdan ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn, 1998ba3cbf3dSdan ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix, 1999ba3cbf3dSdan ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn, 2000ba3cbf3dSdan ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn, 2001ba3cbf3dSdan la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln, 2002ba3cbf3dSdan ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn 2003ba3cbf3dSdan ); 2004ba3cbf3dSdan CREATE TABLE t2(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, 2005ba3cbf3dSdan ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, 2006ba3cbf3dSdan ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, 2007ba3cbf3dSdan da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn, 2008ba3cbf3dSdan ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, 2009ba3cbf3dSdan fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, 2010ba3cbf3dSdan ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn, 2011ba3cbf3dSdan ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn, 2012ba3cbf3dSdan ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix, 2013ba3cbf3dSdan ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn, 2014ba3cbf3dSdan ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn, 2015ba3cbf3dSdan la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln, 2016ba3cbf3dSdan ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn 2017ba3cbf3dSdan ); 2018ba3cbf3dSdan INSERT INTO t1(aa) VALUES( a_string(100000) ); 2019ba3cbf3dSdan INSERT INTO t2(aa) VALUES( a_string(100000) ); 2020ba3cbf3dSdan VACUUM; 2021ba3cbf3dSdan } 2022ba3cbf3dSdan} {} 2023ba3cbf3dSdan 20246b63ab47Sdan#------------------------------------------------------------------------- 20256b63ab47Sdan# Test a couple of special cases that come up while committing 20266b63ab47Sdan# transactions: 20276b63ab47Sdan# 20286b63ab47Sdan# pager1-20.1.*: Committing an in-memory database transaction when the 20296b63ab47Sdan# database has not been modified at all. 20306b63ab47Sdan# 20316b63ab47Sdan# pager1-20.2.*: As above, but with a normal db in exclusive-locking mode. 20326b63ab47Sdan# 20336b63ab47Sdan# pager1-20.3.*: Committing a transaction in WAL mode where the database has 20346b63ab47Sdan# been modified, but all dirty pages have been flushed to 20356b63ab47Sdan# disk before the commit. 20366b63ab47Sdan# 20376b63ab47Sdando_test pager1-20.1.1 { 20386b63ab47Sdan catch {db close} 20396b63ab47Sdan sqlite3 db :memory: 20406b63ab47Sdan execsql { 20416b63ab47Sdan CREATE TABLE one(two, three); 20426b63ab47Sdan INSERT INTO one VALUES('a', 'b'); 20436b63ab47Sdan } 20446b63ab47Sdan} {} 20456b63ab47Sdando_test pager1-20.1.2 { 20466b63ab47Sdan execsql { 20476b63ab47Sdan BEGIN EXCLUSIVE; 20486b63ab47Sdan COMMIT; 20496b63ab47Sdan } 20506b63ab47Sdan} {} 20516b63ab47Sdan 20526b63ab47Sdando_test pager1-20.2.1 { 20536b63ab47Sdan faultsim_delete_and_reopen 20546b63ab47Sdan execsql { 20556b63ab47Sdan PRAGMA locking_mode = exclusive; 20566b63ab47Sdan PRAGMA journal_mode = persist; 20576b63ab47Sdan CREATE TABLE one(two, three); 20586b63ab47Sdan INSERT INTO one VALUES('a', 'b'); 20596b63ab47Sdan } 20606b63ab47Sdan} {exclusive persist} 20616b63ab47Sdando_test pager1-20.2.2 { 20626b63ab47Sdan execsql { 20636b63ab47Sdan BEGIN EXCLUSIVE; 20646b63ab47Sdan COMMIT; 20656b63ab47Sdan } 20666b63ab47Sdan} {} 20676b63ab47Sdan 20689091f775Sshanehifcapable wal { 20696b63ab47Sdan do_test pager1-20.3.1 { 20706b63ab47Sdan faultsim_delete_and_reopen 20716b63ab47Sdan db func a_string a_string 20726b63ab47Sdan execsql { 20736b63ab47Sdan PRAGMA cache_size = 10; 20746b63ab47Sdan PRAGMA journal_mode = wal; 20756b63ab47Sdan BEGIN; 20766b63ab47Sdan CREATE TABLE t1(x); 20776b63ab47Sdan CREATE TABLE t2(y); 20786b63ab47Sdan INSERT INTO t1 VALUES(a_string(800)); 20796b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 2 */ 20806b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 4 */ 20816b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 8 */ 20826b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 16 */ 20836b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 32 */ 20846b63ab47Sdan COMMIT; 20856b63ab47Sdan } 20866b63ab47Sdan } {wal} 20876b63ab47Sdan do_test pager1-20.3.2 { 20886b63ab47Sdan execsql { 20896b63ab47Sdan BEGIN; 20906b63ab47Sdan INSERT INTO t2 VALUES('xxxx'); 20916b63ab47Sdan } 2092c396d4afSdan recursive_select 32 t1 20936b63ab47Sdan execsql COMMIT 20946b63ab47Sdan } {} 20959091f775Sshaneh} 20966b63ab47Sdan 209789ccf448Sdan#------------------------------------------------------------------------- 209889ccf448Sdan# Test that a WAL database may not be opened if: 209989ccf448Sdan# 210089ccf448Sdan# pager1-21.1.*: The VFS has an iVersion less than 2, or 210189ccf448Sdan# pager1-21.2.*: The VFS does not provide xShmXXX() methods. 210289ccf448Sdan# 21039091f775Sshanehifcapable wal { 210489ccf448Sdan do_test pager1-21.0 { 210589ccf448Sdan faultsim_delete_and_reopen 210689ccf448Sdan execsql { 210789ccf448Sdan PRAGMA journal_mode = WAL; 210889ccf448Sdan CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def'); 210989ccf448Sdan INSERT INTO ko DEFAULT VALUES; 211089ccf448Sdan } 211189ccf448Sdan } {wal} 211289ccf448Sdan do_test pager1-21.1 { 211389ccf448Sdan testvfs tv -noshm 1 211489ccf448Sdan sqlite3 db2 test.db -vfs tv 211589ccf448Sdan catchsql { SELECT * FROM ko } db2 211689ccf448Sdan } {1 {unable to open database file}} 211789ccf448Sdan db2 close 211889ccf448Sdan tv delete 211989ccf448Sdan do_test pager1-21.2 { 212089ccf448Sdan testvfs tv -iversion 1 212189ccf448Sdan sqlite3 db2 test.db -vfs tv 212289ccf448Sdan catchsql { SELECT * FROM ko } db2 212389ccf448Sdan } {1 {unable to open database file}} 212489ccf448Sdan db2 close 212589ccf448Sdan tv delete 21269091f775Sshaneh} 212789ccf448Sdan 212889ccf448Sdan#------------------------------------------------------------------------- 212989ccf448Sdan# Test that a "PRAGMA wal_checkpoint": 213089ccf448Sdan# 213189ccf448Sdan# pager1-22.1.*: is a no-op on a non-WAL db, and 213289ccf448Sdan# pager1-22.2.*: does not cause xSync calls with a synchronous=off db. 213389ccf448Sdan# 21345209132aSdanifcapable wal { 213589ccf448Sdan do_test pager1-22.1.1 { 213689ccf448Sdan faultsim_delete_and_reopen 213789ccf448Sdan execsql { 213889ccf448Sdan CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def'); 213989ccf448Sdan INSERT INTO ko DEFAULT VALUES; 214089ccf448Sdan } 214189ccf448Sdan execsql { PRAGMA wal_checkpoint } 2142bdd9af0fSdan } {0 -1 -1} 214389ccf448Sdan do_test pager1-22.2.1 { 214489ccf448Sdan testvfs tv -default 1 214589ccf448Sdan tv filter xSync 214689ccf448Sdan tv script xSyncCb 214789ccf448Sdan proc xSyncCb {args} {incr ::synccount} 214889ccf448Sdan set ::synccount 0 214989ccf448Sdan sqlite3 db test.db 215089ccf448Sdan execsql { 215189ccf448Sdan PRAGMA synchronous = off; 215289ccf448Sdan PRAGMA journal_mode = WAL; 215389ccf448Sdan INSERT INTO ko DEFAULT VALUES; 215489ccf448Sdan } 215589ccf448Sdan execsql { PRAGMA wal_checkpoint } 215689ccf448Sdan set synccount 215789ccf448Sdan } {0} 215889ccf448Sdan db close 215989ccf448Sdan tv delete 21605209132aSdan} 216189ccf448Sdan 216289ccf448Sdan#------------------------------------------------------------------------- 216389ccf448Sdan# Tests for changing journal mode. 216489ccf448Sdan# 216589ccf448Sdan# pager1-23.1.*: Test that when changing from PERSIST to DELETE mode, 216689ccf448Sdan# the journal file is deleted. 216789ccf448Sdan# 216889ccf448Sdan# pager1-23.2.*: Same test as above, but while a shared lock is held 216989ccf448Sdan# on the database file. 217089ccf448Sdan# 217189ccf448Sdan# pager1-23.3.*: Same test as above, but while a reserved lock is held 217289ccf448Sdan# on the database file. 217389ccf448Sdan# 217489ccf448Sdan# pager1-23.4.*: And, for fun, while holding an exclusive lock. 217589ccf448Sdan# 217689ccf448Sdan# pager1-23.5.*: Try to set various different journal modes with an 217789ccf448Sdan# in-memory database (only MEMORY and OFF should work). 217889ccf448Sdan# 2179d0b0d4dcSdan# pager1-23.6.*: Try to set locking_mode=normal on an in-memory database 2180d0b0d4dcSdan# (doesn't work - in-memory databases always use 2181d0b0d4dcSdan# locking_mode=exclusive). 2182d0b0d4dcSdan# 218389ccf448Sdando_test pager1-23.1.1 { 218489ccf448Sdan faultsim_delete_and_reopen 218589ccf448Sdan execsql { 218689ccf448Sdan PRAGMA journal_mode = PERSIST; 218789ccf448Sdan CREATE TABLE t1(a, b); 218889ccf448Sdan } 218989ccf448Sdan file exists test.db-journal 219089ccf448Sdan} {1} 219189ccf448Sdando_test pager1-23.1.2 { 219289ccf448Sdan execsql { PRAGMA journal_mode = DELETE } 219389ccf448Sdan file exists test.db-journal 219489ccf448Sdan} {0} 219589ccf448Sdan 219689ccf448Sdando_test pager1-23.2.1 { 219789ccf448Sdan execsql { 219889ccf448Sdan PRAGMA journal_mode = PERSIST; 219989ccf448Sdan INSERT INTO t1 VALUES('Canberra', 'ACT'); 220089ccf448Sdan } 220189ccf448Sdan db eval { SELECT * FROM t1 } { 220289ccf448Sdan db eval { PRAGMA journal_mode = DELETE } 220389ccf448Sdan } 220489ccf448Sdan execsql { PRAGMA journal_mode } 220589ccf448Sdan} {delete} 220689ccf448Sdando_test pager1-23.2.2 { 220789ccf448Sdan file exists test.db-journal 220889ccf448Sdan} {0} 220989ccf448Sdan 221089ccf448Sdando_test pager1-23.3.1 { 221189ccf448Sdan execsql { 221289ccf448Sdan PRAGMA journal_mode = PERSIST; 221389ccf448Sdan INSERT INTO t1 VALUES('Darwin', 'NT'); 221489ccf448Sdan BEGIN IMMEDIATE; 221589ccf448Sdan } 221689ccf448Sdan db eval { PRAGMA journal_mode = DELETE } 221789ccf448Sdan execsql { PRAGMA journal_mode } 221889ccf448Sdan} {delete} 221989ccf448Sdando_test pager1-23.3.2 { 222089ccf448Sdan file exists test.db-journal 222189ccf448Sdan} {0} 222289ccf448Sdando_test pager1-23.3.3 { 222389ccf448Sdan execsql COMMIT 222489ccf448Sdan} {} 222589ccf448Sdan 222689ccf448Sdando_test pager1-23.4.1 { 222789ccf448Sdan execsql { 222889ccf448Sdan PRAGMA journal_mode = PERSIST; 222989ccf448Sdan INSERT INTO t1 VALUES('Adelaide', 'SA'); 223089ccf448Sdan BEGIN EXCLUSIVE; 223189ccf448Sdan } 223289ccf448Sdan db eval { PRAGMA journal_mode = DELETE } 223389ccf448Sdan execsql { PRAGMA journal_mode } 223489ccf448Sdan} {delete} 223589ccf448Sdando_test pager1-23.4.2 { 223689ccf448Sdan file exists test.db-journal 223789ccf448Sdan} {0} 223889ccf448Sdando_test pager1-23.4.3 { 223989ccf448Sdan execsql COMMIT 224089ccf448Sdan} {} 224189ccf448Sdan 224289ccf448Sdando_test pager1-23.5.1 { 224389ccf448Sdan faultsim_delete_and_reopen 224489ccf448Sdan sqlite3 db :memory: 224589ccf448Sdan} {} 224689ccf448Sdanforeach {tn mode possible} { 224789ccf448Sdan 2 off 1 224889ccf448Sdan 3 memory 1 224989ccf448Sdan 4 persist 0 225089ccf448Sdan 5 delete 0 225189ccf448Sdan 6 wal 0 225289ccf448Sdan 7 truncate 0 225389ccf448Sdan} { 225489ccf448Sdan do_test pager1-23.5.$tn.1 { 225589ccf448Sdan execsql "PRAGMA journal_mode = off" 225689ccf448Sdan execsql "PRAGMA journal_mode = $mode" 225789ccf448Sdan } [if $possible {list $mode} {list off}] 225889ccf448Sdan do_test pager1-23.5.$tn.2 { 225989ccf448Sdan execsql "PRAGMA journal_mode = memory" 226089ccf448Sdan execsql "PRAGMA journal_mode = $mode" 226189ccf448Sdan } [if $possible {list $mode} {list memory}] 226289ccf448Sdan} 2263d0b0d4dcSdando_test pager1-23.6.1 { 226489ccf448Sdan execsql {PRAGMA locking_mode = normal} 226589ccf448Sdan} {exclusive} 2266d0b0d4dcSdando_test pager1-23.6.2 { 226789ccf448Sdan execsql {PRAGMA locking_mode = exclusive} 226889ccf448Sdan} {exclusive} 2269d0b0d4dcSdando_test pager1-23.6.3 { 227089ccf448Sdan execsql {PRAGMA locking_mode} 227189ccf448Sdan} {exclusive} 2272d0b0d4dcSdando_test pager1-23.6.4 { 227389ccf448Sdan execsql {PRAGMA main.locking_mode} 227489ccf448Sdan} {exclusive} 22756b63ab47Sdan 2276d0b0d4dcSdan#------------------------------------------------------------------------- 2277d0b0d4dcSdan# 2278d0b0d4dcSdando_test pager1-24.1.1 { 2279d0b0d4dcSdan faultsim_delete_and_reopen 2280d0b0d4dcSdan db func a_string a_string 2281d0b0d4dcSdan execsql { 2282d0b0d4dcSdan PRAGMA cache_size = 10; 2283d0b0d4dcSdan PRAGMA auto_vacuum = FULL; 2284d0b0d4dcSdan CREATE TABLE x1(x, y, z, PRIMARY KEY(y, z)); 2285d0b0d4dcSdan CREATE TABLE x2(x, y, z, PRIMARY KEY(y, z)); 2286d0b0d4dcSdan INSERT INTO x2 VALUES(a_string(400), a_string(500), a_string(600)); 2287d0b0d4dcSdan INSERT INTO x2 SELECT a_string(600), a_string(400), a_string(500) FROM x2; 2288d0b0d4dcSdan INSERT INTO x2 SELECT a_string(500), a_string(600), a_string(400) FROM x2; 2289d0b0d4dcSdan INSERT INTO x2 SELECT a_string(400), a_string(500), a_string(600) FROM x2; 2290d0b0d4dcSdan INSERT INTO x2 SELECT a_string(600), a_string(400), a_string(500) FROM x2; 2291d0b0d4dcSdan INSERT INTO x2 SELECT a_string(500), a_string(600), a_string(400) FROM x2; 2292d0b0d4dcSdan INSERT INTO x2 SELECT a_string(400), a_string(500), a_string(600) FROM x2; 2293d0b0d4dcSdan INSERT INTO x1 SELECT * FROM x2; 2294d0b0d4dcSdan } 2295d0b0d4dcSdan} {} 2296d0b0d4dcSdando_test pager1-24.1.2 { 2297d0b0d4dcSdan execsql { 2298d0b0d4dcSdan BEGIN; 2299d0b0d4dcSdan DELETE FROM x1 WHERE rowid<32; 2300d0b0d4dcSdan } 2301c396d4afSdan recursive_select 64 x2 2302d0b0d4dcSdan} {} 2303d0b0d4dcSdando_test pager1-24.1.3 { 2304d0b0d4dcSdan execsql { 2305d0b0d4dcSdan UPDATE x1 SET z = a_string(300) WHERE rowid>40; 2306d0b0d4dcSdan COMMIT; 2307d0b0d4dcSdan PRAGMA integrity_check; 2308d0b0d4dcSdan SELECT count(*) FROM x1; 2309d0b0d4dcSdan } 2310d0b0d4dcSdan} {ok 33} 2311d0b0d4dcSdan 2312d0b0d4dcSdando_test pager1-24.1.4 { 2313d0b0d4dcSdan execsql { 2314d0b0d4dcSdan DELETE FROM x1; 2315d0b0d4dcSdan INSERT INTO x1 SELECT * FROM x2; 2316d0b0d4dcSdan BEGIN; 2317d0b0d4dcSdan DELETE FROM x1 WHERE rowid<32; 2318d0b0d4dcSdan UPDATE x1 SET z = a_string(299) WHERE rowid>40; 2319d0b0d4dcSdan } 2320c396d4afSdan recursive_select 64 x2 {db eval COMMIT} 2321d0b0d4dcSdan execsql { 2322d0b0d4dcSdan PRAGMA integrity_check; 2323d0b0d4dcSdan SELECT count(*) FROM x1; 2324d0b0d4dcSdan } 2325d0b0d4dcSdan} {ok 33} 2326d0b0d4dcSdan 2327d0b0d4dcSdando_test pager1-24.1.5 { 2328d0b0d4dcSdan execsql { 2329d0b0d4dcSdan DELETE FROM x1; 2330d0b0d4dcSdan INSERT INTO x1 SELECT * FROM x2; 2331d0b0d4dcSdan } 2332c396d4afSdan recursive_select 64 x2 { db eval {CREATE TABLE x3(x, y, z)} } 2333d0b0d4dcSdan execsql { SELECT * FROM x3 } 2334d0b0d4dcSdan} {} 2335d0b0d4dcSdan 2336d0b0d4dcSdan#------------------------------------------------------------------------- 2337d0b0d4dcSdan# 2338d0b0d4dcSdando_test pager1-25-1 { 2339d0b0d4dcSdan faultsim_delete_and_reopen 2340d0b0d4dcSdan execsql { 2341d0b0d4dcSdan BEGIN; 2342d0b0d4dcSdan SAVEPOINT abc; 2343d0b0d4dcSdan CREATE TABLE t1(a, b); 2344d0b0d4dcSdan ROLLBACK TO abc; 2345d0b0d4dcSdan COMMIT; 2346d0b0d4dcSdan } 2347d0b0d4dcSdan db close 2348d0b0d4dcSdan} {} 2349d0b0d4dcSdando_test pager1-25-2 { 2350d0b0d4dcSdan faultsim_delete_and_reopen 2351d0b0d4dcSdan execsql { 2352d0b0d4dcSdan SAVEPOINT abc; 2353d0b0d4dcSdan CREATE TABLE t1(a, b); 2354d0b0d4dcSdan ROLLBACK TO abc; 2355d0b0d4dcSdan COMMIT; 2356d0b0d4dcSdan } 2357d0b0d4dcSdan db close 2358d0b0d4dcSdan} {} 23596b63ab47Sdan 2360c396d4afSdan#------------------------------------------------------------------------- 2361c396d4afSdan# Sector-size tests. 2362c396d4afSdan# 2363c396d4afSdando_test pager1-26.1 { 2364c396d4afSdan testvfs tv -default 1 2365c396d4afSdan tv sectorsize 4096 2366c396d4afSdan faultsim_delete_and_reopen 2367c396d4afSdan db func a_string a_string 2368c396d4afSdan execsql { 2369c396d4afSdan PRAGMA page_size = 512; 2370c396d4afSdan CREATE TABLE tbl(a PRIMARY KEY, b UNIQUE); 2371c396d4afSdan BEGIN; 2372c396d4afSdan INSERT INTO tbl VALUES(a_string(25), a_string(600)); 2373c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2374c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2375c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2376c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2377c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2378c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2379c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2380c396d4afSdan COMMIT; 2381c396d4afSdan } 2382c396d4afSdan} {} 2383c396d4afSdando_execsql_test pager1-26.1 { 2384c396d4afSdan UPDATE tbl SET b = a_string(550); 2385c396d4afSdan} {} 2386c396d4afSdandb close 2387c396d4afSdantv delete 2388c396d4afSdan 2389c396d4afSdan#------------------------------------------------------------------------- 239022b328b2Sdan# 2391c396d4afSdando_test pager1.27.1 { 2392c396d4afSdan faultsim_delete_and_reopen 2393c396d4afSdan sqlite3_pager_refcounts db 2394c396d4afSdan execsql { 2395c396d4afSdan BEGIN; 2396c396d4afSdan CREATE TABLE t1(a, b); 2397c396d4afSdan } 2398c396d4afSdan sqlite3_pager_refcounts db 2399c396d4afSdan execsql COMMIT 2400c396d4afSdan} {} 2401c396d4afSdan 240222b328b2Sdan#------------------------------------------------------------------------- 240322b328b2Sdan# Test that attempting to open a write-transaction with 240422b328b2Sdan# locking_mode=exclusive in WAL mode fails if there are other clients on 240522b328b2Sdan# the same database. 240622b328b2Sdan# 240722b328b2Sdancatch { db close } 24089091f775Sshanehifcapable wal { 240922b328b2Sdan do_multiclient_test tn { 241022b328b2Sdan do_test pager1-28.$tn.1 { 241122b328b2Sdan sql1 { 241222b328b2Sdan PRAGMA journal_mode = WAL; 241322b328b2Sdan CREATE TABLE t1(a, b); 241422b328b2Sdan INSERT INTO t1 VALUES('a', 'b'); 241522b328b2Sdan } 241622b328b2Sdan } {wal} 241722b328b2Sdan do_test pager1-28.$tn.2 { sql2 { SELECT * FROM t1 } } {a b} 241822b328b2Sdan 241922b328b2Sdan do_test pager1-28.$tn.3 { sql1 { PRAGMA locking_mode=exclusive } } {exclusive} 242022b328b2Sdan do_test pager1-28.$tn.4 { 242122b328b2Sdan csql1 { BEGIN; INSERT INTO t1 VALUES('c', 'd'); } 242222b328b2Sdan } {1 {database is locked}} 242322b328b2Sdan code2 { db2 close ; sqlite3 db2 test.db } 242422b328b2Sdan do_test pager1-28.$tn.4 { 242522b328b2Sdan sql1 { INSERT INTO t1 VALUES('c', 'd'); COMMIT } 242622b328b2Sdan } {} 242722b328b2Sdan } 24289091f775Sshaneh} 24295653e4daSdan 24305653e4daSdan#------------------------------------------------------------------------- 24315653e4daSdan# Normally, when changing from journal_mode=PERSIST to DELETE the pager 24325653e4daSdan# attempts to delete the journal file. However, if it cannot obtain a 24335653e4daSdan# RESERVED lock on the database file, this step is skipped. 24345653e4daSdan# 24355653e4daSdando_multiclient_test tn { 24365653e4daSdan do_test pager1-28.$tn.1 { 24375653e4daSdan sql1 { 24385653e4daSdan PRAGMA journal_mode = PERSIST; 24395653e4daSdan CREATE TABLE t1(a, b); 24405653e4daSdan INSERT INTO t1 VALUES('a', 'b'); 24415653e4daSdan } 24425653e4daSdan } {persist} 24435653e4daSdan do_test pager1-28.$tn.2 { file exists test.db-journal } 1 24445653e4daSdan do_test pager1-28.$tn.3 { sql1 { PRAGMA journal_mode = DELETE } } delete 24455653e4daSdan do_test pager1-28.$tn.4 { file exists test.db-journal } 0 24465653e4daSdan 24475653e4daSdan do_test pager1-28.$tn.5 { 24485653e4daSdan sql1 { 24495653e4daSdan PRAGMA journal_mode = PERSIST; 24505653e4daSdan INSERT INTO t1 VALUES('c', 'd'); 24515653e4daSdan } 24525653e4daSdan } {persist} 24535653e4daSdan do_test pager1-28.$tn.6 { file exists test.db-journal } 1 24545653e4daSdan do_test pager1-28.$tn.7 { 24555653e4daSdan sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); } 24565653e4daSdan } {} 24575653e4daSdan do_test pager1-28.$tn.8 { file exists test.db-journal } 1 24585653e4daSdan do_test pager1-28.$tn.9 { sql1 { PRAGMA journal_mode = DELETE } } delete 24595653e4daSdan do_test pager1-28.$tn.10 { file exists test.db-journal } 1 24605653e4daSdan 24615653e4daSdan do_test pager1-28.$tn.11 { sql2 COMMIT } {} 24625653e4daSdan do_test pager1-28.$tn.12 { file exists test.db-journal } 0 24635653e4daSdan 24645653e4daSdan do_test pager1-28-$tn.13 { 24655653e4daSdan code1 { set channel [db incrblob -readonly t1 a 2] } 24665653e4daSdan sql1 { 24675653e4daSdan PRAGMA journal_mode = PERSIST; 24685653e4daSdan INSERT INTO t1 VALUES('g', 'h'); 24695653e4daSdan } 24705653e4daSdan } {persist} 24715653e4daSdan do_test pager1-28.$tn.14 { file exists test.db-journal } 1 24725653e4daSdan do_test pager1-28.$tn.15 { 24735653e4daSdan sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); } 24745653e4daSdan } {} 24755653e4daSdan do_test pager1-28.$tn.16 { sql1 { PRAGMA journal_mode = DELETE } } delete 24765653e4daSdan do_test pager1-28.$tn.17 { file exists test.db-journal } 1 24775653e4daSdan 24785653e4daSdan do_test pager1-28.$tn.17 { csql2 { COMMIT } } {1 {database is locked}} 24795653e4daSdan do_test pager1-28-$tn.18 { code1 { read $channel } } c 24805653e4daSdan do_test pager1-28-$tn.19 { code1 { close $channel } } {} 24815653e4daSdan do_test pager1-28.$tn.20 { sql2 { COMMIT } } {} 24825653e4daSdan} 24835653e4daSdan 24841879b088Sdando_test pager1-29.1 { 24851879b088Sdan faultsim_delete_and_reopen 24861879b088Sdan execsql { 24871879b088Sdan PRAGMA page_size = 1024; 24881879b088Sdan PRAGMA auto_vacuum = full; 24891879b088Sdan PRAGMA locking_mode=exclusive; 24901879b088Sdan CREATE TABLE t1(a, b); 24911879b088Sdan INSERT INTO t1 VALUES(1, 2); 24921879b088Sdan } 24931879b088Sdan file size test.db 24941879b088Sdan} [expr 1024*3] 24954a8a6467Sdrhif {[nonzero_reserved_bytes]} { 24964a8a6467Sdrh # VACUUM with size changes is not possible with the codec. 24974a8a6467Sdrh do_test pager1-29.2 { 24984a8a6467Sdrh catchsql { 24994a8a6467Sdrh PRAGMA page_size = 4096; 25004a8a6467Sdrh VACUUM; 25014a8a6467Sdrh } 25024a8a6467Sdrh } {1 {attempt to write a readonly database}} 25034a8a6467Sdrh} else { 25041879b088Sdan do_test pager1-29.2 { 25051879b088Sdan execsql { 25061879b088Sdan PRAGMA page_size = 4096; 25071879b088Sdan VACUUM; 25081879b088Sdan } 25091879b088Sdan file size test.db 25101879b088Sdan } [expr 4096*3] 25114a8a6467Sdrh} 25121879b088Sdan 2513e08c2066Sdan#------------------------------------------------------------------------- 2514e08c2066Sdan# Test that if an empty database file (size 0 bytes) is opened in 2515e08c2066Sdan# exclusive-locking mode, any journal file is deleted from the file-system 2516e08c2066Sdan# without being rolled back. And that the RESERVED lock obtained while 2517e08c2066Sdan# doing this is not released. 2518e08c2066Sdan# 2519e08c2066Sdando_test pager1-30.1 { 2520e08c2066Sdan db close 2521fda06befSmistachkin delete_file test.db 2522fda06befSmistachkin delete_file test.db-journal 2523e08c2066Sdan set fd [open test.db-journal w] 2524e08c2066Sdan seek $fd [expr 512+1032*2] 2525e08c2066Sdan puts -nonewline $fd x 2526e08c2066Sdan close $fd 2527e08c2066Sdan 2528e08c2066Sdan sqlite3 db test.db 2529e08c2066Sdan execsql { 2530e08c2066Sdan PRAGMA locking_mode=EXCLUSIVE; 2531e08c2066Sdan SELECT count(*) FROM sqlite_master; 2532e08c2066Sdan PRAGMA lock_status; 2533e08c2066Sdan } 2534e08c2066Sdan} {exclusive 0 main reserved temp closed} 2535e08c2066Sdan 2536e08c2066Sdan#------------------------------------------------------------------------- 2537e08c2066Sdan# Test that if the "page-size" field in a journal-header is 0, the journal 2538e08c2066Sdan# file can still be rolled back. This is required for backward compatibility - 2539e08c2066Sdan# versions of SQLite prior to 3.5.8 always set this field to zero. 2540e08c2066Sdan# 254133f5379cSdanif {$tcl_platform(platform)=="unix"} { 2542e08c2066Sdando_test pager1-31.1 { 2543e08c2066Sdan faultsim_delete_and_reopen 2544e08c2066Sdan execsql { 2545e08c2066Sdan PRAGMA cache_size = 10; 2546e08c2066Sdan PRAGMA page_size = 1024; 2547e08c2066Sdan CREATE TABLE t1(x, y, UNIQUE(x, y)); 2548e08c2066Sdan INSERT INTO t1 VALUES(randomblob(1500), randomblob(1500)); 2549e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2550e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2551e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2552e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2553e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2554e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2555e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2556e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2557e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2558e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2559e08c2066Sdan BEGIN; 2560e08c2066Sdan UPDATE t1 SET y = randomblob(1499); 2561e08c2066Sdan } 2562fda06befSmistachkin copy_file test.db test.db2 2563fda06befSmistachkin copy_file test.db-journal test.db2-journal 2564e08c2066Sdan 2565e08c2066Sdan hexio_write test.db2-journal 24 00000000 2566e08c2066Sdan sqlite3 db2 test.db2 2567e08c2066Sdan execsql { PRAGMA integrity_check } db2 2568e08c2066Sdan} {ok} 256933f5379cSdan} 2570e08c2066Sdan 257131e80976Sdrh#------------------------------------------------------------------------- 257231e80976Sdrh# Test that a database file can be "pre-hinted" to a certain size and that 257331e80976Sdrh# subsequent spilling of the pager cache does not result in the database 257431e80976Sdrh# file being shrunk. 257531e80976Sdrh# 257631e80976Sdrhcatch {db close} 257731e80976Sdrhforcedelete test.db 257831e80976Sdrh 257931e80976Sdrhdo_test pager1-32.1 { 258031e80976Sdrh sqlite3 db test.db 258131e80976Sdrh execsql { 258231e80976Sdrh CREATE TABLE t1(x, y); 258331e80976Sdrh } 258431e80976Sdrh db close 258531e80976Sdrh sqlite3 db test.db 258631e80976Sdrh execsql { 258731e80976Sdrh BEGIN; 258831e80976Sdrh INSERT INTO t1 VALUES(1, randomblob(10000)); 258931e80976Sdrh } 25902f7820d8Sdrh file_control_chunksize_test db main 1024 259131e80976Sdrh file_control_sizehint_test db main 20971520; # 20MB 259231e80976Sdrh execsql { 259331e80976Sdrh PRAGMA cache_size = 10; 259431e80976Sdrh INSERT INTO t1 VALUES(1, randomblob(10000)); 259531e80976Sdrh INSERT INTO t1 VALUES(2, randomblob(10000)); 259631e80976Sdrh INSERT INTO t1 SELECT x+2, randomblob(10000) from t1; 259731e80976Sdrh INSERT INTO t1 SELECT x+4, randomblob(10000) from t1; 259831e80976Sdrh INSERT INTO t1 SELECT x+8, randomblob(10000) from t1; 259931e80976Sdrh INSERT INTO t1 SELECT x+16, randomblob(10000) from t1; 260031e80976Sdrh SELECT count(*) FROM t1; 260131e80976Sdrh COMMIT; 260231e80976Sdrh } 260331e80976Sdrh db close 260431e80976Sdrh file size test.db 260531e80976Sdrh} {20971520} 260631e80976Sdrh 260731e80976Sdrh# Cleanup 20MB file left by the previous test. 260831e80976Sdrhforcedelete test.db 26095653e4daSdan 26109fc5b4a5Sdan#------------------------------------------------------------------------- 26119fc5b4a5Sdan# Test that if a transaction is committed in journal_mode=DELETE mode, 26129fc5b4a5Sdan# and the call to unlink() returns an ENOENT error, the COMMIT does not 26139fc5b4a5Sdan# succeed. 26149fc5b4a5Sdan# 26159fc5b4a5Sdanif {$::tcl_platform(platform)=="unix"} { 26169fc5b4a5Sdan do_test pager1-33.1 { 26179fc5b4a5Sdan sqlite3 db test.db 26189fc5b4a5Sdan execsql { 26199fc5b4a5Sdan CREATE TABLE t1(x); 26209fc5b4a5Sdan INSERT INTO t1 VALUES('one'); 26219fc5b4a5Sdan INSERT INTO t1 VALUES('two'); 26229fc5b4a5Sdan BEGIN; 26239fc5b4a5Sdan INSERT INTO t1 VALUES('three'); 26249fc5b4a5Sdan INSERT INTO t1 VALUES('four'); 26259fc5b4a5Sdan } 26269fc5b4a5Sdan forcedelete bak-journal 26279fc5b4a5Sdan file rename test.db-journal bak-journal 26289fc5b4a5Sdan 26299fc5b4a5Sdan catchsql COMMIT 26309fc5b4a5Sdan } {1 {disk I/O error}} 26319fc5b4a5Sdan 26329fc5b4a5Sdan do_test pager1-33.2 { 26339fc5b4a5Sdan file rename bak-journal test.db-journal 26349fc5b4a5Sdan execsql { SELECT * FROM t1 } 26359fc5b4a5Sdan } {one two} 26369fc5b4a5Sdan} 26379fc5b4a5Sdan 2638d7a558a9Sdan#------------------------------------------------------------------------- 2639d7a558a9Sdan# Test that appending pages to the database file then moving those pages 2640d7a558a9Sdan# to the free-list before the transaction is committed does not cause 2641d7a558a9Sdan# an error. 2642d7a558a9Sdan# 2643d7a558a9Sdanforeach {tn pragma strsize} { 26449b4c59faSdrh 1 { PRAGMA mmap_size = 0 } 2400 2645d7a558a9Sdan 2 { } 2400 26469b4c59faSdrh 3 { PRAGMA mmap_size = 0 } 4400 2647d7a558a9Sdan 4 { } 4400 2648d7a558a9Sdan} { 2649d7a558a9Sdan reset_db 2650d7a558a9Sdan db func a_string a_string 2651d7a558a9Sdan db eval $pragma 2652d7a558a9Sdan do_execsql_test 34.$tn.1 { 2653d7a558a9Sdan CREATE TABLE t1(a, b); 2654d7a558a9Sdan INSERT INTO t1 VALUES(1, 2); 2655d7a558a9Sdan } 2656d7a558a9Sdan do_execsql_test 34.$tn.2 { 2657d7a558a9Sdan BEGIN; 2658d7a558a9Sdan INSERT INTO t1 VALUES(2, a_string($strsize)); 2659d7a558a9Sdan DELETE FROM t1 WHERE oid=2; 2660d7a558a9Sdan COMMIT; 2661d7a558a9Sdan PRAGMA integrity_check; 2662d7a558a9Sdan } {ok} 2663d7a558a9Sdan} 2664d7a558a9Sdan 2665d7a558a9Sdan#------------------------------------------------------------------------- 2666d7a558a9Sdan# 2667d7a558a9Sdanreset_db 2668d7a558a9Sdando_test 35 { 2669d7a558a9Sdan sqlite3 db test.db 2670d7a558a9Sdan 2671d7a558a9Sdan execsql { 2672d7a558a9Sdan CREATE TABLE t1(x, y); 2673d7a558a9Sdan PRAGMA journal_mode = WAL; 2674d7a558a9Sdan INSERT INTO t1 VALUES(1, 2); 2675d7a558a9Sdan } 2676d7a558a9Sdan 2677d7a558a9Sdan execsql { 2678d7a558a9Sdan BEGIN; 2679d7a558a9Sdan CREATE TABLE t2(a, b); 2680d7a558a9Sdan } 2681d7a558a9Sdan 2682d7a558a9Sdan hexio_write test.db-shm [expr 16*1024] [string repeat 0055 8192] 2683d7a558a9Sdan catchsql ROLLBACK 2684d7a558a9Sdan} {0 {}} 2685d7a558a9Sdan 2686d7a558a9Sdando_multiclient_test tn { 2687d7a558a9Sdan sql1 { 2688d7a558a9Sdan PRAGMA auto_vacuum = 0; 2689d7a558a9Sdan CREATE TABLE t1(x, y); 2690d7a558a9Sdan INSERT INTO t1 VALUES(1, 2); 2691d7a558a9Sdan } 2692d7a558a9Sdan 2693d7a558a9Sdan do_test 36.$tn.1 { 2694d7a558a9Sdan sql2 { PRAGMA max_page_count = 2 } 2695d7a558a9Sdan list [catch { sql2 { CREATE TABLE t2(x) } } msg] $msg 2696d7a558a9Sdan } {1 {database or disk is full}} 2697d7a558a9Sdan 2698d7a558a9Sdan sql1 { PRAGMA checkpoint_fullfsync = 1 } 2699d7a558a9Sdan sql1 { CREATE TABLE t2(x) } 2700d7a558a9Sdan 2701d7a558a9Sdan do_test 36.$tn.2 { 2702d7a558a9Sdan sql2 { INSERT INTO t2 VALUES('xyz') } 2703d7a558a9Sdan list [catch { sql2 { CREATE TABLE t3(x) } } msg] $msg 2704d7a558a9Sdan } {1 {database or disk is full}} 2705d7a558a9Sdan} 2706d7a558a9Sdan 2707d7a558a9Sdanforcedelete test1 test2 2708d7a558a9Sdanforeach {tn uri} { 2709d7a558a9Sdan 1 {file:?mode=memory&cache=shared} 2710d7a558a9Sdan 2 {file:one?mode=memory&cache=shared} 2711d7a558a9Sdan 3 {file:test1?cache=shared} 2712d7a558a9Sdan 4 {file:test2?another=parameter&yet=anotherone} 2713d7a558a9Sdan} { 2714d7a558a9Sdan do_test 37.$tn { 2715d7a558a9Sdan catch { db close } 2716d7a558a9Sdan sqlite3_shutdown 2717d7a558a9Sdan sqlite3_config_uri 1 2718d7a558a9Sdan sqlite3 db $uri 2719abd6d84aSdan 2720d7a558a9Sdan db eval { 2721d7a558a9Sdan CREATE TABLE t1(x); 2722d7a558a9Sdan INSERT INTO t1 VALUES(1); 2723d7a558a9Sdan SELECT * FROM t1; 2724d7a558a9Sdan } 2725d7a558a9Sdan } {1} 2726abd6d84aSdan 2727abd6d84aSdan do_execsql_test 37.$tn.2 { 2728abd6d84aSdan VACUUM; 2729abd6d84aSdan SELECT * FROM t1; 2730abd6d84aSdan } {1} 2731abd6d84aSdan 2732d7a558a9Sdan db close 2733d7a558a9Sdan sqlite3_shutdown 2734d7a558a9Sdan sqlite3_config_uri 0 2735d7a558a9Sdan} 2736d7a558a9Sdan 2737d7a558a9Sdando_test 38.1 { 2738d7a558a9Sdan catch { db close } 2739d7a558a9Sdan forcedelete test.db 2740d7a558a9Sdan set fd [open test.db w] 2741d7a558a9Sdan puts $fd "hello world" 2742d7a558a9Sdan close $fd 2743d7a558a9Sdan sqlite3 db test.db 2744d7a558a9Sdan catchsql { CREATE TABLE t1(x) } 2745ff4fa772Sdrh} {1 {file is not a database}} 2746d7a558a9Sdando_test 38.2 { 2747d7a558a9Sdan catch { db close } 2748d7a558a9Sdan forcedelete test.db 2749d7a558a9Sdan} {} 2750d7a558a9Sdan 2751d7a558a9Sdando_test 39.1 { 2752d7a558a9Sdan sqlite3 db test.db 2753d7a558a9Sdan execsql { 2754d7a558a9Sdan PRAGMA auto_vacuum = 1; 2755d7a558a9Sdan CREATE TABLE t1(x); 2756d7a558a9Sdan INSERT INTO t1 VALUES('xxx'); 2757d7a558a9Sdan INSERT INTO t1 VALUES('two'); 2758d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(400)); 2759d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(400)); 2760d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(400)); 2761d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(400)); 2762d7a558a9Sdan BEGIN; 2763d7a558a9Sdan UPDATE t1 SET x = 'one' WHERE rowid=1; 2764d7a558a9Sdan } 2765d7a558a9Sdan set ::stmt [sqlite3_prepare db "SELECT * FROM t1 ORDER BY rowid" -1 dummy] 2766d7a558a9Sdan sqlite3_step $::stmt 2767d7a558a9Sdan sqlite3_column_text $::stmt 0 2768d7a558a9Sdan} {one} 2769d7a558a9Sdando_test 39.2 { 2770d7a558a9Sdan execsql { CREATE TABLE t2(x) } 2771d7a558a9Sdan sqlite3_step $::stmt 2772d7a558a9Sdan sqlite3_column_text $::stmt 0 2773d7a558a9Sdan} {two} 2774d7a558a9Sdando_test 39.3 { 2775d7a558a9Sdan sqlite3_finalize $::stmt 2776d7a558a9Sdan execsql COMMIT 2777d7a558a9Sdan} {} 2778d7a558a9Sdan 2779d7a558a9Sdando_execsql_test 39.4 { 2780d7a558a9Sdan PRAGMA auto_vacuum = 2; 2781d7a558a9Sdan CREATE TABLE t3(x); 2782d7a558a9Sdan CREATE TABLE t4(x); 2783d7a558a9Sdan 2784d7a558a9Sdan DROP TABLE t2; 2785d7a558a9Sdan DROP TABLE t3; 2786d7a558a9Sdan DROP TABLE t4; 2787d7a558a9Sdan} 2788d7a558a9Sdando_test 39.5 { 2789d7a558a9Sdan db close 2790d7a558a9Sdan sqlite3 db test.db 2791d7a558a9Sdan execsql { 2792d7a558a9Sdan PRAGMA cache_size = 1; 2793d7a558a9Sdan PRAGMA incremental_vacuum; 2794d7a558a9Sdan PRAGMA integrity_check; 2795d7a558a9Sdan } 2796d7a558a9Sdan} {ok} 2797d7a558a9Sdan 2798d7a558a9Sdando_test 40.1 { 2799d7a558a9Sdan reset_db 2800d7a558a9Sdan execsql { 2801d7a558a9Sdan PRAGMA auto_vacuum = 1; 2802d7a558a9Sdan CREATE TABLE t1(x PRIMARY KEY); 2803d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(1200)); 2804d7a558a9Sdan PRAGMA page_count; 2805d7a558a9Sdan } 2806d7a558a9Sdan} {6} 2807d7a558a9Sdando_test 40.2 { 2808d7a558a9Sdan execsql { 2809d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(1200)); 2810d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(1200)); 2811d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(1200)); 2812d7a558a9Sdan } 2813d7a558a9Sdan} {} 2814d7a558a9Sdando_test 40.3 { 2815d7a558a9Sdan db close 2816d7a558a9Sdan sqlite3 db test.db 2817d7a558a9Sdan execsql { 2818d7a558a9Sdan PRAGMA cache_size = 1; 2819d7a558a9Sdan CREATE TABLE t2(x); 2820d7a558a9Sdan PRAGMA integrity_check; 2821d7a558a9Sdan } 2822d7a558a9Sdan} {ok} 2823d7a558a9Sdan 2824d7a558a9Sdando_test 41.1 { 2825d7a558a9Sdan reset_db 2826d7a558a9Sdan execsql { 2827d7a558a9Sdan CREATE TABLE t1(x PRIMARY KEY); 2828d7a558a9Sdan INSERT INTO t1 VALUES(randomblob(200)); 2829d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2830d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2831d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2832d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2833d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2834d7a558a9Sdan INSERT INTO t1 SELECT randomblob(200) FROM t1; 2835d7a558a9Sdan } 2836d7a558a9Sdan} {} 2837d7a558a9Sdando_test 41.2 { 2838d7a558a9Sdan testvfs tv -default 1 2839d7a558a9Sdan tv sectorsize 16384; 2840d7a558a9Sdan tv devchar [list] 2841d7a558a9Sdan db close 2842d7a558a9Sdan sqlite3 db test.db 2843d7a558a9Sdan execsql { 2844d7a558a9Sdan PRAGMA cache_size = 1; 2845d7a558a9Sdan DELETE FROM t1 WHERE rowid%4; 2846d7a558a9Sdan PRAGMA integrity_check; 2847d7a558a9Sdan } 2848d7a558a9Sdan} {ok} 2849abd6d84aSdandb close 2850abd6d84aSdantv delete 2851d7a558a9Sdan 2852abd6d84aSdanset pending_prev [sqlite3_test_control_pending_byte 0x1000000] 2853abd6d84aSdando_test 42.1 { 2854abd6d84aSdan reset_db 2855abd6d84aSdan execsql { 2856abd6d84aSdan CREATE TABLE t1(x, y); 2857abd6d84aSdan INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); 2858abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2859abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2860abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2861abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2862abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2863abd6d84aSdan 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 } 2868abd6d84aSdan db close 2869abd6d84aSdan sqlite3_test_control_pending_byte 0x0010000 2870abd6d84aSdan sqlite3 db test.db 28719b4c59faSdrh db eval { PRAGMA mmap_size = 0 } 2872abd6d84aSdan catchsql { SELECT sum(length(y)) FROM t1 } 2873abd6d84aSdan} {1 {database disk image is malformed}} 2874abd6d84aSdando_test 42.2 { 2875abd6d84aSdan reset_db 2876abd6d84aSdan execsql { 2877abd6d84aSdan CREATE TABLE t1(x, y); 2878abd6d84aSdan INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); 2879abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2880abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2881abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2882abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2883abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2884abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2885abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2886abd6d84aSdan INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; 2887abd6d84aSdan } 2888abd6d84aSdan db close 2889abd6d84aSdan 2890abd6d84aSdan testvfs tv -default 1 2891abd6d84aSdan tv sectorsize 16384; 2892abd6d84aSdan tv devchar [list] 2893abd6d84aSdan sqlite3 db test.db -vfs tv 2894abd6d84aSdan execsql { UPDATE t1 SET x = randomblob(200) } 2895abd6d84aSdan} {} 2896abd6d84aSdandb close 2897abd6d84aSdantv delete 2898abd6d84aSdansqlite3_test_control_pending_byte $pending_prev 2899abd6d84aSdan 2900abd6d84aSdando_test 43.1 { 2901abd6d84aSdan reset_db 2902abd6d84aSdan execsql { 2903abd6d84aSdan CREATE TABLE t1(x, y); 2904abd6d84aSdan INSERT INTO t1 VALUES(1, 2); 2905abd6d84aSdan CREATE TABLE t2(x, y); 2906abd6d84aSdan INSERT INTO t2 VALUES(1, 2); 2907abd6d84aSdan CREATE TABLE t3(x, y); 2908abd6d84aSdan INSERT INTO t3 VALUES(1, 2); 2909abd6d84aSdan } 2910abd6d84aSdan db close 2911abd6d84aSdan sqlite3 db test.db 2912abd6d84aSdan 29139b4c59faSdrh db eval { PRAGMA mmap_size = 0 } 2914abd6d84aSdan db eval { SELECT * FROM t1 } 2915abd6d84aSdan sqlite3_db_status db CACHE_MISS 0 2916abd6d84aSdan} {0 2 0} 2917abd6d84aSdan 2918abd6d84aSdando_test 43.2 { 2919abd6d84aSdan db eval { SELECT * FROM t2 } 2920abd6d84aSdan sqlite3_db_status db CACHE_MISS 1 2921abd6d84aSdan} {0 3 0} 2922abd6d84aSdan 2923abd6d84aSdando_test 43.3 { 2924abd6d84aSdan db eval { SELECT * FROM t3 } 2925abd6d84aSdan sqlite3_db_status db CACHE_MISS 0 2926abd6d84aSdan} {0 1 0} 2927d7a558a9Sdan 2928*90368c5dSdrh# 2022-03-01 Forum post https://sqlite.org/forum/forumpost/3b9e894312 2929*90368c5dSdrh# Ensure that max_page_count gets adjusted upward, if needed, on a 2930*90368c5dSdrh# ROLLBACK. 2931*90368c5dSdrh# 2932*90368c5dSdrhdb close 2933*90368c5dSdrhsqlite3 db :memory: 2934*90368c5dSdrhdo_execsql_test 44.1 { 2935*90368c5dSdrh PRAGMA page_size=4096; 2936*90368c5dSdrh PRAGMA auto_vacuum=FULL; 2937*90368c5dSdrh CREATE TABLE t1(a INTEGER PRIMARY KEY, b ANY); 2938*90368c5dSdrh WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<50) 2939*90368c5dSdrh INSERT INTO t1(a,b) SELECT x, zeroblob(1000) FROM c; 2940*90368c5dSdrh CREATE TABLE t2 AS SELECT * FROM t1; 2941*90368c5dSdrh PRAGMA page_count; 2942*90368c5dSdrh} {31} 2943*90368c5dSdrhdo_execsql_test 44.2 { 2944*90368c5dSdrh BEGIN; 2945*90368c5dSdrh DROP TABLE t2; 2946*90368c5dSdrh PRAGMA incremental_vacuum=50; 2947*90368c5dSdrh PRAGMA page_count; 2948*90368c5dSdrh PRAGMA max_page_count=2; 2949*90368c5dSdrh} {16 16} 2950*90368c5dSdrhdo_execsql_test 44.3 { 2951*90368c5dSdrh ROLLBACK; 2952*90368c5dSdrh PRAGMA page_count; 2953*90368c5dSdrh PRAGMA max_page_count; 2954*90368c5dSdrh} {31 31} 2955*90368c5dSdrh 2956d353331aSdanfinish_test 2957