1e91a54e1Sdan# 2010 June 15 2e91a54e1Sdan# 3e91a54e1Sdan# The author disclaims copyright to this source code. In place of 4e91a54e1Sdan# a legal notice, here is a blessing: 5e91a54e1Sdan# 6e91a54e1Sdan# May you do good and not evil. 7e91a54e1Sdan# May you find forgiveness for yourself and forgive others. 8e91a54e1Sdan# May you share freely, never taking more than you give. 9e91a54e1Sdan# 10e91a54e1Sdan#*********************************************************************** 11e91a54e1Sdan# 12e91a54e1Sdan 13e91a54e1Sdanset testdir [file dirname $argv0] 14e91a54e1Sdansource $testdir/tester.tcl 15e91a54e1Sdansource $testdir/lock_common.tcl 16e91a54e1Sdansource $testdir/malloc_common.tcl 17153eda0aSdansource $testdir/wal_common.tcl 1868928b6cSdan 1968928b6cSdan# Do not use a codec for tests in this file, as the database file is 2068928b6cSdan# manipulated directly using tcl scripts (using the [hexio_write] command). 2168928b6cSdan# 2268928b6cSdando_not_use_codec 23e91a54e1Sdan 24b0ac3e3aSdan# 25b0ac3e3aSdan# pager1-1.*: Test inter-process locking (clients in multiple processes). 26b0ac3e3aSdan# 27b0ac3e3aSdan# pager1-2.*: Test intra-process locking (multiple clients in this process). 28b0ac3e3aSdan# 29b0ac3e3aSdan# pager1-3.*: Savepoint related tests. 30b0ac3e3aSdan# 311f4cb65aSdan# pager1-4.*: Hot-journal related tests. 321f4cb65aSdan# 33de4996e2Sdan# pager1-5.*: Cases related to multi-file commits. 34de4996e2Sdan# 35146ed78bSdan# pager1-6.*: Cases related to "PRAGMA max_page_count" 36146ed78bSdan# 37153eda0aSdan# pager1-7.*: Cases specific to "PRAGMA journal_mode=TRUNCATE" 38153eda0aSdan# 390e986f51Sdan# pager1-8.*: Cases using temporary and in-memory databases. 400e986f51Sdan# 41dca321aeSdan# pager1-9.*: Tests related to the backup API. 42dca321aeSdan# 43ec6ffc1aSdan# pager1-10.*: Test that the assumed file-system sector-size is limited to 44ec6ffc1aSdan# 64KB. 45ec6ffc1aSdan# 46d353331aSdan# pager1-12.*: Tests involving "PRAGMA page_size" 47d353331aSdan# 48d353331aSdan# pager1-13.*: Cases specific to "PRAGMA journal_mode=PERSIST" 49d353331aSdan# 50d353331aSdan# pager1-14.*: Cases specific to "PRAGMA journal_mode=OFF" 51ec6ffc1aSdan# 52c8ce3972Sdan# pager1-15.*: Varying sqlite3_vfs.szOsFile 53c8ce3972Sdan# 54c8ce3972Sdan# pager1-16.*: Varying sqlite3_vfs.mxPathname 55c8ce3972Sdan# 56c8ce3972Sdan# pager1-17.*: Tests related to "PRAGMA omit_readlock" 5733f111dcSdrh# (The omit_readlock pragma has been removed and so have 5833f111dcSdrh# these tests.) 59c8ce3972Sdan# 60c8ce3972Sdan# pager1-18.*: Test that the pager layer responds correctly if the b-tree 61c8ce3972Sdan# requests an invalid page number (due to db corruption). 62c8ce3972Sdan# 63b0ac3e3aSdan 64c396d4afSdanproc recursive_select {id table {script {}}} { 65c396d4afSdan set cnt 0 66c396d4afSdan db eval "SELECT rowid, * FROM $table WHERE rowid = ($id-1)" { 67c396d4afSdan recursive_select $rowid $table $script 68c396d4afSdan incr cnt 69c396d4afSdan } 70c396d4afSdan if {$cnt==0} { eval $script } 71c396d4afSdan} 72c396d4afSdan 7353f04f3bSdanset a_string_counter 1 7453f04f3bSdanproc a_string {n} { 7553f04f3bSdan global a_string_counter 7653f04f3bSdan incr a_string_counter 7753f04f3bSdan string range [string repeat "${a_string_counter}." $n] 1 $n 7853f04f3bSdan} 7953f04f3bSdandb func a_string a_string 8053f04f3bSdan 81a4a9095eSdando_multiclient_test tn { 82e91a54e1Sdan 83e91a54e1Sdan # Create and populate a database table using connection [db]. Check 84e91a54e1Sdan # that connections [db2] and [db3] can see the schema and content. 85e91a54e1Sdan # 86e91a54e1Sdan do_test pager1-$tn.1 { 87e91a54e1Sdan sql1 { 88e91a54e1Sdan CREATE TABLE t1(a PRIMARY KEY, b); 89e91a54e1Sdan CREATE INDEX i1 ON t1(b); 90d353331aSdan INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); 91e91a54e1Sdan } 92e91a54e1Sdan } {} 93e91a54e1Sdan do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two} 94e91a54e1Sdan do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two} 95e91a54e1Sdan 96e91a54e1Sdan # Open a transaction and add a row using [db]. This puts [db] in 97e91a54e1Sdan # RESERVED state. Check that connections [db2] and [db3] can still 98e91a54e1Sdan # read the database content as it was before the transaction was 99e91a54e1Sdan # opened. [db] should see the inserted row. 100e91a54e1Sdan # 101e91a54e1Sdan do_test pager1-$tn.4 { 102e91a54e1Sdan sql1 { 103e91a54e1Sdan BEGIN; 104e91a54e1Sdan INSERT INTO t1 VALUES(3, 'three'); 105e91a54e1Sdan } 106e91a54e1Sdan } {} 107e91a54e1Sdan do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two} 108e91a54e1Sdan do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} 109e91a54e1Sdan 110e91a54e1Sdan # [db] still has an open write transaction. Check that this prevents 111e91a54e1Sdan # other connections (specifically [db2]) from writing to the database. 112e91a54e1Sdan # 113e91a54e1Sdan # Even if [db2] opens a transaction first, it may not write to the 114e91a54e1Sdan # database. After the attempt to write the db within a transaction, 115e91a54e1Sdan # [db2] is left with an open transaction, but not a read-lock on 116e91a54e1Sdan # the main database. So it does not prevent [db] from committing. 117e91a54e1Sdan # 118e91a54e1Sdan do_test pager1-$tn.8 { 119e91a54e1Sdan csql2 { UPDATE t1 SET a = a + 10 } 120e91a54e1Sdan } {1 {database is locked}} 121e91a54e1Sdan do_test pager1-$tn.9 { 122e91a54e1Sdan csql2 { 123e91a54e1Sdan BEGIN; 124e91a54e1Sdan UPDATE t1 SET a = a + 10; 125e91a54e1Sdan } 126e91a54e1Sdan } {1 {database is locked}} 127e91a54e1Sdan 128e91a54e1Sdan # Have [db] commit its transactions. Check the other connections can 129e91a54e1Sdan # now see the new database content. 130e91a54e1Sdan # 131e91a54e1Sdan do_test pager1-$tn.10 { sql1 { COMMIT } } {} 132e91a54e1Sdan do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} 133e91a54e1Sdan do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 134e91a54e1Sdan do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 135e91a54e1Sdan 136e91a54e1Sdan # Check that, as noted above, [db2] really did keep an open transaction 137e91a54e1Sdan # after the attempt to write the database failed. 138e91a54e1Sdan # 139e91a54e1Sdan do_test pager1-$tn.14 { 140e91a54e1Sdan csql2 { BEGIN } 141e91a54e1Sdan } {1 {cannot start a transaction within a transaction}} 142e91a54e1Sdan do_test pager1-$tn.15 { sql2 { ROLLBACK } } {} 143e91a54e1Sdan 144e91a54e1Sdan # Have [db2] open a transaction and take a read-lock on the database. 145e91a54e1Sdan # Check that this prevents [db] from writing to the database (outside 146e91a54e1Sdan # of any transaction). After this fails, check that [db3] can read 147e91a54e1Sdan # the db (showing that [db] did not take a PENDING lock etc.) 148e91a54e1Sdan # 149e91a54e1Sdan do_test pager1-$tn.15 { 150e91a54e1Sdan sql2 { BEGIN; SELECT * FROM t1; } 151e91a54e1Sdan } {1 one 2 two 3 three} 152e91a54e1Sdan do_test pager1-$tn.16 { 153e91a54e1Sdan csql1 { UPDATE t1 SET a = a + 10 } 154e91a54e1Sdan } {1 {database is locked}} 155e91a54e1Sdan do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 156e91a54e1Sdan 157e91a54e1Sdan # This time, have [db] open a transaction before writing the database. 158e91a54e1Sdan # This works - [db] gets a RESERVED lock which does not conflict with 159e91a54e1Sdan # the SHARED lock [db2] is holding. 160e91a54e1Sdan # 161e91a54e1Sdan do_test pager1-$tn.18 { 162e91a54e1Sdan sql1 { 163e91a54e1Sdan BEGIN; 164e91a54e1Sdan UPDATE t1 SET a = a + 10; 165e91a54e1Sdan } 166e91a54e1Sdan } {} 167e91a54e1Sdan do_test pager1-$tn-19 { 168e91a54e1Sdan sql1 { PRAGMA lock_status } 169e91a54e1Sdan } {main reserved temp closed} 170e91a54e1Sdan do_test pager1-$tn-20 { 171e91a54e1Sdan sql2 { PRAGMA lock_status } 172e91a54e1Sdan } {main shared temp closed} 173e91a54e1Sdan 174e91a54e1Sdan # Check that all connections can still read the database. Only [db] sees 175e91a54e1Sdan # the updated content (as the transaction has not been committed yet). 176e91a54e1Sdan # 177e91a54e1Sdan do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} 178e91a54e1Sdan do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 179e91a54e1Sdan do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 180e91a54e1Sdan 181e91a54e1Sdan # Because [db2] still has the SHARED lock, [db] is unable to commit the 182e91a54e1Sdan # transaction. If it tries, an error is returned and the connection 183e91a54e1Sdan # upgrades to a PENDING lock. 184e91a54e1Sdan # 185e91a54e1Sdan # Once this happens, [db] can read the database and see the new content, 186e91a54e1Sdan # [db2] (still holding SHARED) can still read the old content, but [db3] 187e91a54e1Sdan # (not holding any lock) is prevented by [db]'s PENDING from reading 188e91a54e1Sdan # the database. 189e91a54e1Sdan # 190e91a54e1Sdan do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}} 191e91a54e1Sdan do_test pager1-$tn-25 { 192e91a54e1Sdan sql1 { PRAGMA lock_status } 193e91a54e1Sdan } {main pending temp closed} 194e91a54e1Sdan do_test pager1-$tn.26 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} 195e91a54e1Sdan do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 196e91a54e1Sdan do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} 197e91a54e1Sdan 198e91a54e1Sdan # Have [db2] commit its read transaction, releasing the SHARED lock it 199e91a54e1Sdan # is holding. Now, neither [db2] nor [db3] may read the database (as [db] 200e91a54e1Sdan # is still holding a PENDING). 201e91a54e1Sdan # 202e91a54e1Sdan do_test pager1-$tn.29 { sql2 { COMMIT } } {} 203e91a54e1Sdan do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}} 204e91a54e1Sdan do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} 205e91a54e1Sdan 206e91a54e1Sdan # [db] is now able to commit the transaction. Once the transaction is 207e91a54e1Sdan # committed, all three connections can read the new content. 208e91a54e1Sdan # 209e91a54e1Sdan do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {} 210e91a54e1Sdan do_test pager1-$tn.26 { sql1 { COMMIT } } {} 211e91a54e1Sdan do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three} 212e91a54e1Sdan do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three} 213e91a54e1Sdan do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three} 214d353331aSdan 215d353331aSdan # Install a busy-handler for connection [db]. 216d353331aSdan # 217d353331aSdan set ::nbusy [list] 218d353331aSdan proc busy {n} { 219d353331aSdan lappend ::nbusy $n 220d353331aSdan if {$n>5} { sql2 COMMIT } 221d353331aSdan return 0 222d353331aSdan } 223d353331aSdan db busy busy 224d353331aSdan 225d353331aSdan do_test pager1-$tn.29 { 226d353331aSdan sql1 { BEGIN ; INSERT INTO t1 VALUES('x', 'y') } 227d353331aSdan } {} 228d353331aSdan do_test pager1-$tn.30 { 229d353331aSdan sql2 { BEGIN ; SELECT * FROM t1 } 230d353331aSdan } {21 one 22 two 23 three} 231d353331aSdan do_test pager1-$tn.31 { sql1 COMMIT } {} 232d353331aSdan do_test pager1-$tn.32 { set ::nbusy } {0 1 2 3 4 5 6} 233e91a54e1Sdan} 234e91a54e1Sdan 23553f04f3bSdan#------------------------------------------------------------------------- 23653f04f3bSdan# Savepoint related test cases. 23753f04f3bSdan# 238dca321aeSdan# pager1-3.1.2.*: Force a savepoint rollback to cause the database file 239dca321aeSdan# to grow. 240dca321aeSdan# 241273f3f0dSdan# pager1-3.1.3.*: Use a journal created in synchronous=off mode as part 242273f3f0dSdan# of a savepoint rollback. 243273f3f0dSdan# 2440e986f51Sdando_test pager1-3.1.1 { 245b0ac3e3aSdan faultsim_delete_and_reopen 246b0ac3e3aSdan execsql { 247b0ac3e3aSdan CREATE TABLE t1(a PRIMARY KEY, b); 248b0ac3e3aSdan CREATE TABLE counter( 249b0ac3e3aSdan i CHECK (i<5), 250b0ac3e3aSdan u CHECK (u<10) 251b0ac3e3aSdan ); 252b0ac3e3aSdan INSERT INTO counter VALUES(0, 0); 253b0ac3e3aSdan CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN 254b0ac3e3aSdan UPDATE counter SET i = i+1; 255b0ac3e3aSdan END; 256b0ac3e3aSdan CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN 257b0ac3e3aSdan UPDATE counter SET u = u+1; 258b0ac3e3aSdan END; 259b0ac3e3aSdan } 260b0ac3e3aSdan execsql { SELECT * FROM counter } 261b0ac3e3aSdan} {0 0} 262b0ac3e3aSdan 2630e986f51Sdando_execsql_test pager1-3.1.2 { 264d353331aSdan PRAGMA cache_size = 10; 265b0ac3e3aSdan BEGIN; 266b0ac3e3aSdan INSERT INTO t1 VALUES(1, randomblob(1500)); 267b0ac3e3aSdan INSERT INTO t1 VALUES(2, randomblob(1500)); 268b0ac3e3aSdan INSERT INTO t1 VALUES(3, randomblob(1500)); 269b0ac3e3aSdan SELECT * FROM counter; 270b0ac3e3aSdan} {3 0} 2710e986f51Sdando_catchsql_test pager1-3.1.3 { 272b0ac3e3aSdan INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1 273b0ac3e3aSdan} {1 {constraint failed}} 274b0ac3e3aSdando_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0} 275b0ac3e3aSdando_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3} 276b0ac3e3aSdando_execsql_test pager1-3.6 { COMMIT } {} 277b0ac3e3aSdan 278273f3f0dSdanforeach {tn sql tcl} { 279d353331aSdan 7 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 0 } { 280273f3f0dSdan testvfs tv -default 1 281273f3f0dSdan tv devchar safe_append 282273f3f0dSdan } 283d353331aSdan 8 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 2 } { 284d353331aSdan testvfs tv -default 1 285d353331aSdan tv devchar sequential 286d353331aSdan } 287d353331aSdan 9 { PRAGMA synchronous = FULL } { } 288d353331aSdan 10 { PRAGMA synchronous = NORMAL } { } 289d353331aSdan 11 { PRAGMA synchronous = OFF } { } 290d353331aSdan 12 { PRAGMA synchronous = FULL ; PRAGMA fullfsync = 1 } { } 291d353331aSdan 13 { PRAGMA synchronous = FULL } { 292d353331aSdan testvfs tv -default 1 293d353331aSdan tv devchar sequential 294d353331aSdan } 2956b63ab47Sdan 14 { PRAGMA locking_mode = EXCLUSIVE } { 2966b63ab47Sdan } 297273f3f0dSdan} { 298273f3f0dSdan do_test pager1-3.$tn.1 { 299273f3f0dSdan eval $tcl 300dca321aeSdan faultsim_delete_and_reopen 301dca321aeSdan db func a_string a_string 302273f3f0dSdan execsql $sql 303dca321aeSdan execsql { 304dca321aeSdan PRAGMA auto_vacuum = 2; 305dca321aeSdan PRAGMA cache_size = 10; 306dca321aeSdan CREATE TABLE z(x INTEGER PRIMARY KEY, y); 307dca321aeSdan BEGIN; 308dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 309dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 2 310dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 4 311dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 8 312dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 16 313dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 32 314dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 64 315dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 128 316dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 256 317dca321aeSdan COMMIT; 318dca321aeSdan } 319dca321aeSdan execsql { PRAGMA auto_vacuum } 320dca321aeSdan } {2} 321273f3f0dSdan do_execsql_test pager1-3.$tn.2 { 322dca321aeSdan BEGIN; 323dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 324dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 325dca321aeSdan SAVEPOINT one; 326273f3f0dSdan UPDATE z SET y = NULL WHERE x>256; 327dca321aeSdan PRAGMA incremental_vacuum; 328dca321aeSdan SELECT count(*) FROM z WHERE x < 100; 329dca321aeSdan ROLLBACK TO one; 330dca321aeSdan COMMIT; 331dca321aeSdan } {99} 332dca321aeSdan 333273f3f0dSdan do_execsql_test pager1-3.$tn.3 { 334273f3f0dSdan BEGIN; 335273f3f0dSdan SAVEPOINT one; 336273f3f0dSdan UPDATE z SET y = y||x; 337273f3f0dSdan ROLLBACK TO one; 338273f3f0dSdan COMMIT; 339273f3f0dSdan SELECT count(*) FROM z; 340273f3f0dSdan } {258} 341273f3f0dSdan 342273f3f0dSdan do_execsql_test pager1-3.$tn.4 { 343273f3f0dSdan SAVEPOINT one; 344273f3f0dSdan UPDATE z SET y = y||x; 345273f3f0dSdan ROLLBACK TO one; 346273f3f0dSdan } {} 347273f3f0dSdan do_execsql_test pager1-3.$tn.5 { 348273f3f0dSdan SELECT count(*) FROM z; 349273f3f0dSdan RELEASE one; 350273f3f0dSdan PRAGMA integrity_check; 351273f3f0dSdan } {258 ok} 352273f3f0dSdan 35378f1e538Sdan do_execsql_test pager1-3.$tn.6 { 35478f1e538Sdan SAVEPOINT one; 35578f1e538Sdan RELEASE one; 35678f1e538Sdan } {} 35778f1e538Sdan 358273f3f0dSdan db close 359273f3f0dSdan catch { tv delete } 360273f3f0dSdan} 361273f3f0dSdan 36253f04f3bSdan#------------------------------------------------------------------------- 36353f04f3bSdan# Hot journal rollback related test cases. 36453f04f3bSdan# 36553f04f3bSdan# pager1.4.1.*: Test that the pager module deletes very small invalid 36653f04f3bSdan# journal files. 36753f04f3bSdan# 36853f04f3bSdan# pager1.4.2.*: Test that if the master journal pointer at the end of a 36953f04f3bSdan# hot-journal file appears to be corrupt (checksum does not 37053f04f3bSdan# compute) the associated journal is rolled back (and no 37153f04f3bSdan# xAccess() call to check for the presence of any master 37253f04f3bSdan# journal file is made). 37353f04f3bSdan# 374de4996e2Sdan# pager1.4.3.*: Test that the contents of a hot-journal are ignored if the 375de4996e2Sdan# page-size or sector-size in the journal header appear to 376de4996e2Sdan# be invalid (too large, too small or not a power of 2). 377de4996e2Sdan# 378e08341c6Sdan# pager1.4.4.*: Test hot-journal rollback of journal file with a master 379e08341c6Sdan# journal pointer generated in various "PRAGMA synchronous" 380e08341c6Sdan# modes. 381e08341c6Sdan# 382e08341c6Sdan# pager1.4.5.*: Test that hot-journal rollback stops if it encounters a 383e08341c6Sdan# journal-record for which the checksum fails. 384e08341c6Sdan# 385ec6ffc1aSdan# pager1.4.6.*: Test that when rolling back a hot-journal that contains a 386ec6ffc1aSdan# master journal pointer, the master journal file is deleted 387ec6ffc1aSdan# after all the hot-journals that refer to it are deleted. 388ec6ffc1aSdan# 389c8ce3972Sdan# pager1.4.7.*: Test that if a hot-journal file exists but a client can 390c8ce3972Sdan# open it for reading only, the database cannot be accessed and 391c8ce3972Sdan# SQLITE_CANTOPEN is returned. 392c8ce3972Sdan# 39353f04f3bSdando_test pager1.4.1.1 { 39453f04f3bSdan faultsim_delete_and_reopen 39553f04f3bSdan execsql { 39653f04f3bSdan CREATE TABLE x(y, z); 39753f04f3bSdan INSERT INTO x VALUES(1, 2); 39853f04f3bSdan } 39953f04f3bSdan set fd [open test.db-journal w] 40053f04f3bSdan puts -nonewline $fd "helloworld" 40153f04f3bSdan close $fd 40253f04f3bSdan file exists test.db-journal 40353f04f3bSdan} {1} 40453f04f3bSdando_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2} 40553f04f3bSdando_test pager1.4.1.3 { file exists test.db-journal } {0} 40653f04f3bSdan 40753f04f3bSdan# Set up a [testvfs] to snapshot the file-system just before SQLite 40853f04f3bSdan# deletes the master-journal to commit a multi-file transaction. 40953f04f3bSdan# 41053f04f3bSdan# In subsequent test cases, invoking [faultsim_restore_and_reopen] sets 41153f04f3bSdan# up the file system to contain two databases, two hot-journal files and 41253f04f3bSdan# a master-journal. 41353f04f3bSdan# 41453f04f3bSdando_test pager1.4.2.1 { 41553f04f3bSdan testvfs tstvfs -default 1 41653f04f3bSdan tstvfs filter xDelete 41753f04f3bSdan tstvfs script xDeleteCallback 41853f04f3bSdan proc xDeleteCallback {method file args} { 41953f04f3bSdan set file [file tail $file] 42053f04f3bSdan if { [string match *mj* $file] } { faultsim_save } 42153f04f3bSdan } 42253f04f3bSdan faultsim_delete_and_reopen 42353f04f3bSdan db func a_string a_string 42453f04f3bSdan execsql { 42553f04f3bSdan ATTACH 'test.db2' AS aux; 42653f04f3bSdan PRAGMA journal_mode = DELETE; 42753f04f3bSdan PRAGMA main.cache_size = 10; 42853f04f3bSdan PRAGMA aux.cache_size = 10; 42953f04f3bSdan CREATE TABLE t1(a UNIQUE, b UNIQUE); 43053f04f3bSdan CREATE TABLE aux.t2(a UNIQUE, b UNIQUE); 43153f04f3bSdan INSERT INTO t1 VALUES(a_string(200), a_string(300)); 43253f04f3bSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 43353f04f3bSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 43453f04f3bSdan INSERT INTO t2 SELECT * FROM t1; 43553f04f3bSdan BEGIN; 43653f04f3bSdan INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1; 43753f04f3bSdan INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1; 43853f04f3bSdan INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1; 43953f04f3bSdan INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1; 44053f04f3bSdan REPLACE INTO t2 SELECT * FROM t1; 44153f04f3bSdan COMMIT; 44253f04f3bSdan } 44353f04f3bSdan db close 44453f04f3bSdan tstvfs delete 44553f04f3bSdan} {} 446b2f20bfcSshaneh 447b2f20bfcSshanehif {$::tcl_platform(platform)!="windows"} { 44853f04f3bSdando_test pager1.4.2.2 { 44953f04f3bSdan faultsim_restore_and_reopen 45053f04f3bSdan execsql { 45153f04f3bSdan SELECT count(*) FROM t1; 45253f04f3bSdan PRAGMA integrity_check; 45353f04f3bSdan } 45453f04f3bSdan} {4 ok} 45553f04f3bSdando_test pager1.4.2.3 { 45653f04f3bSdan faultsim_restore_and_reopen 457fda06befSmistachkin foreach f [glob test.db-mj*] { forcedelete $f } 45853f04f3bSdan execsql { 45953f04f3bSdan SELECT count(*) FROM t1; 46053f04f3bSdan PRAGMA integrity_check; 46153f04f3bSdan } 46253f04f3bSdan} {64 ok} 46353f04f3bSdando_test pager1.4.2.4 { 46453f04f3bSdan faultsim_restore_and_reopen 4650971140bSdrh hexio_write test.db-journal [expr [file size test.db-journal]-30] 123456 46653f04f3bSdan execsql { 46753f04f3bSdan SELECT count(*) FROM t1; 46853f04f3bSdan PRAGMA integrity_check; 46953f04f3bSdan } 47053f04f3bSdan} {4 ok} 47153f04f3bSdando_test pager1.4.2.5 { 47253f04f3bSdan faultsim_restore_and_reopen 4730971140bSdrh hexio_write test.db-journal [expr [file size test.db-journal]-30] 123456 474fda06befSmistachkin foreach f [glob test.db-mj*] { forcedelete $f } 47553f04f3bSdan execsql { 47653f04f3bSdan SELECT count(*) FROM t1; 47753f04f3bSdan PRAGMA integrity_check; 47853f04f3bSdan } 47953f04f3bSdan} {4 ok} 480b2f20bfcSshaneh} 48153f04f3bSdan 482de4996e2Sdando_test pager1.4.3.1 { 483de4996e2Sdan testvfs tstvfs -default 1 484de4996e2Sdan tstvfs filter xSync 485de4996e2Sdan tstvfs script xSyncCallback 486de4996e2Sdan proc xSyncCallback {method file args} { 487de4996e2Sdan set file [file tail $file] 488de4996e2Sdan if { 0==[string match *journal $file] } { faultsim_save } 489de4996e2Sdan } 490de4996e2Sdan faultsim_delete_and_reopen 491de4996e2Sdan execsql { 492de4996e2Sdan PRAGMA journal_mode = DELETE; 493de4996e2Sdan CREATE TABLE t1(a, b); 494de4996e2Sdan INSERT INTO t1 VALUES(1, 2); 495de4996e2Sdan INSERT INTO t1 VALUES(3, 4); 496de4996e2Sdan } 497de4996e2Sdan db close 498de4996e2Sdan tstvfs delete 499de4996e2Sdan} {} 500de4996e2Sdan 501de4996e2Sdanforeach {tn ofst value result} { 502de4996e2Sdan 2 20 31 {1 2 3 4} 503de4996e2Sdan 3 20 32 {1 2 3 4} 504de4996e2Sdan 4 20 33 {1 2 3 4} 505de4996e2Sdan 5 20 65536 {1 2 3 4} 506de4996e2Sdan 6 20 131072 {1 2 3 4} 507de4996e2Sdan 508de4996e2Sdan 7 24 511 {1 2 3 4} 509de4996e2Sdan 8 24 513 {1 2 3 4} 510b2eced5dSdrh 9 24 131072 {1 2 3 4} 511de4996e2Sdan 512de4996e2Sdan 10 32 65536 {1 2} 513de4996e2Sdan} { 514de4996e2Sdan do_test pager1.4.3.$tn { 515de4996e2Sdan faultsim_restore_and_reopen 516de4996e2Sdan hexio_write test.db-journal $ofst [format %.8x $value] 517de4996e2Sdan execsql { SELECT * FROM t1 } 518de4996e2Sdan } $result 519de4996e2Sdan} 520de4996e2Sdandb close 521de4996e2Sdan 522e08341c6Sdan# Set up a VFS that snapshots the file-system just before a master journal 523e08341c6Sdan# file is deleted to commit a multi-file transaction. Specifically, the 524e08341c6Sdan# file-system is saved just before the xDelete() call to remove the 525e08341c6Sdan# master journal file from the file-system. 526e08341c6Sdan# 5276aa18c95Smistachkinset pwd [get_pwd] 528e08341c6Sdantestvfs tv -default 1 529e08341c6Sdantv script copy_on_mj_delete 530e08341c6Sdanset ::mj_filename_length 0 531e08341c6Sdanproc copy_on_mj_delete {method filename args} { 532e08341c6Sdan if {[string match *mj* [file tail $filename]]} { 533c5484654Smistachkin # 534c5484654Smistachkin # NOTE: Is the file name relative? If so, add the length of the current 535c5484654Smistachkin # directory. 536c5484654Smistachkin # 537c5484654Smistachkin if {[is_relative_file $filename]} { 538c5484654Smistachkin set ::mj_filename_length \ 539c5484654Smistachkin [expr {[string length $filename] + [string length $::pwd]}] 540c5484654Smistachkin } else { 541e08341c6Sdan set ::mj_filename_length [string length $filename] 542c5484654Smistachkin } 543e08341c6Sdan faultsim_save 544e08341c6Sdan } 545e08341c6Sdan return SQLITE_OK 546e08341c6Sdan} 547e08341c6Sdan 548e08341c6Sdanforeach {tn1 tcl} { 549e08341c6Sdan 1 { set prefix "test.db" } 550e08341c6Sdan 2 { 551e08341c6Sdan # This test depends on the underlying VFS being able to open paths 552e08341c6Sdan # 512 bytes in length. The idea is to create a hot-journal file that 553e08341c6Sdan # contains a master-journal pointer so large that it could contain 554e08341c6Sdan # a valid page record (if the file page-size is 512 bytes). So as to 555e08341c6Sdan # make sure SQLite doesn't get confused by this. 556e08341c6Sdan # 557e08341c6Sdan set nPadding [expr 511 - $::mj_filename_length] 55833d85c9cSshaneh if {$tcl_platform(platform)=="windows"} { 55933d85c9cSshaneh # TBD need to figure out how to do this correctly for Windows!!! 56033d85c9cSshaneh set nPadding [expr 255 - $::mj_filename_length] 56133d85c9cSshaneh } 562e08341c6Sdan 563e08341c6Sdan # We cannot just create a really long database file name to open, as 564e08341c6Sdan # Linux limits a single component of a path to 255 bytes by default 565e08341c6Sdan # (and presumably other systems have limits too). So create a directory 566e08341c6Sdan # hierarchy to work in. 567e08341c6Sdan # 568e08341c6Sdan set dirname "d123456789012345678901234567890/" 569e08341c6Sdan set nDir [expr $nPadding / 32] 570e08341c6Sdan if { $nDir } { 571e08341c6Sdan set p [string repeat $dirname $nDir] 572e08341c6Sdan file mkdir $p 573e08341c6Sdan cd $p 574e08341c6Sdan } 575e08341c6Sdan 576e08341c6Sdan set padding [string repeat x [expr $nPadding %32]] 577e08341c6Sdan set prefix "test.db${padding}" 578e08341c6Sdan } 579e08341c6Sdan} { 580e08341c6Sdan eval $tcl 581e08341c6Sdan foreach {tn2 sql} { 582e08341c6Sdan o { 583e08341c6Sdan PRAGMA main.synchronous=OFF; 584e08341c6Sdan PRAGMA aux.synchronous=OFF; 5853f94b609Sdan PRAGMA journal_mode = DELETE; 586e08341c6Sdan } 587e08341c6Sdan o512 { 588e08341c6Sdan PRAGMA main.synchronous=OFF; 589e08341c6Sdan PRAGMA aux.synchronous=OFF; 590e08341c6Sdan PRAGMA main.page_size = 512; 591e08341c6Sdan PRAGMA aux.page_size = 512; 5923f94b609Sdan PRAGMA journal_mode = DELETE; 593e08341c6Sdan } 594e08341c6Sdan n { 595e08341c6Sdan PRAGMA main.synchronous=NORMAL; 596e08341c6Sdan PRAGMA aux.synchronous=NORMAL; 5973f94b609Sdan PRAGMA journal_mode = DELETE; 598e08341c6Sdan } 599e08341c6Sdan f { 600e08341c6Sdan PRAGMA main.synchronous=FULL; 601e08341c6Sdan PRAGMA aux.synchronous=FULL; 6023f94b609Sdan PRAGMA journal_mode = DELETE; 603e08341c6Sdan } 604e08341c6Sdan } { 605e08341c6Sdan 606e08341c6Sdan set tn "${tn1}.${tn2}" 607e08341c6Sdan 608e08341c6Sdan # Set up a connection to have two databases, test.db (main) and 609e08341c6Sdan # test.db2 (aux). Then run a multi-file transaction on them. The 610e08341c6Sdan # VFS will snapshot the file-system just before the master-journal 611e08341c6Sdan # file is deleted to commit the transaction. 612e08341c6Sdan # 613e08341c6Sdan tv filter xDelete 614e08341c6Sdan do_test pager1-4.4.$tn.1 { 615e08341c6Sdan faultsim_delete_and_reopen $prefix 616e08341c6Sdan execsql " 617e08341c6Sdan ATTACH '${prefix}2' AS aux; 618e08341c6Sdan $sql 619e08341c6Sdan CREATE TABLE a(x); 620e08341c6Sdan CREATE TABLE aux.b(x); 621e08341c6Sdan INSERT INTO a VALUES('double-you'); 622e08341c6Sdan INSERT INTO a VALUES('why'); 623e08341c6Sdan INSERT INTO a VALUES('zed'); 624e08341c6Sdan INSERT INTO b VALUES('won'); 625e08341c6Sdan INSERT INTO b VALUES('too'); 626e08341c6Sdan INSERT INTO b VALUES('free'); 627e08341c6Sdan " 628e08341c6Sdan execsql { 629e08341c6Sdan BEGIN; 630e08341c6Sdan INSERT INTO a SELECT * FROM b WHERE rowid<=3; 631e08341c6Sdan INSERT INTO b SELECT * FROM a WHERE rowid<=3; 632e08341c6Sdan COMMIT; 633e08341c6Sdan } 634e08341c6Sdan } {} 635e08341c6Sdan tv filter {} 636e08341c6Sdan 637e08341c6Sdan # Check that the transaction was committed successfully. 638e08341c6Sdan # 639e08341c6Sdan do_execsql_test pager1-4.4.$tn.2 { 640e08341c6Sdan SELECT * FROM a 641e08341c6Sdan } {double-you why zed won too free} 642e08341c6Sdan do_execsql_test pager1-4.4.$tn.3 { 643e08341c6Sdan SELECT * FROM b 644e08341c6Sdan } {won too free double-you why zed} 645e08341c6Sdan 646e08341c6Sdan # Restore the file-system and reopen the databases. Check that it now 647e08341c6Sdan # appears that the transaction was not committed (because the file-system 648e08341c6Sdan # was restored to the state where it had not been). 649e08341c6Sdan # 650e08341c6Sdan do_test pager1-4.4.$tn.4 { 651e08341c6Sdan faultsim_restore_and_reopen $prefix 652e08341c6Sdan execsql "ATTACH '${prefix}2' AS aux" 653e08341c6Sdan } {} 654e08341c6Sdan do_execsql_test pager1-4.4.$tn.5 {SELECT * FROM a} {double-you why zed} 655e08341c6Sdan do_execsql_test pager1-4.4.$tn.6 {SELECT * FROM b} {won too free} 656e08341c6Sdan 657e08341c6Sdan # Restore the file-system again. This time, before reopening the databases, 658e08341c6Sdan # delete the master-journal file from the file-system. It now appears that 659e08341c6Sdan # the transaction was committed (no master-journal file == no rollback). 660e08341c6Sdan # 661e08341c6Sdan do_test pager1-4.4.$tn.7 { 662e08341c6Sdan faultsim_restore_and_reopen $prefix 663fda06befSmistachkin foreach f [glob ${prefix}-mj*] { forcedelete $f } 664e08341c6Sdan execsql "ATTACH '${prefix}2' AS aux" 665e08341c6Sdan } {} 666e08341c6Sdan do_execsql_test pager1-4.4.$tn.8 { 667e08341c6Sdan SELECT * FROM a 668e08341c6Sdan } {double-you why zed won too free} 669e08341c6Sdan do_execsql_test pager1-4.4.$tn.9 { 670e08341c6Sdan SELECT * FROM b 671e08341c6Sdan } {won too free double-you why zed} 672e08341c6Sdan } 673e08341c6Sdan 674e08341c6Sdan cd $pwd 675e08341c6Sdan} 676e08341c6Sdandb close 677e08341c6Sdantv delete 678fda06befSmistachkinforcedelete $dirname 6790e986f51Sdan 6800e986f51Sdan 6810e986f51Sdan# Set up a VFS to make a copy of the file-system just before deleting a 6820e986f51Sdan# journal file to commit a transaction. The transaction modifies exactly 6830e986f51Sdan# two database pages (and page 1 - the change counter). 6840e986f51Sdan# 6850e986f51Sdantestvfs tv -default 1 6860e986f51Sdantv sectorsize 512 6870e986f51Sdantv script copy_on_journal_delete 6880e986f51Sdantv filter xDelete 6890e986f51Sdanproc copy_on_journal_delete {method filename args} { 6900e986f51Sdan if {[string match *journal $filename]} faultsim_save 6910e986f51Sdan return SQLITE_OK 6920e986f51Sdan} 6930e986f51Sdanfaultsim_delete_and_reopen 6940e986f51Sdando_execsql_test pager1.4.5.1 { 6953f94b609Sdan PRAGMA journal_mode = DELETE; 6960e986f51Sdan PRAGMA page_size = 1024; 6970e986f51Sdan CREATE TABLE t1(a, b); 6980e986f51Sdan CREATE TABLE t2(a, b); 6990e986f51Sdan INSERT INTO t1 VALUES('I', 'II'); 7000e986f51Sdan INSERT INTO t2 VALUES('III', 'IV'); 7010e986f51Sdan BEGIN; 7020e986f51Sdan INSERT INTO t1 VALUES(1, 2); 7030e986f51Sdan INSERT INTO t2 VALUES(3, 4); 7040e986f51Sdan COMMIT; 7053f94b609Sdan} {delete} 7060e986f51Sdantv filter {} 7070e986f51Sdan 7080e986f51Sdan# Check the transaction was committed: 7090e986f51Sdan# 7100e986f51Sdando_execsql_test pager1.4.5.2 { 7110e986f51Sdan SELECT * FROM t1; 7120e986f51Sdan SELECT * FROM t2; 7130e986f51Sdan} {I II 1 2 III IV 3 4} 7140e986f51Sdan 715ec6ffc1aSdan# Now try four tests: 7160e986f51Sdan# 7170e986f51Sdan# pager1-4.5.3: Restore the file-system. Check that the whole transaction 7180e986f51Sdan# is rolled back. 7190e986f51Sdan# 7200e986f51Sdan# pager1-4.5.4: Restore the file-system. Corrupt the first record in the 7210e986f51Sdan# journal. Check the transaction is not rolled back. 7220e986f51Sdan# 7230e986f51Sdan# pager1-4.5.5: Restore the file-system. Corrupt the second record in the 7240e986f51Sdan# journal. Check that the first record in the transaction is 7250e986f51Sdan# played back, but not the second. 7260e986f51Sdan# 72710f5a50eSdan# pager1-4.5.6: Restore the file-system. Try to open the database with a 72810f5a50eSdan# readonly connection. This should fail, as a read-only 72910f5a50eSdan# connection cannot roll back the database file. 73010f5a50eSdan# 7310e986f51Sdanfaultsim_restore_and_reopen 7320e986f51Sdando_execsql_test pager1.4.5.3 { 7330e986f51Sdan SELECT * FROM t1; 7340e986f51Sdan SELECT * FROM t2; 7350e986f51Sdan} {I II III IV} 7360e986f51Sdanfaultsim_restore_and_reopen 7370e986f51Sdanhexio_write test.db-journal [expr 512+4+1024 - 202] 0123456789ABCDEF 7380e986f51Sdando_execsql_test pager1.4.5.4 { 7390e986f51Sdan SELECT * FROM t1; 7400e986f51Sdan SELECT * FROM t2; 7410e986f51Sdan} {I II 1 2 III IV 3 4} 7420e986f51Sdanfaultsim_restore_and_reopen 7430e986f51Sdanhexio_write test.db-journal [expr 512+4+1024+4+4+1024 - 202] 0123456789ABCDEF 7440e986f51Sdando_execsql_test pager1.4.5.5 { 7450e986f51Sdan SELECT * FROM t1; 7460e986f51Sdan SELECT * FROM t2; 7470e986f51Sdan} {I II III IV 3 4} 7480e986f51Sdan 74910f5a50eSdanfaultsim_restore_and_reopen 75010f5a50eSdandb close 75110f5a50eSdansqlite3 db test.db -readonly 1 75210f5a50eSdando_catchsql_test pager1.4.5.6 { 75310f5a50eSdan SELECT * FROM t1; 75410f5a50eSdan SELECT * FROM t2; 75510f5a50eSdan} {1 {disk I/O error}} 756ec6ffc1aSdandb close 757ec6ffc1aSdan 758ec6ffc1aSdan# Snapshot the file-system just before multi-file commit. Save the name 759ec6ffc1aSdan# of the master journal file in $::mj_filename. 760ec6ffc1aSdan# 761ec6ffc1aSdantv script copy_on_mj_delete 762ec6ffc1aSdantv filter xDelete 763ec6ffc1aSdanproc copy_on_mj_delete {method filename args} { 764ec6ffc1aSdan if {[string match *mj* [file tail $filename]]} { 765ec6ffc1aSdan set ::mj_filename $filename 766ec6ffc1aSdan faultsim_save 767ec6ffc1aSdan } 768ec6ffc1aSdan return SQLITE_OK 769ec6ffc1aSdan} 770ec6ffc1aSdando_test pager1.4.6.1 { 771ec6ffc1aSdan faultsim_delete_and_reopen 772ec6ffc1aSdan execsql { 7733f94b609Sdan PRAGMA journal_mode = DELETE; 774ec6ffc1aSdan ATTACH 'test.db2' AS two; 775ec6ffc1aSdan CREATE TABLE t1(a, b); 776ec6ffc1aSdan CREATE TABLE two.t2(a, b); 777ec6ffc1aSdan INSERT INTO t1 VALUES(1, 't1.1'); 778ec6ffc1aSdan INSERT INTO t2 VALUES(1, 't2.1'); 779ec6ffc1aSdan BEGIN; 780ec6ffc1aSdan UPDATE t1 SET b = 't1.2'; 781ec6ffc1aSdan UPDATE t2 SET b = 't2.2'; 782ec6ffc1aSdan COMMIT; 783ec6ffc1aSdan } 784ec6ffc1aSdan tv filter {} 785ec6ffc1aSdan db close 786ec6ffc1aSdan} {} 787ec6ffc1aSdan 788ec6ffc1aSdanfaultsim_restore_and_reopen 789ec6ffc1aSdando_execsql_test pager1.4.6.2 { SELECT * FROM t1 } {1 t1.1} 790ec6ffc1aSdando_test pager1.4.6.3 { file exists $::mj_filename } {1} 791ec6ffc1aSdando_execsql_test pager1.4.6.4 { 792ec6ffc1aSdan ATTACH 'test.db2' AS two; 793ec6ffc1aSdan SELECT * FROM t2; 794ec6ffc1aSdan} {1 t2.1} 795ec6ffc1aSdando_test pager1.4.6.5 { file exists $::mj_filename } {0} 796ec6ffc1aSdan 797ec6ffc1aSdanfaultsim_restore_and_reopen 798ec6ffc1aSdandb close 799ec6ffc1aSdando_test pager1.4.6.8 { 800ec6ffc1aSdan set ::mj_filename1 $::mj_filename 801ec6ffc1aSdan tv filter xDelete 802ec6ffc1aSdan sqlite3 db test.db2 803ec6ffc1aSdan execsql { 8043f94b609Sdan PRAGMA journal_mode = DELETE; 805ec6ffc1aSdan ATTACH 'test.db3' AS three; 806ec6ffc1aSdan CREATE TABLE three.t3(a, b); 807ec6ffc1aSdan INSERT INTO t3 VALUES(1, 't3.1'); 808ec6ffc1aSdan BEGIN; 809ec6ffc1aSdan UPDATE t2 SET b = 't2.3'; 810ec6ffc1aSdan UPDATE t3 SET b = 't3.3'; 811ec6ffc1aSdan COMMIT; 812ec6ffc1aSdan } 813ec6ffc1aSdan expr {$::mj_filename1 != $::mj_filename} 814ec6ffc1aSdan} {1} 815ec6ffc1aSdanfaultsim_restore_and_reopen 816ec6ffc1aSdantv filter {} 817ec6ffc1aSdan 818ec6ffc1aSdan# The file-system now contains: 819ec6ffc1aSdan# 820ec6ffc1aSdan# * three databases 821ec6ffc1aSdan# * three hot-journal files 822ec6ffc1aSdan# * two master-journal files. 823ec6ffc1aSdan# 824ec6ffc1aSdan# The hot-journals associated with test.db2 and test.db3 point to 825ec6ffc1aSdan# master journal $::mj_filename. The hot-journal file associated with 826ec6ffc1aSdan# test.db points to master journal $::mj_filename1. So reading from 827ec6ffc1aSdan# test.db should delete $::mj_filename1. 828ec6ffc1aSdan# 829ec6ffc1aSdando_test pager1.4.6.9 { 830ec6ffc1aSdan lsort [glob test.db*] 831ec6ffc1aSdan} [lsort [list \ 832ec6ffc1aSdan test.db test.db2 test.db3 \ 833ec6ffc1aSdan test.db-journal test.db2-journal test.db3-journal \ 834ec6ffc1aSdan [file tail $::mj_filename] [file tail $::mj_filename1] 835ec6ffc1aSdan]] 836ec6ffc1aSdan 837ec6ffc1aSdan# The master-journal $::mj_filename1 contains pointers to test.db and 838ec6ffc1aSdan# test.db2. However the hot-journal associated with test.db2 points to 839ec6ffc1aSdan# a different master-journal. Therefore, reading from test.db only should 840ec6ffc1aSdan# be enough to cause SQLite to delete $::mj_filename1. 841ec6ffc1aSdan# 842ec6ffc1aSdando_test pager1.4.6.10 { file exists $::mj_filename } {1} 843ec6ffc1aSdando_test pager1.4.6.11 { file exists $::mj_filename1 } {1} 844ec6ffc1aSdando_execsql_test pager1.4.6.12 { SELECT * FROM t1 } {1 t1.1} 845ec6ffc1aSdando_test pager1.4.6.13 { file exists $::mj_filename } {1} 846ec6ffc1aSdando_test pager1.4.6.14 { file exists $::mj_filename1 } {0} 847ec6ffc1aSdan 848ec6ffc1aSdando_execsql_test pager1.4.6.12 { 849ec6ffc1aSdan ATTACH 'test.db2' AS two; 850ec6ffc1aSdan SELECT * FROM t2; 851ec6ffc1aSdan} {1 t2.1} 852ec6ffc1aSdando_test pager1.4.6.13 { file exists $::mj_filename } {1} 853ec6ffc1aSdando_execsql_test pager1.4.6.14 { 854ec6ffc1aSdan ATTACH 'test.db3' AS three; 855ec6ffc1aSdan SELECT * FROM t3; 856ec6ffc1aSdan} {1 t3.1} 857ec6ffc1aSdando_test pager1.4.6.15 { file exists $::mj_filename } {0} 85810f5a50eSdan 8590e986f51Sdandb close 8600e986f51Sdantv delete 861e08341c6Sdan 862c8ce3972Sdantestvfs tv -default 1 863c8ce3972Sdantv sectorsize 512 864c8ce3972Sdantv script copy_on_journal_delete 865c8ce3972Sdantv filter xDelete 866c8ce3972Sdanproc copy_on_journal_delete {method filename args} { 867c8ce3972Sdan if {[string match *journal $filename]} faultsim_save 868c8ce3972Sdan return SQLITE_OK 869c8ce3972Sdan} 870c8ce3972Sdanfaultsim_delete_and_reopen 871c8ce3972Sdando_execsql_test pager1.4.7.1 { 8723f94b609Sdan PRAGMA journal_mode = DELETE; 873c8ce3972Sdan CREATE TABLE t1(x PRIMARY KEY, y); 874c8ce3972Sdan CREATE INDEX i1 ON t1(y); 875c8ce3972Sdan INSERT INTO t1 VALUES('I', 'one'); 876c8ce3972Sdan INSERT INTO t1 VALUES('II', 'four'); 877c8ce3972Sdan INSERT INTO t1 VALUES('III', 'nine'); 878c8ce3972Sdan BEGIN; 879c8ce3972Sdan INSERT INTO t1 VALUES('IV', 'sixteen'); 880c8ce3972Sdan INSERT INTO t1 VALUES('V' , 'twentyfive'); 881c8ce3972Sdan COMMIT; 8823f94b609Sdan} {delete} 883c8ce3972Sdantv filter {} 884c8ce3972Sdandb close 885c8ce3972Sdantv delete 886*e1186ab2Sdrhcatch { 887*e1186ab2Sdrh test_syscall install fchmod 888*e1186ab2Sdrh test_syscall fault 1 1 889*e1186ab2Sdrh} 890c8ce3972Sdando_test pager1.4.7.2 { 891c8ce3972Sdan faultsim_restore_and_reopen 892c8ce3972Sdan catch {file attributes test.db-journal -permissions r--------} 893c8ce3972Sdan catch {file attributes test.db-journal -readonly 1} 894c8ce3972Sdan catchsql { SELECT * FROM t1 } 895c8ce3972Sdan} {1 {unable to open database file}} 896*e1186ab2Sdrhcatch { 897*e1186ab2Sdrh test_syscall reset 898*e1186ab2Sdrh test_syscall fault 0 0 899*e1186ab2Sdrh} 900c8ce3972Sdando_test pager1.4.7.3 { 901c8ce3972Sdan db close 902c8ce3972Sdan catch {file attributes test.db-journal -permissions rw-rw-rw-} 903c8ce3972Sdan catch {file attributes test.db-journal -readonly 0} 904fda06befSmistachkin delete_file test.db-journal 905c8ce3972Sdan file exists test.db-journal 906c8ce3972Sdan} {0} 907421377e6Sdrhdo_test pager1.4.8.1 { 908421377e6Sdrh catch {file attributes test.db -permissions r--------} 909421377e6Sdrh catch {file attributes test.db -readonly 1} 910421377e6Sdrh sqlite3 db test.db 911421377e6Sdrh db eval { SELECT * FROM t1 } 912421377e6Sdrh sqlite3_db_readonly db main 913421377e6Sdrh} {1} 914421377e6Sdrhdo_test pager1.4.8.2 { 915421377e6Sdrh sqlite3_db_readonly db xyz 916421377e6Sdrh} {-1} 917421377e6Sdrhdo_test pager1.4.8.3 { 918421377e6Sdrh db close 919421377e6Sdrh catch {file attributes test.db -readonly 0} 920db0ad5f2Sdan catch {file attributes test.db -permissions rw-rw-rw-} msg 921421377e6Sdrh sqlite3 db test.db 922421377e6Sdrh db eval { SELECT * FROM t1 } 923421377e6Sdrh sqlite3_db_readonly db main 924421377e6Sdrh} {0} 925c8ce3972Sdan 926de4996e2Sdan#------------------------------------------------------------------------- 927146ed78bSdan# The following tests deal with multi-file commits. 928de4996e2Sdan# 929146ed78bSdan# pager1-5.1.*: The case where a multi-file cannot be committed because 930146ed78bSdan# another connection is holding a SHARED lock on one of the 931146ed78bSdan# files. After the SHARED lock is removed, the COMMIT succeeds. 932146ed78bSdan# 933146ed78bSdan# pager1-5.2.*: Multi-file commits with journal_mode=memory. 934146ed78bSdan# 935146ed78bSdan# pager1-5.3.*: Multi-file commits with journal_mode=memory. 936146ed78bSdan# 937146ed78bSdan# pager1-5.4.*: Check that with synchronous=normal, the master-journal file 938146ed78bSdan# name is added to a journal file immediately after the last 939146ed78bSdan# journal record. But with synchronous=full, extra unused space 940146ed78bSdan# is allocated between the last journal record and the 941146ed78bSdan# master-journal file name so that the master-journal file 942146ed78bSdan# name does not lie on the same sector as the last journal file 943146ed78bSdan# record. 944146ed78bSdan# 945e08341c6Sdan# pager1-5.5.*: Check that in journal_mode=PERSIST mode, a journal file is 946e08341c6Sdan# truncated to zero bytes when a multi-file transaction is 947e08341c6Sdan# committed (instead of the first couple of bytes being zeroed). 948e08341c6Sdan# 949146ed78bSdan# 950146ed78bSdando_test pager1-5.1.1 { 951146ed78bSdan faultsim_delete_and_reopen 952146ed78bSdan execsql { 953146ed78bSdan ATTACH 'test.db2' AS aux; 954146ed78bSdan CREATE TABLE t1(a, b); 955146ed78bSdan CREATE TABLE aux.t2(a, b); 956146ed78bSdan INSERT INTO t1 VALUES(17, 'Lenin'); 957146ed78bSdan INSERT INTO t1 VALUES(22, 'Stalin'); 958146ed78bSdan INSERT INTO t1 VALUES(53, 'Khrushchev'); 959146ed78bSdan } 960146ed78bSdan} {} 961146ed78bSdando_test pager1-5.1.2 { 962146ed78bSdan execsql { 963146ed78bSdan BEGIN; 964146ed78bSdan INSERT INTO t1 VALUES(64, 'Brezhnev'); 965146ed78bSdan INSERT INTO t2 SELECT * FROM t1; 966146ed78bSdan } 967146ed78bSdan sqlite3 db2 test.db2 968146ed78bSdan execsql { 969146ed78bSdan BEGIN; 970146ed78bSdan SELECT * FROM t2; 971146ed78bSdan } db2 972146ed78bSdan} {} 973146ed78bSdando_test pager1-5.1.3 { 974146ed78bSdan catchsql COMMIT 975146ed78bSdan} {1 {database is locked}} 976146ed78bSdando_test pager1-5.1.4 { 977146ed78bSdan execsql COMMIT db2 978146ed78bSdan execsql COMMIT 979146ed78bSdan execsql { SELECT * FROM t2 } db2 980146ed78bSdan} {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev} 981146ed78bSdando_test pager1-5.1.5 { 982146ed78bSdan db2 close 983146ed78bSdan} {} 984146ed78bSdan 985146ed78bSdando_test pager1-5.2.1 { 986146ed78bSdan execsql { 987146ed78bSdan PRAGMA journal_mode = memory; 988146ed78bSdan BEGIN; 989146ed78bSdan INSERT INTO t1 VALUES(84, 'Andropov'); 990146ed78bSdan INSERT INTO t2 VALUES(84, 'Andropov'); 991146ed78bSdan COMMIT; 992146ed78bSdan } 993146ed78bSdan} {memory} 994146ed78bSdando_test pager1-5.3.1 { 995146ed78bSdan execsql { 996146ed78bSdan PRAGMA journal_mode = off; 997146ed78bSdan BEGIN; 998146ed78bSdan INSERT INTO t1 VALUES(85, 'Gorbachev'); 999146ed78bSdan INSERT INTO t2 VALUES(85, 'Gorbachev'); 1000146ed78bSdan COMMIT; 1001146ed78bSdan } 1002146ed78bSdan} {off} 1003146ed78bSdan 1004146ed78bSdando_test pager1-5.4.1 { 1005146ed78bSdan db close 1006146ed78bSdan testvfs tv 1007146ed78bSdan sqlite3 db test.db -vfs tv 1008146ed78bSdan execsql { ATTACH 'test.db2' AS aux } 1009146ed78bSdan 1010146ed78bSdan tv filter xDelete 1011146ed78bSdan tv script max_journal_size 1012146ed78bSdan tv sectorsize 512 1013146ed78bSdan set ::max_journal 0 1014146ed78bSdan proc max_journal_size {method args} { 1015146ed78bSdan set sz 0 1016146ed78bSdan catch { set sz [file size test.db-journal] } 1017146ed78bSdan if {$sz > $::max_journal} { 1018146ed78bSdan set ::max_journal $sz 1019146ed78bSdan } 1020146ed78bSdan return SQLITE_OK 1021146ed78bSdan } 1022146ed78bSdan execsql { 1023146ed78bSdan PRAGMA journal_mode = DELETE; 1024146ed78bSdan PRAGMA synchronous = NORMAL; 1025146ed78bSdan BEGIN; 1026146ed78bSdan INSERT INTO t1 VALUES(85, 'Gorbachev'); 1027146ed78bSdan INSERT INTO t2 VALUES(85, 'Gorbachev'); 1028146ed78bSdan COMMIT; 1029146ed78bSdan } 10307f9026ddSdan 10317f9026ddSdan # The size of the journal file is now: 10327f9026ddSdan # 10337f9026ddSdan # 1) 512 byte header + 10347f9026ddSdan # 2) 2 * (1024+8) byte records + 10357f9026ddSdan # 3) 20+N bytes of master-journal pointer, where N is the size of 10367f9026ddSdan # the master-journal name encoded as utf-8 with no nul term. 10377f9026ddSdan # 10387f9026ddSdan set mj_pointer [expr { 1039c5484654Smistachkin 20 + [string length "test.db-mjXXXXXX9XX"] 10407f9026ddSdan }] 1041c5484654Smistachkin # 1042c5484654Smistachkin # NOTE: For item 3 above, if the current SQLite VFS lacks the concept of a 1043c5484654Smistachkin # current directory, the length of the current directory name plus 1 1044c5484654Smistachkin # character for the directory separator character are NOT counted as 1045c5484654Smistachkin # part of the total size; otherwise, they are. 1046c5484654Smistachkin # 1047c5484654Smistachkin ifcapable curdir { 10486aa18c95Smistachkin set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}] 1049c5484654Smistachkin } 10507f9026ddSdan expr {$::max_journal==(512+2*(1024+8)+$mj_pointer)} 10517f9026ddSdan} 1 1052146ed78bSdando_test pager1-5.4.2 { 1053146ed78bSdan set ::max_journal 0 1054146ed78bSdan execsql { 1055146ed78bSdan PRAGMA synchronous = full; 1056146ed78bSdan BEGIN; 1057146ed78bSdan DELETE FROM t1 WHERE b = 'Lenin'; 1058146ed78bSdan DELETE FROM t2 WHERE b = 'Lenin'; 1059146ed78bSdan COMMIT; 1060146ed78bSdan } 10617f9026ddSdan 10627f9026ddSdan # In synchronous=full mode, the master-journal pointer is not written 10637f9026ddSdan # directly after the last record in the journal file. Instead, it is 10647f9026ddSdan # written starting at the next (in this case 512 byte) sector boundary. 10657f9026ddSdan # 10667f9026ddSdan set mj_pointer [expr { 1067c5484654Smistachkin 20 + [string length "test.db-mjXXXXXX9XX"] 10687f9026ddSdan }] 1069c5484654Smistachkin # 1070c5484654Smistachkin # NOTE: If the current SQLite VFS lacks the concept of a current directory, 1071c5484654Smistachkin # the length of the current directory name plus 1 character for the 1072c5484654Smistachkin # directory separator character are NOT counted as part of the total 1073c5484654Smistachkin # size; otherwise, they are. 1074c5484654Smistachkin # 1075c5484654Smistachkin ifcapable curdir { 10766aa18c95Smistachkin set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}] 1077c5484654Smistachkin } 10787f9026ddSdan expr {$::max_journal==(((512+2*(1024+8)+511)/512)*512 + $mj_pointer)} 10797f9026ddSdan} 1 1080146ed78bSdandb close 1081146ed78bSdantv delete 1082146ed78bSdan 1083146ed78bSdando_test pager1-5.5.1 { 1084146ed78bSdan sqlite3 db test.db 1085146ed78bSdan execsql { 1086146ed78bSdan ATTACH 'test.db2' AS aux; 1087146ed78bSdan PRAGMA journal_mode = PERSIST; 1088146ed78bSdan CREATE TABLE t3(a, b); 1089146ed78bSdan INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1; 1090146ed78bSdan UPDATE t3 SET b = randomblob(1500); 1091146ed78bSdan } 1092146ed78bSdan expr [file size test.db-journal] > 15000 1093146ed78bSdan} {1} 1094146ed78bSdando_test pager1-5.5.2 { 1095146ed78bSdan execsql { 1096146ed78bSdan PRAGMA synchronous = full; 1097146ed78bSdan BEGIN; 1098146ed78bSdan DELETE FROM t1 WHERE b = 'Stalin'; 1099146ed78bSdan DELETE FROM t2 WHERE b = 'Stalin'; 1100146ed78bSdan COMMIT; 1101146ed78bSdan } 1102146ed78bSdan file size test.db-journal 1103146ed78bSdan} {0} 1104146ed78bSdan 1105146ed78bSdan 1106146ed78bSdan#------------------------------------------------------------------------- 1107146ed78bSdan# The following tests work with "PRAGMA max_page_count" 1108146ed78bSdan# 1109146ed78bSdando_test pager1-6.1 { 1110146ed78bSdan faultsim_delete_and_reopen 1111146ed78bSdan execsql { 1112f43d7fceSdan PRAGMA auto_vacuum = none; 1113146ed78bSdan PRAGMA max_page_count = 10; 1114146ed78bSdan CREATE TABLE t2(a, b); 1115146ed78bSdan CREATE TABLE t3(a, b); 1116146ed78bSdan CREATE TABLE t4(a, b); 1117146ed78bSdan CREATE TABLE t5(a, b); 1118146ed78bSdan CREATE TABLE t6(a, b); 1119146ed78bSdan CREATE TABLE t7(a, b); 1120146ed78bSdan CREATE TABLE t8(a, b); 1121146ed78bSdan CREATE TABLE t9(a, b); 1122146ed78bSdan CREATE TABLE t10(a, b); 1123146ed78bSdan } 1124146ed78bSdan} {10} 1125d353331aSdando_catchsql_test pager1-6.2 { 1126d353331aSdan CREATE TABLE t11(a, b) 1127146ed78bSdan} {1 {database or disk is full}} 1128d353331aSdando_execsql_test pager1-6.4 { PRAGMA max_page_count } {10} 1129d353331aSdando_execsql_test pager1-6.5 { PRAGMA max_page_count = 15 } {15} 1130d353331aSdando_execsql_test pager1-6.6 { CREATE TABLE t11(a, b) } {} 1131d353331aSdando_execsql_test pager1-6.7 { 1132d353331aSdan BEGIN; 1133d353331aSdan INSERT INTO t11 VALUES(1, 2); 1134d353331aSdan PRAGMA max_page_count = 13; 1135d353331aSdan} {13} 1136d353331aSdando_execsql_test pager1-6.8 { 1137d353331aSdan INSERT INTO t11 VALUES(3, 4); 1138d353331aSdan PRAGMA max_page_count = 10; 1139d353331aSdan} {11} 1140d353331aSdando_execsql_test pager1-6.9 { COMMIT } {} 1141de4996e2Sdan 114260ac3f42Sdrhdo_execsql_test pager1-6.10 { PRAGMA max_page_count = 10 } {11} 114322b328b2Sdando_execsql_test pager1-6.11 { SELECT * FROM t11 } {1 2 3 4} 114422b328b2Sdando_execsql_test pager1-6.12 { PRAGMA max_page_count } {11} 114522b328b2Sdan 1146153eda0aSdan 1147153eda0aSdan#------------------------------------------------------------------------- 1148153eda0aSdan# The following tests work with "PRAGMA journal_mode=TRUNCATE" and 1149153eda0aSdan# "PRAGMA locking_mode=EXCLUSIVE". 1150153eda0aSdan# 1151153eda0aSdan# Each test is specified with 5 variables. As follows: 1152153eda0aSdan# 1153153eda0aSdan# $tn: Test Number. Used as part of the [do_test] test names. 1154153eda0aSdan# $sql: SQL to execute. 1155153eda0aSdan# $res: Expected result of executing $sql. 1156153eda0aSdan# $js: The expected size of the journal file, in bytes, after executing 1157153eda0aSdan# the SQL script. Or -1 if the journal is not expected to exist. 1158153eda0aSdan# $ws: The expected size of the WAL file, in bytes, after executing 1159153eda0aSdan# the SQL script. Or -1 if the WAL is not expected to exist. 1160153eda0aSdan# 116138e1a279Sdanifcapable wal { 1162153eda0aSdan faultsim_delete_and_reopen 1163153eda0aSdan foreach {tn sql res js ws} [subst { 1164153eda0aSdan 1165153eda0aSdan 1 { 1166153eda0aSdan CREATE TABLE t1(a, b); 1167153eda0aSdan PRAGMA auto_vacuum=OFF; 1168153eda0aSdan PRAGMA synchronous=NORMAL; 1169153eda0aSdan PRAGMA page_size=1024; 1170153eda0aSdan PRAGMA locking_mode=EXCLUSIVE; 1171153eda0aSdan PRAGMA journal_mode=TRUNCATE; 1172153eda0aSdan INSERT INTO t1 VALUES(1, 2); 1173153eda0aSdan } {exclusive truncate} 0 -1 1174153eda0aSdan 1175153eda0aSdan 2 { 1176153eda0aSdan BEGIN IMMEDIATE; 1177153eda0aSdan SELECT * FROM t1; 1178153eda0aSdan COMMIT; 1179153eda0aSdan } {1 2} 0 -1 1180153eda0aSdan 1181153eda0aSdan 3 { 1182153eda0aSdan BEGIN; 1183153eda0aSdan SELECT * FROM t1; 1184153eda0aSdan COMMIT; 1185153eda0aSdan } {1 2} 0 -1 1186153eda0aSdan 1187153eda0aSdan 4 { PRAGMA journal_mode = WAL } wal -1 -1 1188153eda0aSdan 5 { INSERT INTO t1 VALUES(3, 4) } {} -1 [wal_file_size 1 1024] 11898c408004Sdan 6 { PRAGMA locking_mode = NORMAL } exclusive -1 [wal_file_size 1 1024] 1190153eda0aSdan 7 { INSERT INTO t1 VALUES(5, 6); } {} -1 [wal_file_size 2 1024] 1191153eda0aSdan 1192153eda0aSdan 8 { PRAGMA journal_mode = TRUNCATE } truncate 0 -1 1193153eda0aSdan 9 { INSERT INTO t1 VALUES(7, 8) } {} 0 -1 1194153eda0aSdan 10 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8} 0 -1 1195153eda0aSdan 1196153eda0aSdan }] { 1197153eda0aSdan do_execsql_test pager1-7.1.$tn.1 $sql $res 1198153eda0aSdan catch { set J -1 ; set J [file size test.db-journal] } 1199153eda0aSdan catch { set W -1 ; set W [file size test.db-wal] } 1200153eda0aSdan do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws] 1201153eda0aSdan } 120238e1a279Sdan} 1203153eda0aSdan 120489ccf448Sdando_test pager1-7.2.1 { 120589ccf448Sdan faultsim_delete_and_reopen 120689ccf448Sdan execsql { 120789ccf448Sdan PRAGMA locking_mode = EXCLUSIVE; 120889ccf448Sdan CREATE TABLE t1(a, b); 120989ccf448Sdan BEGIN; 121089ccf448Sdan PRAGMA journal_mode = delete; 121189ccf448Sdan PRAGMA journal_mode = truncate; 121289ccf448Sdan } 121389ccf448Sdan} {exclusive delete truncate} 121489ccf448Sdando_test pager1-7.2.2 { 121589ccf448Sdan execsql { INSERT INTO t1 VALUES(1, 2) } 121689ccf448Sdan execsql { PRAGMA journal_mode = persist } 121789ccf448Sdan} {truncate} 121889ccf448Sdando_test pager1-7.2.3 { 121989ccf448Sdan execsql { COMMIT } 122089ccf448Sdan execsql { 122189ccf448Sdan PRAGMA journal_mode = persist; 122289ccf448Sdan PRAGMA journal_size_limit; 122389ccf448Sdan } 122489ccf448Sdan} {persist -1} 122589ccf448Sdan 1226d353331aSdan#------------------------------------------------------------------------- 1227d353331aSdan# The following tests, pager1-8.*, test that the special filenames 1228d353331aSdan# ":memory:" and "" open temporary databases. 1229d353331aSdan# 12300e986f51Sdanforeach {tn filename} { 12310e986f51Sdan 1 :memory: 12320e986f51Sdan 2 "" 12330e986f51Sdan} { 12340e986f51Sdan do_test pager1-8.$tn.1 { 1235153eda0aSdan faultsim_delete_and_reopen 1236153eda0aSdan db close 12370e986f51Sdan sqlite3 db $filename 1238153eda0aSdan execsql { 1239c8ce3972Sdan PRAGMA auto_vacuum = 1; 1240153eda0aSdan CREATE TABLE x1(x); 1241153eda0aSdan INSERT INTO x1 VALUES('Charles'); 1242153eda0aSdan INSERT INTO x1 VALUES('James'); 1243153eda0aSdan INSERT INTO x1 VALUES('Mary'); 1244153eda0aSdan SELECT * FROM x1; 1245153eda0aSdan } 1246153eda0aSdan } {Charles James Mary} 12470e986f51Sdan 12480e986f51Sdan do_test pager1-8.$tn.2 { 12490e986f51Sdan sqlite3 db2 $filename 12500e986f51Sdan catchsql { SELECT * FROM x1 } db2 1251153eda0aSdan } {1 {no such table: x1}} 1252153eda0aSdan 12530e986f51Sdan do_execsql_test pager1-8.$tn.3 { 12540e986f51Sdan BEGIN; 12550e986f51Sdan INSERT INTO x1 VALUES('William'); 12560e986f51Sdan INSERT INTO x1 VALUES('Anne'); 12570e986f51Sdan ROLLBACK; 12580e986f51Sdan } {} 12590e986f51Sdan} 12600e986f51Sdan 1261dca321aeSdan#------------------------------------------------------------------------- 1262dca321aeSdan# The next block of tests - pager1-9.* - deal with interactions between 1263dca321aeSdan# the pager and the backup API. Test cases: 1264dca321aeSdan# 1265dca321aeSdan# pager1-9.1.*: Test that a backup completes successfully even if the 1266dca321aeSdan# source db is written to during the backup op. 1267dca321aeSdan# 1268dca321aeSdan# pager1-9.2.*: Test that a backup completes successfully even if the 1269dca321aeSdan# source db is written to and then rolled back during a 1270dca321aeSdan# backup operation. 1271dca321aeSdan# 1272dca321aeSdando_test pager1-9.0.1 { 1273dca321aeSdan faultsim_delete_and_reopen 1274dca321aeSdan db func a_string a_string 1275dca321aeSdan execsql { 1276dca321aeSdan PRAGMA cache_size = 10; 1277dca321aeSdan BEGIN; 1278dca321aeSdan CREATE TABLE ab(a, b, UNIQUE(a, b)); 1279dca321aeSdan INSERT INTO ab VALUES( a_string(200), a_string(300) ); 1280dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1281dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1282dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1283dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1284dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1285dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1286dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1287dca321aeSdan COMMIT; 1288dca321aeSdan } 1289dca321aeSdan} {} 1290dca321aeSdando_test pager1-9.0.2 { 1291dca321aeSdan sqlite3 db2 test.db2 1292dca321aeSdan db2 eval { PRAGMA cache_size = 10 } 1293dca321aeSdan sqlite3_backup B db2 main db main 1294dca321aeSdan list [B step 10000] [B finish] 1295dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1296dca321aeSdando_test pager1-9.0.3 { 1297dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1298dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1299dca321aeSdan 1300dca321aeSdando_test pager1-9.1.1 { 1301dca321aeSdan execsql { UPDATE ab SET a = a_string(201) } 1302dca321aeSdan sqlite3_backup B db2 main db main 1303dca321aeSdan B step 30 1304dca321aeSdan} {SQLITE_OK} 1305dca321aeSdando_test pager1-9.1.2 { 1306dca321aeSdan execsql { UPDATE ab SET b = a_string(301) } 1307dca321aeSdan list [B step 10000] [B finish] 1308dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1309dca321aeSdando_test pager1-9.1.3 { 1310dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1311dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1312dca321aeSdando_test pager1-9.1.4 { execsql { SELECT count(*) FROM ab } } {128} 1313dca321aeSdan 1314dca321aeSdando_test pager1-9.2.1 { 1315dca321aeSdan execsql { UPDATE ab SET a = a_string(202) } 1316dca321aeSdan sqlite3_backup B db2 main db main 1317dca321aeSdan B step 30 1318dca321aeSdan} {SQLITE_OK} 1319dca321aeSdando_test pager1-9.2.2 { 1320dca321aeSdan execsql { 1321dca321aeSdan BEGIN; 1322dca321aeSdan UPDATE ab SET b = a_string(301); 1323dca321aeSdan ROLLBACK; 1324dca321aeSdan } 1325dca321aeSdan list [B step 10000] [B finish] 1326dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1327dca321aeSdando_test pager1-9.2.3 { 1328dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1329dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1330dca321aeSdando_test pager1-9.2.4 { execsql { SELECT count(*) FROM ab } } {128} 1331ec6ffc1aSdandb close 1332ec6ffc1aSdandb2 close 1333ec6ffc1aSdan 1334c396d4afSdando_test pager1-9.3.1 { 1335c396d4afSdan testvfs tv -default 1 1336c396d4afSdan tv sectorsize 4096 1337c396d4afSdan faultsim_delete_and_reopen 1338c396d4afSdan 1339c396d4afSdan execsql { PRAGMA page_size = 1024 } 1340c396d4afSdan for {set ii 0} {$ii < 4} {incr ii} { execsql "CREATE TABLE t${ii}(a, b)" } 1341c396d4afSdan} {} 1342c396d4afSdando_test pager1-9.3.2 { 1343c396d4afSdan sqlite3 db2 test.db2 1344f412ee2eSdan 1345c396d4afSdan execsql { 1346c396d4afSdan PRAGMA page_size = 4096; 1347c396d4afSdan PRAGMA synchronous = OFF; 1348c396d4afSdan CREATE TABLE t1(a, b); 1349c396d4afSdan CREATE TABLE t2(a, b); 1350c396d4afSdan } db2 1351c396d4afSdan 1352c396d4afSdan sqlite3_backup B db2 main db main 1353c396d4afSdan B step 30 1354c396d4afSdan list [B step 10000] [B finish] 1355c396d4afSdan} {SQLITE_DONE SQLITE_OK} 1356c396d4afSdando_test pager1-9.3.3 { 1357c396d4afSdan db2 close 1358c396d4afSdan db close 1359c396d4afSdan tv delete 1360c396d4afSdan file size test.db2 1361c396d4afSdan} [file size test.db] 1362c396d4afSdan 1363f412ee2eSdando_test pager1-9.4.1 { 1364f412ee2eSdan faultsim_delete_and_reopen 1365f412ee2eSdan sqlite3 db2 test.db2 1366f412ee2eSdan execsql { 1367f412ee2eSdan PRAGMA page_size = 4096; 1368f412ee2eSdan CREATE TABLE t1(a, b); 1369f412ee2eSdan CREATE TABLE t2(a, b); 1370f412ee2eSdan } db2 1371f412ee2eSdan sqlite3_backup B db2 main db main 1372f412ee2eSdan list [B step 10000] [B finish] 1373f412ee2eSdan} {SQLITE_DONE SQLITE_OK} 1374f412ee2eSdando_test pager1-9.4.2 { 1375f412ee2eSdan list [file size test.db2] [file size test.db] 1376b483eba0Sdan} {1024 0} 137733d85c9cSshanehdb2 close 1378d0b0d4dcSdan 1379ec6ffc1aSdan#------------------------------------------------------------------------- 1380ec6ffc1aSdan# Test that regardless of the value returned by xSectorSize(), the 1381ec6ffc1aSdan# minimum effective sector-size is 512 and the maximum 65536 bytes. 1382ec6ffc1aSdan# 1383ec6ffc1aSdantestvfs tv -default 1 1384ec6ffc1aSdanforeach sectorsize { 1385ec6ffc1aSdan 32 64 128 256 512 1024 2048 1386ec6ffc1aSdan 4096 8192 16384 32768 65536 131072 262144 1387ec6ffc1aSdan} { 1388ec6ffc1aSdan tv sectorsize $sectorsize 13891eaaf93aSdrh tv devchar {} 1390ec6ffc1aSdan set eff $sectorsize 1391ec6ffc1aSdan if {$sectorsize < 512} { set eff 512 } 1392ec6ffc1aSdan if {$sectorsize > 65536} { set eff 65536 } 1393ec6ffc1aSdan 1394d0b0d4dcSdan do_test pager1-10.$sectorsize.1 { 1395ec6ffc1aSdan faultsim_delete_and_reopen 1396d0b0d4dcSdan db func a_string a_string 1397ec6ffc1aSdan execsql { 1398ec6ffc1aSdan PRAGMA journal_mode = PERSIST; 1399ec6ffc1aSdan PRAGMA page_size = 1024; 1400d0b0d4dcSdan BEGIN; 1401ec6ffc1aSdan CREATE TABLE t1(a, b); 1402d0b0d4dcSdan CREATE TABLE t2(a, b); 1403d0b0d4dcSdan CREATE TABLE t3(a, b); 1404d0b0d4dcSdan COMMIT; 1405ec6ffc1aSdan } 1406ec6ffc1aSdan file size test.db-journal 1407ec6ffc1aSdan } [expr $sectorsize > 65536 ? 65536 : $sectorsize] 1408d0b0d4dcSdan 1409d0b0d4dcSdan do_test pager1-10.$sectorsize.2 { 1410d0b0d4dcSdan execsql { 1411d0b0d4dcSdan INSERT INTO t3 VALUES(a_string(300), a_string(300)); 1412d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 2 */ 1413d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 4 */ 1414d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 8 */ 1415d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 16 */ 1416d0b0d4dcSdan INSERT INTO t3 SELECT * FROM t3; /* 32 */ 1417ec6ffc1aSdan } 1418d0b0d4dcSdan } {} 1419d0b0d4dcSdan 1420d0b0d4dcSdan do_test pager1-10.$sectorsize.3 { 1421d0b0d4dcSdan db close 1422d0b0d4dcSdan sqlite3 db test.db 1423d0b0d4dcSdan execsql { 1424d0b0d4dcSdan PRAGMA cache_size = 10; 1425d0b0d4dcSdan BEGIN; 1426d0b0d4dcSdan } 1427d0b0d4dcSdan recursive_select 32 t3 {db eval "INSERT INTO t2 VALUES(1, 2)"} 1428d0b0d4dcSdan execsql { 1429d0b0d4dcSdan COMMIT; 1430d0b0d4dcSdan SELECT * FROM t2; 1431d0b0d4dcSdan } 1432d0b0d4dcSdan } {1 2} 1433d0b0d4dcSdan 1434d0b0d4dcSdan do_test pager1-10.$sectorsize.4 { 1435d0b0d4dcSdan execsql { 1436d0b0d4dcSdan CREATE TABLE t6(a, b); 1437d0b0d4dcSdan CREATE TABLE t7(a, b); 1438d0b0d4dcSdan CREATE TABLE t5(a, b); 1439d0b0d4dcSdan DROP TABLE t6; 1440d0b0d4dcSdan DROP TABLE t7; 1441d0b0d4dcSdan } 1442d0b0d4dcSdan execsql { 1443d0b0d4dcSdan BEGIN; 1444d0b0d4dcSdan CREATE TABLE t6(a, b); 1445d0b0d4dcSdan } 1446d0b0d4dcSdan recursive_select 32 t3 {db eval "INSERT INTO t5 VALUES(1, 2)"} 1447d0b0d4dcSdan execsql { 1448d0b0d4dcSdan COMMIT; 1449d0b0d4dcSdan SELECT * FROM t5; 1450d0b0d4dcSdan } 1451d0b0d4dcSdan } {1 2} 1452d0b0d4dcSdan 1453d0b0d4dcSdan} 1454d0b0d4dcSdandb close 1455d0b0d4dcSdan 1456d0b0d4dcSdantv sectorsize 4096 1457d0b0d4dcSdando_test pager1.10.x.1 { 1458d0b0d4dcSdan faultsim_delete_and_reopen 1459d0b0d4dcSdan execsql { 1460f43d7fceSdan PRAGMA auto_vacuum = none; 1461d0b0d4dcSdan PRAGMA page_size = 1024; 1462d0b0d4dcSdan CREATE TABLE t1(x); 1463d0b0d4dcSdan } 1464d0b0d4dcSdan for {set i 0} {$i<30} {incr i} { 1465d0b0d4dcSdan execsql { INSERT INTO t1 VALUES(zeroblob(900)) } 1466d0b0d4dcSdan } 1467d0b0d4dcSdan file size test.db 1468d0b0d4dcSdan} {32768} 1469d0b0d4dcSdando_test pager1.10.x.2 { 1470d0b0d4dcSdan execsql { 1471d0b0d4dcSdan CREATE TABLE t2(x); 1472d0b0d4dcSdan DROP TABLE t2; 1473d0b0d4dcSdan } 1474d0b0d4dcSdan file size test.db 1475d0b0d4dcSdan} {33792} 1476d0b0d4dcSdando_test pager1.10.x.3 { 1477d0b0d4dcSdan execsql { 1478d0b0d4dcSdan BEGIN; 1479d0b0d4dcSdan CREATE TABLE t2(x); 1480d0b0d4dcSdan } 1481d0b0d4dcSdan recursive_select 30 t1 1482d0b0d4dcSdan execsql { 1483d0b0d4dcSdan CREATE TABLE t3(x); 1484d0b0d4dcSdan COMMIT; 1485d0b0d4dcSdan } 1486d0b0d4dcSdan} {} 1487d0b0d4dcSdan 1488ec6ffc1aSdandb close 1489ec6ffc1aSdantv delete 1490ec6ffc1aSdan 1491ec6ffc1aSdantestvfs tv -default 1 1492ec6ffc1aSdanfaultsim_delete_and_reopen 1493ec6ffc1aSdandb func a_string a_string 1494ec6ffc1aSdando_execsql_test pager1-11.1 { 14953f94b609Sdan PRAGMA journal_mode = DELETE; 1496ec6ffc1aSdan PRAGMA cache_size = 10; 1497ec6ffc1aSdan BEGIN; 1498ec6ffc1aSdan CREATE TABLE zz(top PRIMARY KEY); 1499ec6ffc1aSdan INSERT INTO zz VALUES(a_string(222)); 1500ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1501ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1502ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1503ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1504ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1505ec6ffc1aSdan COMMIT; 1506ec6ffc1aSdan BEGIN; 1507ec6ffc1aSdan UPDATE zz SET top = a_string(345); 15083f94b609Sdan} {delete} 1509ec6ffc1aSdan 1510ec6ffc1aSdanproc lockout {method args} { return SQLITE_IOERR } 1511ec6ffc1aSdantv script lockout 1512ec6ffc1aSdantv filter {xWrite xTruncate xSync} 1513ec6ffc1aSdando_catchsql_test pager1-11.2 { COMMIT } {1 {disk I/O error}} 1514ec6ffc1aSdan 1515ec6ffc1aSdantv script {} 1516ec6ffc1aSdando_test pager1-11.3 { 1517ec6ffc1aSdan sqlite3 db2 test.db 1518ec6ffc1aSdan execsql { 1519ec6ffc1aSdan PRAGMA journal_mode = TRUNCATE; 1520ec6ffc1aSdan PRAGMA integrity_check; 1521ec6ffc1aSdan } db2 1522ec6ffc1aSdan} {truncate ok} 1523ec6ffc1aSdando_test pager1-11.4 { 1524ec6ffc1aSdan db2 close 1525f6c61471Sdan file exists test.db-journal 1526ec6ffc1aSdan} {0} 1527ec6ffc1aSdando_execsql_test pager1-11.5 { SELECT count(*) FROM zz } {32} 1528f9b4419dSdandb close 1529f9b4419dSdantv delete 1530ec6ffc1aSdan 1531f9b4419dSdan#------------------------------------------------------------------------- 1532f9b4419dSdan# Test "PRAGMA page_size" 1533f9b4419dSdan# 1534f43d7fceSdantestvfs tv -default 1 1535f43d7fceSdantv sectorsize 1024 1536f9b4419dSdanforeach pagesize { 1537f9b4419dSdan 512 1024 2048 4096 8192 16384 32768 1538f9b4419dSdan} { 1539f9b4419dSdan faultsim_delete_and_reopen 1540f9b4419dSdan 1541f43d7fceSdan # The sector-size (according to the VFS) is 1024 bytes. So if the 1542f43d7fceSdan # page-size requested using "PRAGMA page_size" is greater than the 1543f43d7fceSdan # compile time value of SQLITE_MAX_PAGE_SIZE, then the effective 1544f43d7fceSdan # page-size remains 1024 bytes. 1545f43d7fceSdan # 1546f43d7fceSdan set eff $pagesize 1547f43d7fceSdan if {$eff > $::SQLITE_MAX_PAGE_SIZE} { set eff 1024 } 1548f43d7fceSdan 1549f9b4419dSdan do_test pager1-12.$pagesize.1 { 1550f9b4419dSdan sqlite3 db2 test.db 1551f9b4419dSdan execsql " 1552f9b4419dSdan PRAGMA page_size = $pagesize; 1553f9b4419dSdan CREATE VIEW v AS SELECT * FROM sqlite_master; 1554f9b4419dSdan " db2 1555f9b4419dSdan file size test.db 1556f43d7fceSdan } $eff 1557f9b4419dSdan do_test pager1-12.$pagesize.2 { 1558f9b4419dSdan sqlite3 db2 test.db 1559f9b4419dSdan execsql { 1560f9b4419dSdan SELECT count(*) FROM v; 1561f9b4419dSdan PRAGMA main.page_size; 1562f9b4419dSdan } db2 1563f43d7fceSdan } [list 1 $eff] 1564f9b4419dSdan do_test pager1-12.$pagesize.3 { 1565f9b4419dSdan execsql { 1566f9b4419dSdan SELECT count(*) FROM v; 1567f9b4419dSdan PRAGMA main.page_size; 1568f9b4419dSdan } 1569f43d7fceSdan } [list 1 $eff] 1570f9b4419dSdan db2 close 1571f9b4419dSdan} 1572f43d7fceSdandb close 1573f43d7fceSdantv delete 1574dca321aeSdan 1575d353331aSdan#------------------------------------------------------------------------- 1576d353331aSdan# Test specal "PRAGMA journal_mode=PERSIST" test cases. 1577d353331aSdan# 1578d353331aSdan# pager1-13.1.*: This tests a special case encountered in persistent 1579d353331aSdan# journal mode: If the journal associated with a transaction 1580d353331aSdan# is smaller than the journal file (because a previous 1581d353331aSdan# transaction left a very large non-hot journal file in the 1582d353331aSdan# file-system), then SQLite has to be careful that there is 1583d353331aSdan# not a journal-header left over from a previous transaction 1584d353331aSdan# immediately following the journal content just written. 1585d353331aSdan# If there is, and the process crashes so that the journal 1586d353331aSdan# becomes a hot-journal and must be rolled back by another 1587d353331aSdan# process, there is a danger that the other process may roll 1588d353331aSdan# back the aborted transaction, then continue copying data 1589d353331aSdan# from an older transaction from the remainder of the journal. 1590d353331aSdan# See the syncJournal() function for details. 1591d353331aSdan# 1592d353331aSdan# pager1-13.2.*: Same test as the previous. This time, throw an index into 1593d353331aSdan# the mix to make the integrity-check more likely to catch 1594d353331aSdan# errors. 1595d353331aSdan# 1596d353331aSdantestvfs tv -default 1 1597d353331aSdantv script xSyncCb 1598d353331aSdantv filter xSync 1599d353331aSdanproc xSyncCb {method filename args} { 1600d353331aSdan set t [file tail $filename] 1601d353331aSdan if {$t == "test.db"} faultsim_save 1602d353331aSdan return SQLITE_OK 1603d353331aSdan} 1604d353331aSdanfaultsim_delete_and_reopen 1605d353331aSdandb func a_string a_string 1606e91a54e1Sdan 1607d353331aSdan# The UPDATE statement at the end of this test case creates a really big 1608d353331aSdan# journal. Since the cache-size is only 10 pages, the journal contains 1609d353331aSdan# frequent journal headers. 1610d353331aSdan# 1611d353331aSdando_execsql_test pager1-13.1.1 { 1612d353331aSdan PRAGMA page_size = 1024; 1613d353331aSdan PRAGMA journal_mode = PERSIST; 1614d353331aSdan PRAGMA cache_size = 10; 1615d353331aSdan BEGIN; 1616d353331aSdan CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB); 1617d353331aSdan INSERT INTO t1 VALUES(NULL, a_string(400)); 1618d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 2 */ 1619d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 4 */ 1620d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 8 */ 1621d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 16 */ 1622d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 32 */ 1623d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 64 */ 1624d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 128 */ 1625d353331aSdan COMMIT; 1626d353331aSdan UPDATE t1 SET b = a_string(400); 1627d353331aSdan} {persist} 1628d353331aSdan 1629b2f20bfcSshanehif {$::tcl_platform(platform)!="windows"} { 1630d353331aSdan# Run transactions of increasing sizes. Eventually, one (or more than one) 1631d353331aSdan# of these will write just enough content that one of the old headers created 1632d353331aSdan# by the transaction in the block above lies immediately after the content 1633d353331aSdan# journalled by the current transaction. 1634d353331aSdan# 1635d353331aSdanfor {set nUp 1} {$nUp<64} {incr nUp} { 1636d353331aSdan do_execsql_test pager1-13.1.2.$nUp.1 { 1637d353331aSdan UPDATE t1 SET b = a_string(399) WHERE a <= $nUp 1638d353331aSdan } {} 1639d353331aSdan do_execsql_test pager1-13.1.2.$nUp.2 { PRAGMA integrity_check } {ok} 1640d353331aSdan 1641d353331aSdan # Try to access the snapshot of the file-system. 1642d353331aSdan # 1643d353331aSdan sqlite3 db2 sv_test.db 1644d353331aSdan do_test pager1-13.1.2.$nUp.3 { 1645d353331aSdan execsql { SELECT sum(length(b)) FROM t1 } db2 1646d353331aSdan } [expr {128*400 - ($nUp-1)}] 1647d353331aSdan do_test pager1-13.1.2.$nUp.4 { 1648d353331aSdan execsql { PRAGMA integrity_check } db2 1649d353331aSdan } {ok} 1650d353331aSdan db2 close 1651d353331aSdan} 1652b2f20bfcSshaneh} 1653d353331aSdan 1654b2f20bfcSshanehif {$::tcl_platform(platform)!="windows"} { 1655d353331aSdan# Same test as above. But this time with an index on the table. 1656d353331aSdan# 1657d353331aSdando_execsql_test pager1-13.2.1 { 1658d353331aSdan CREATE INDEX i1 ON t1(b); 1659d353331aSdan UPDATE t1 SET b = a_string(400); 1660d353331aSdan} {} 1661d353331aSdanfor {set nUp 1} {$nUp<64} {incr nUp} { 1662d353331aSdan do_execsql_test pager1-13.2.2.$nUp.1 { 1663d353331aSdan UPDATE t1 SET b = a_string(399) WHERE a <= $nUp 1664d353331aSdan } {} 1665d353331aSdan do_execsql_test pager1-13.2.2.$nUp.2 { PRAGMA integrity_check } {ok} 1666d353331aSdan sqlite3 db2 sv_test.db 1667d353331aSdan do_test pager1-13.2.2.$nUp.3 { 1668d353331aSdan execsql { SELECT sum(length(b)) FROM t1 } db2 1669d353331aSdan } [expr {128*400 - ($nUp-1)}] 1670d353331aSdan do_test pager1-13.2.2.$nUp.4 { 1671d353331aSdan execsql { PRAGMA integrity_check } db2 1672d353331aSdan } {ok} 1673d353331aSdan db2 close 1674d353331aSdan} 1675b2f20bfcSshaneh} 1676d353331aSdan 1677d353331aSdandb close 1678d353331aSdantv delete 1679d353331aSdan 1680d353331aSdan#------------------------------------------------------------------------- 1681d353331aSdan# Test specal "PRAGMA journal_mode=OFF" test cases. 1682d353331aSdan# 1683d353331aSdanfaultsim_delete_and_reopen 1684d353331aSdando_execsql_test pager1-14.1.1 { 1685d353331aSdan PRAGMA journal_mode = OFF; 1686d353331aSdan CREATE TABLE t1(a, b); 1687d353331aSdan BEGIN; 1688d353331aSdan INSERT INTO t1 VALUES(1, 2); 1689d353331aSdan COMMIT; 1690d353331aSdan SELECT * FROM t1; 1691d353331aSdan} {off 1 2} 1692d353331aSdando_catchsql_test pager1-14.1.2 { 1693d353331aSdan BEGIN; 1694d353331aSdan INSERT INTO t1 VALUES(3, 4); 1695d353331aSdan ROLLBACK; 1696d353331aSdan} {0 {}} 1697d353331aSdando_execsql_test pager1-14.1.3 { 1698d353331aSdan SELECT * FROM t1; 1699354bfe03Sdan} {1 2} 1700d353331aSdando_catchsql_test pager1-14.1.4 { 1701d353331aSdan BEGIN; 1702d353331aSdan INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; 1703d353331aSdan INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; 1704d353331aSdan} {1 {PRIMARY KEY must be unique}} 1705d353331aSdando_execsql_test pager1-14.1.5 { 1706d353331aSdan COMMIT; 1707d353331aSdan SELECT * FROM t1; 1708354bfe03Sdan} {1 2 2 2} 1709d353331aSdan 1710c8ce3972Sdan#------------------------------------------------------------------------- 1711c8ce3972Sdan# Test opening and closing the pager sub-system with different values 1712c8ce3972Sdan# for the sqlite3_vfs.szOsFile variable. 1713c8ce3972Sdan# 1714c8ce3972Sdanfaultsim_delete_and_reopen 1715c8ce3972Sdando_execsql_test pager1-15.0 { 1716c8ce3972Sdan CREATE TABLE tx(y, z); 1717c8ce3972Sdan INSERT INTO tx VALUES('Ayutthaya', 'Beijing'); 1718c8ce3972Sdan INSERT INTO tx VALUES('London', 'Tokyo'); 1719c8ce3972Sdan} {} 1720c8ce3972Sdandb close 1721c8ce3972Sdanfor {set i 0} {$i<513} {incr i 3} { 1722c8ce3972Sdan testvfs tv -default 1 -szosfile $i 1723c8ce3972Sdan sqlite3 db test.db 1724c8ce3972Sdan do_execsql_test pager1-15.$i.1 { 1725c8ce3972Sdan SELECT * FROM tx; 1726c8ce3972Sdan } {Ayutthaya Beijing London Tokyo} 1727c8ce3972Sdan db close 1728c8ce3972Sdan tv delete 1729c8ce3972Sdan} 1730c8ce3972Sdan 1731c8ce3972Sdan#------------------------------------------------------------------------- 1732c8ce3972Sdan# Check that it is not possible to open a database file if the full path 1733c8ce3972Sdan# to the associated journal file will be longer than sqlite3_vfs.mxPathname. 1734c8ce3972Sdan# 1735c8ce3972Sdantestvfs tv -default 1 1736c8ce3972Sdantv script xOpenCb 1737c8ce3972Sdantv filter xOpen 173833f5379cSdanproc xOpenCb {method filename args} { 1739c8ce3972Sdan set ::file_len [string length $filename] 1740c8ce3972Sdan} 1741c8ce3972Sdansqlite3 db test.db 1742c8ce3972Sdandb close 1743c8ce3972Sdantv delete 1744c8ce3972Sdan 1745c8ce3972Sdanfor {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} { 1746c8ce3972Sdan testvfs tv -default 1 -mxpathname $ii 1747c8ce3972Sdan 1748c8ce3972Sdan # The length of the full path to file "test.db-journal" is ($::file_len+8). 1749c8ce3972Sdan # If the configured sqlite3_vfs.mxPathname value greater than or equal to 1750c8ce3972Sdan # this, then the file can be opened. Otherwise, it cannot. 1751c8ce3972Sdan # 1752c8ce3972Sdan if {$ii >= [expr $::file_len+8]} { 1753c8ce3972Sdan set res {0 {}} 1754c8ce3972Sdan } else { 1755c8ce3972Sdan set res {1 {unable to open database file}} 1756c8ce3972Sdan } 1757c8ce3972Sdan 1758c8ce3972Sdan do_test pager1-16.1.$ii { 1759c8ce3972Sdan list [catch { sqlite3 db test.db } msg] $msg 1760c8ce3972Sdan } $res 1761c8ce3972Sdan 1762c8ce3972Sdan catch {db close} 1763c8ce3972Sdan tv delete 1764c8ce3972Sdan} 1765c8ce3972Sdan 1766c8ce3972Sdan 1767c8ce3972Sdan#------------------------------------------------------------------------- 1768c8ce3972Sdan# Test the pagers response to the b-tree layer requesting illegal page 1769c8ce3972Sdan# numbers: 1770c8ce3972Sdan# 1771c8ce3972Sdan# + The locking page, 1772c8ce3972Sdan# + Page 0, 1773c8ce3972Sdan# + A page with a page number greater than (2^31-1). 1774c8ce3972Sdan# 1775f4ba1093Sdan# These tests will not work if SQLITE_DIRECT_OVERFLOW_READ is defined. In 1776f4ba1093Sdan# that case IO errors are sometimes reported instead of SQLITE_CORRUPT. 1777f4ba1093Sdan# 1778f4ba1093Sdanifcapable !direct_read { 1779c8ce3972Sdando_test pager1-18.1 { 1780c8ce3972Sdan faultsim_delete_and_reopen 1781c8ce3972Sdan db func a_string a_string 1782c8ce3972Sdan execsql { 1783c8ce3972Sdan PRAGMA page_size = 1024; 1784c8ce3972Sdan CREATE TABLE t1(a, b); 1785c8ce3972Sdan INSERT INTO t1 VALUES(a_string(500), a_string(200)); 1786c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1787c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1788c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1789c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1790c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1791c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1792c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1793c8ce3972Sdan } 1794c8ce3972Sdan} {} 1795c8ce3972Sdando_test pager1-18.2 { 1796c8ce3972Sdan set root [db one "SELECT rootpage FROM sqlite_master"] 1797c8ce3972Sdan set lockingpage [expr (0x10000/1024) + 1] 1798c8ce3972Sdan execsql { 1799c8ce3972Sdan PRAGMA writable_schema = 1; 1800c8ce3972Sdan UPDATE sqlite_master SET rootpage = $lockingpage; 1801c8ce3972Sdan } 1802c8ce3972Sdan sqlite3 db2 test.db 1803c8ce3972Sdan catchsql { SELECT count(*) FROM t1 } db2 1804c8ce3972Sdan} {1 {database disk image is malformed}} 1805c8ce3972Sdandb2 close 1806a748fdccSdrhdo_test pager1-18.3.1 { 1807c8ce3972Sdan execsql { 1808c8ce3972Sdan CREATE TABLE t2(x); 1809c8ce3972Sdan INSERT INTO t2 VALUES(a_string(5000)); 1810c8ce3972Sdan } 1811c8ce3972Sdan set pgno [expr ([file size test.db] / 1024)-2] 1812c8ce3972Sdan hexio_write test.db [expr ($pgno-1)*1024] 00000000 1813c8ce3972Sdan sqlite3 db2 test.db 1814a748fdccSdrh # even though x is malformed, because typeof() does 1815a748fdccSdrh # not load the content of x, the error is not noticed. 1816a748fdccSdrh catchsql { SELECT typeof(x) FROM t2 } db2 1817a748fdccSdrh} {0 text} 1818a748fdccSdrhdo_test pager1-18.3.2 { 1819a748fdccSdrh # in this case, the value of x is loaded and so the error is 1820a748fdccSdrh # detected 1821a748fdccSdrh catchsql { SELECT length(x||'') FROM t2 } db2 1822a748fdccSdrh} {1 {database disk image is malformed}} 1823a748fdccSdrhdb2 close 1824a748fdccSdrhdo_test pager1-18.3.3 { 1825a748fdccSdrh execsql { 1826a748fdccSdrh DELETE FROM t2; 1827a748fdccSdrh INSERT INTO t2 VALUES(randomblob(5000)); 1828a748fdccSdrh } 1829a748fdccSdrh set pgno [expr ([file size test.db] / 1024)-2] 1830a748fdccSdrh hexio_write test.db [expr ($pgno-1)*1024] 00000000 1831a748fdccSdrh sqlite3 db2 test.db 1832a748fdccSdrh # even though x is malformed, because length() and typeof() do 1833a748fdccSdrh # not load the content of x, the error is not noticed. 1834a748fdccSdrh catchsql { SELECT length(x), typeof(x) FROM t2 } db2 1835a748fdccSdrh} {0 {5000 blob}} 1836a748fdccSdrhdo_test pager1-18.3.4 { 1837a748fdccSdrh # in this case, the value of x is loaded and so the error is 1838a748fdccSdrh # detected 1839a748fdccSdrh catchsql { SELECT length(x||'') FROM t2 } db2 1840c8ce3972Sdan} {1 {database disk image is malformed}} 1841c8ce3972Sdandb2 close 1842c8ce3972Sdando_test pager1-18.4 { 1843c8ce3972Sdan hexio_write test.db [expr ($pgno-1)*1024] 90000000 1844c8ce3972Sdan sqlite3 db2 test.db 1845a748fdccSdrh catchsql { SELECT length(x||'') FROM t2 } db2 1846c8ce3972Sdan} {1 {database disk image is malformed}} 1847c8ce3972Sdandb2 close 1848c8ce3972Sdando_test pager1-18.5 { 1849c8ce3972Sdan sqlite3 db "" 1850c8ce3972Sdan execsql { 1851c8ce3972Sdan CREATE TABLE t1(a, b); 1852c8ce3972Sdan CREATE TABLE t2(a, b); 1853c8ce3972Sdan PRAGMA writable_schema = 1; 1854c8ce3972Sdan UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1'; 1855c8ce3972Sdan PRAGMA writable_schema = 0; 1856c8ce3972Sdan ALTER TABLE t1 RENAME TO x1; 1857c8ce3972Sdan } 1858c8ce3972Sdan catchsql { SELECT * FROM x1 } 1859ba3cbf3dSdan} {1 {database disk image is malformed}} 1860c8ce3972Sdandb close 1861c8ce3972Sdan 1862ba3cbf3dSdando_test pager1-18.6 { 1863ba3cbf3dSdan faultsim_delete_and_reopen 1864ba3cbf3dSdan db func a_string a_string 1865ba3cbf3dSdan execsql { 1866ba3cbf3dSdan PRAGMA page_size = 1024; 1867ba3cbf3dSdan CREATE TABLE t1(x); 1868ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(800)); 1869ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(800)); 1870ba3cbf3dSdan } 1871ba3cbf3dSdan 1872ba3cbf3dSdan set root [db one "SELECT rootpage FROM sqlite_master"] 1873ba3cbf3dSdan db close 1874ba3cbf3dSdan 1875ba3cbf3dSdan hexio_write test.db [expr ($root-1)*1024 + 8] 00000000 1876ba3cbf3dSdan sqlite3 db test.db 1877ba3cbf3dSdan catchsql { SELECT length(x) FROM t1 } 1878ba3cbf3dSdan} {1 {database disk image is malformed}} 1879f4ba1093Sdan} 1880ba3cbf3dSdan 1881ba3cbf3dSdando_test pager1-19.1 { 1882ba3cbf3dSdan sqlite3 db "" 1883ba3cbf3dSdan db func a_string a_string 1884ba3cbf3dSdan execsql { 1885ba3cbf3dSdan PRAGMA page_size = 512; 1886ba3cbf3dSdan PRAGMA auto_vacuum = 1; 1887ba3cbf3dSdan CREATE TABLE t1(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, 1888ba3cbf3dSdan ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, 1889ba3cbf3dSdan ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, 1890ba3cbf3dSdan da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn, 1891ba3cbf3dSdan ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, 1892ba3cbf3dSdan fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, 1893ba3cbf3dSdan ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn, 1894ba3cbf3dSdan ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn, 1895ba3cbf3dSdan ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix, 1896ba3cbf3dSdan ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn, 1897ba3cbf3dSdan ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn, 1898ba3cbf3dSdan la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln, 1899ba3cbf3dSdan ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn 1900ba3cbf3dSdan ); 1901ba3cbf3dSdan CREATE TABLE t2(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, 1902ba3cbf3dSdan ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, 1903ba3cbf3dSdan ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, 1904ba3cbf3dSdan da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn, 1905ba3cbf3dSdan ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, 1906ba3cbf3dSdan fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, 1907ba3cbf3dSdan ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn, 1908ba3cbf3dSdan ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn, 1909ba3cbf3dSdan ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix, 1910ba3cbf3dSdan ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn, 1911ba3cbf3dSdan ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn, 1912ba3cbf3dSdan la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln, 1913ba3cbf3dSdan ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn 1914ba3cbf3dSdan ); 1915ba3cbf3dSdan INSERT INTO t1(aa) VALUES( a_string(100000) ); 1916ba3cbf3dSdan INSERT INTO t2(aa) VALUES( a_string(100000) ); 1917ba3cbf3dSdan VACUUM; 1918ba3cbf3dSdan } 1919ba3cbf3dSdan} {} 1920ba3cbf3dSdan 19216b63ab47Sdan#------------------------------------------------------------------------- 19226b63ab47Sdan# Test a couple of special cases that come up while committing 19236b63ab47Sdan# transactions: 19246b63ab47Sdan# 19256b63ab47Sdan# pager1-20.1.*: Committing an in-memory database transaction when the 19266b63ab47Sdan# database has not been modified at all. 19276b63ab47Sdan# 19286b63ab47Sdan# pager1-20.2.*: As above, but with a normal db in exclusive-locking mode. 19296b63ab47Sdan# 19306b63ab47Sdan# pager1-20.3.*: Committing a transaction in WAL mode where the database has 19316b63ab47Sdan# been modified, but all dirty pages have been flushed to 19326b63ab47Sdan# disk before the commit. 19336b63ab47Sdan# 19346b63ab47Sdando_test pager1-20.1.1 { 19356b63ab47Sdan catch {db close} 19366b63ab47Sdan sqlite3 db :memory: 19376b63ab47Sdan execsql { 19386b63ab47Sdan CREATE TABLE one(two, three); 19396b63ab47Sdan INSERT INTO one VALUES('a', 'b'); 19406b63ab47Sdan } 19416b63ab47Sdan} {} 19426b63ab47Sdando_test pager1-20.1.2 { 19436b63ab47Sdan execsql { 19446b63ab47Sdan BEGIN EXCLUSIVE; 19456b63ab47Sdan COMMIT; 19466b63ab47Sdan } 19476b63ab47Sdan} {} 19486b63ab47Sdan 19496b63ab47Sdando_test pager1-20.2.1 { 19506b63ab47Sdan faultsim_delete_and_reopen 19516b63ab47Sdan execsql { 19526b63ab47Sdan PRAGMA locking_mode = exclusive; 19536b63ab47Sdan PRAGMA journal_mode = persist; 19546b63ab47Sdan CREATE TABLE one(two, three); 19556b63ab47Sdan INSERT INTO one VALUES('a', 'b'); 19566b63ab47Sdan } 19576b63ab47Sdan} {exclusive persist} 19586b63ab47Sdando_test pager1-20.2.2 { 19596b63ab47Sdan execsql { 19606b63ab47Sdan BEGIN EXCLUSIVE; 19616b63ab47Sdan COMMIT; 19626b63ab47Sdan } 19636b63ab47Sdan} {} 19646b63ab47Sdan 19659091f775Sshanehifcapable wal { 19666b63ab47Sdan do_test pager1-20.3.1 { 19676b63ab47Sdan faultsim_delete_and_reopen 19686b63ab47Sdan db func a_string a_string 19696b63ab47Sdan execsql { 19706b63ab47Sdan PRAGMA cache_size = 10; 19716b63ab47Sdan PRAGMA journal_mode = wal; 19726b63ab47Sdan BEGIN; 19736b63ab47Sdan CREATE TABLE t1(x); 19746b63ab47Sdan CREATE TABLE t2(y); 19756b63ab47Sdan INSERT INTO t1 VALUES(a_string(800)); 19766b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 2 */ 19776b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 4 */ 19786b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 8 */ 19796b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 16 */ 19806b63ab47Sdan INSERT INTO t1 SELECT a_string(800) FROM t1; /* 32 */ 19816b63ab47Sdan COMMIT; 19826b63ab47Sdan } 19836b63ab47Sdan } {wal} 19846b63ab47Sdan do_test pager1-20.3.2 { 19856b63ab47Sdan execsql { 19866b63ab47Sdan BEGIN; 19876b63ab47Sdan INSERT INTO t2 VALUES('xxxx'); 19886b63ab47Sdan } 1989c396d4afSdan recursive_select 32 t1 19906b63ab47Sdan execsql COMMIT 19916b63ab47Sdan } {} 19929091f775Sshaneh} 19936b63ab47Sdan 199489ccf448Sdan#------------------------------------------------------------------------- 199589ccf448Sdan# Test that a WAL database may not be opened if: 199689ccf448Sdan# 199789ccf448Sdan# pager1-21.1.*: The VFS has an iVersion less than 2, or 199889ccf448Sdan# pager1-21.2.*: The VFS does not provide xShmXXX() methods. 199989ccf448Sdan# 20009091f775Sshanehifcapable wal { 200189ccf448Sdan do_test pager1-21.0 { 200289ccf448Sdan faultsim_delete_and_reopen 200389ccf448Sdan execsql { 200489ccf448Sdan PRAGMA journal_mode = WAL; 200589ccf448Sdan CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def'); 200689ccf448Sdan INSERT INTO ko DEFAULT VALUES; 200789ccf448Sdan } 200889ccf448Sdan } {wal} 200989ccf448Sdan do_test pager1-21.1 { 201089ccf448Sdan testvfs tv -noshm 1 201189ccf448Sdan sqlite3 db2 test.db -vfs tv 201289ccf448Sdan catchsql { SELECT * FROM ko } db2 201389ccf448Sdan } {1 {unable to open database file}} 201489ccf448Sdan db2 close 201589ccf448Sdan tv delete 201689ccf448Sdan do_test pager1-21.2 { 201789ccf448Sdan testvfs tv -iversion 1 201889ccf448Sdan sqlite3 db2 test.db -vfs tv 201989ccf448Sdan catchsql { SELECT * FROM ko } db2 202089ccf448Sdan } {1 {unable to open database file}} 202189ccf448Sdan db2 close 202289ccf448Sdan tv delete 20239091f775Sshaneh} 202489ccf448Sdan 202589ccf448Sdan#------------------------------------------------------------------------- 202689ccf448Sdan# Test that a "PRAGMA wal_checkpoint": 202789ccf448Sdan# 202889ccf448Sdan# pager1-22.1.*: is a no-op on a non-WAL db, and 202989ccf448Sdan# pager1-22.2.*: does not cause xSync calls with a synchronous=off db. 203089ccf448Sdan# 20315209132aSdanifcapable wal { 203289ccf448Sdan do_test pager1-22.1.1 { 203389ccf448Sdan faultsim_delete_and_reopen 203489ccf448Sdan execsql { 203589ccf448Sdan CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def'); 203689ccf448Sdan INSERT INTO ko DEFAULT VALUES; 203789ccf448Sdan } 203889ccf448Sdan execsql { PRAGMA wal_checkpoint } 2039bdd9af0fSdan } {0 -1 -1} 204089ccf448Sdan do_test pager1-22.2.1 { 204189ccf448Sdan testvfs tv -default 1 204289ccf448Sdan tv filter xSync 204389ccf448Sdan tv script xSyncCb 204489ccf448Sdan proc xSyncCb {args} {incr ::synccount} 204589ccf448Sdan set ::synccount 0 204689ccf448Sdan sqlite3 db test.db 204789ccf448Sdan execsql { 204889ccf448Sdan PRAGMA synchronous = off; 204989ccf448Sdan PRAGMA journal_mode = WAL; 205089ccf448Sdan INSERT INTO ko DEFAULT VALUES; 205189ccf448Sdan } 205289ccf448Sdan execsql { PRAGMA wal_checkpoint } 205389ccf448Sdan set synccount 205489ccf448Sdan } {0} 205589ccf448Sdan db close 205689ccf448Sdan tv delete 20575209132aSdan} 205889ccf448Sdan 205989ccf448Sdan#------------------------------------------------------------------------- 206089ccf448Sdan# Tests for changing journal mode. 206189ccf448Sdan# 206289ccf448Sdan# pager1-23.1.*: Test that when changing from PERSIST to DELETE mode, 206389ccf448Sdan# the journal file is deleted. 206489ccf448Sdan# 206589ccf448Sdan# pager1-23.2.*: Same test as above, but while a shared lock is held 206689ccf448Sdan# on the database file. 206789ccf448Sdan# 206889ccf448Sdan# pager1-23.3.*: Same test as above, but while a reserved lock is held 206989ccf448Sdan# on the database file. 207089ccf448Sdan# 207189ccf448Sdan# pager1-23.4.*: And, for fun, while holding an exclusive lock. 207289ccf448Sdan# 207389ccf448Sdan# pager1-23.5.*: Try to set various different journal modes with an 207489ccf448Sdan# in-memory database (only MEMORY and OFF should work). 207589ccf448Sdan# 2076d0b0d4dcSdan# pager1-23.6.*: Try to set locking_mode=normal on an in-memory database 2077d0b0d4dcSdan# (doesn't work - in-memory databases always use 2078d0b0d4dcSdan# locking_mode=exclusive). 2079d0b0d4dcSdan# 208089ccf448Sdando_test pager1-23.1.1 { 208189ccf448Sdan faultsim_delete_and_reopen 208289ccf448Sdan execsql { 208389ccf448Sdan PRAGMA journal_mode = PERSIST; 208489ccf448Sdan CREATE TABLE t1(a, b); 208589ccf448Sdan } 208689ccf448Sdan file exists test.db-journal 208789ccf448Sdan} {1} 208889ccf448Sdando_test pager1-23.1.2 { 208989ccf448Sdan execsql { PRAGMA journal_mode = DELETE } 209089ccf448Sdan file exists test.db-journal 209189ccf448Sdan} {0} 209289ccf448Sdan 209389ccf448Sdando_test pager1-23.2.1 { 209489ccf448Sdan execsql { 209589ccf448Sdan PRAGMA journal_mode = PERSIST; 209689ccf448Sdan INSERT INTO t1 VALUES('Canberra', 'ACT'); 209789ccf448Sdan } 209889ccf448Sdan db eval { SELECT * FROM t1 } { 209989ccf448Sdan db eval { PRAGMA journal_mode = DELETE } 210089ccf448Sdan } 210189ccf448Sdan execsql { PRAGMA journal_mode } 210289ccf448Sdan} {delete} 210389ccf448Sdando_test pager1-23.2.2 { 210489ccf448Sdan file exists test.db-journal 210589ccf448Sdan} {0} 210689ccf448Sdan 210789ccf448Sdando_test pager1-23.3.1 { 210889ccf448Sdan execsql { 210989ccf448Sdan PRAGMA journal_mode = PERSIST; 211089ccf448Sdan INSERT INTO t1 VALUES('Darwin', 'NT'); 211189ccf448Sdan BEGIN IMMEDIATE; 211289ccf448Sdan } 211389ccf448Sdan db eval { PRAGMA journal_mode = DELETE } 211489ccf448Sdan execsql { PRAGMA journal_mode } 211589ccf448Sdan} {delete} 211689ccf448Sdando_test pager1-23.3.2 { 211789ccf448Sdan file exists test.db-journal 211889ccf448Sdan} {0} 211989ccf448Sdando_test pager1-23.3.3 { 212089ccf448Sdan execsql COMMIT 212189ccf448Sdan} {} 212289ccf448Sdan 212389ccf448Sdando_test pager1-23.4.1 { 212489ccf448Sdan execsql { 212589ccf448Sdan PRAGMA journal_mode = PERSIST; 212689ccf448Sdan INSERT INTO t1 VALUES('Adelaide', 'SA'); 212789ccf448Sdan BEGIN EXCLUSIVE; 212889ccf448Sdan } 212989ccf448Sdan db eval { PRAGMA journal_mode = DELETE } 213089ccf448Sdan execsql { PRAGMA journal_mode } 213189ccf448Sdan} {delete} 213289ccf448Sdando_test pager1-23.4.2 { 213389ccf448Sdan file exists test.db-journal 213489ccf448Sdan} {0} 213589ccf448Sdando_test pager1-23.4.3 { 213689ccf448Sdan execsql COMMIT 213789ccf448Sdan} {} 213889ccf448Sdan 213989ccf448Sdando_test pager1-23.5.1 { 214089ccf448Sdan faultsim_delete_and_reopen 214189ccf448Sdan sqlite3 db :memory: 214289ccf448Sdan} {} 214389ccf448Sdanforeach {tn mode possible} { 214489ccf448Sdan 2 off 1 214589ccf448Sdan 3 memory 1 214689ccf448Sdan 4 persist 0 214789ccf448Sdan 5 delete 0 214889ccf448Sdan 6 wal 0 214989ccf448Sdan 7 truncate 0 215089ccf448Sdan} { 215189ccf448Sdan do_test pager1-23.5.$tn.1 { 215289ccf448Sdan execsql "PRAGMA journal_mode = off" 215389ccf448Sdan execsql "PRAGMA journal_mode = $mode" 215489ccf448Sdan } [if $possible {list $mode} {list off}] 215589ccf448Sdan do_test pager1-23.5.$tn.2 { 215689ccf448Sdan execsql "PRAGMA journal_mode = memory" 215789ccf448Sdan execsql "PRAGMA journal_mode = $mode" 215889ccf448Sdan } [if $possible {list $mode} {list memory}] 215989ccf448Sdan} 2160d0b0d4dcSdando_test pager1-23.6.1 { 216189ccf448Sdan execsql {PRAGMA locking_mode = normal} 216289ccf448Sdan} {exclusive} 2163d0b0d4dcSdando_test pager1-23.6.2 { 216489ccf448Sdan execsql {PRAGMA locking_mode = exclusive} 216589ccf448Sdan} {exclusive} 2166d0b0d4dcSdando_test pager1-23.6.3 { 216789ccf448Sdan execsql {PRAGMA locking_mode} 216889ccf448Sdan} {exclusive} 2169d0b0d4dcSdando_test pager1-23.6.4 { 217089ccf448Sdan execsql {PRAGMA main.locking_mode} 217189ccf448Sdan} {exclusive} 21726b63ab47Sdan 2173d0b0d4dcSdan#------------------------------------------------------------------------- 2174d0b0d4dcSdan# 2175d0b0d4dcSdando_test pager1-24.1.1 { 2176d0b0d4dcSdan faultsim_delete_and_reopen 2177d0b0d4dcSdan db func a_string a_string 2178d0b0d4dcSdan execsql { 2179d0b0d4dcSdan PRAGMA cache_size = 10; 2180d0b0d4dcSdan PRAGMA auto_vacuum = FULL; 2181d0b0d4dcSdan CREATE TABLE x1(x, y, z, PRIMARY KEY(y, z)); 2182d0b0d4dcSdan CREATE TABLE x2(x, y, z, PRIMARY KEY(y, z)); 2183d0b0d4dcSdan INSERT INTO x2 VALUES(a_string(400), a_string(500), a_string(600)); 2184d0b0d4dcSdan INSERT INTO x2 SELECT a_string(600), a_string(400), a_string(500) FROM x2; 2185d0b0d4dcSdan INSERT INTO x2 SELECT a_string(500), a_string(600), a_string(400) FROM x2; 2186d0b0d4dcSdan INSERT INTO x2 SELECT a_string(400), a_string(500), a_string(600) FROM x2; 2187d0b0d4dcSdan INSERT INTO x2 SELECT a_string(600), a_string(400), a_string(500) FROM x2; 2188d0b0d4dcSdan INSERT INTO x2 SELECT a_string(500), a_string(600), a_string(400) FROM x2; 2189d0b0d4dcSdan INSERT INTO x2 SELECT a_string(400), a_string(500), a_string(600) FROM x2; 2190d0b0d4dcSdan INSERT INTO x1 SELECT * FROM x2; 2191d0b0d4dcSdan } 2192d0b0d4dcSdan} {} 2193d0b0d4dcSdando_test pager1-24.1.2 { 2194d0b0d4dcSdan execsql { 2195d0b0d4dcSdan BEGIN; 2196d0b0d4dcSdan DELETE FROM x1 WHERE rowid<32; 2197d0b0d4dcSdan } 2198c396d4afSdan recursive_select 64 x2 2199d0b0d4dcSdan} {} 2200d0b0d4dcSdando_test pager1-24.1.3 { 2201d0b0d4dcSdan execsql { 2202d0b0d4dcSdan UPDATE x1 SET z = a_string(300) WHERE rowid>40; 2203d0b0d4dcSdan COMMIT; 2204d0b0d4dcSdan PRAGMA integrity_check; 2205d0b0d4dcSdan SELECT count(*) FROM x1; 2206d0b0d4dcSdan } 2207d0b0d4dcSdan} {ok 33} 2208d0b0d4dcSdan 2209d0b0d4dcSdando_test pager1-24.1.4 { 2210d0b0d4dcSdan execsql { 2211d0b0d4dcSdan DELETE FROM x1; 2212d0b0d4dcSdan INSERT INTO x1 SELECT * FROM x2; 2213d0b0d4dcSdan BEGIN; 2214d0b0d4dcSdan DELETE FROM x1 WHERE rowid<32; 2215d0b0d4dcSdan UPDATE x1 SET z = a_string(299) WHERE rowid>40; 2216d0b0d4dcSdan } 2217c396d4afSdan recursive_select 64 x2 {db eval COMMIT} 2218d0b0d4dcSdan execsql { 2219d0b0d4dcSdan PRAGMA integrity_check; 2220d0b0d4dcSdan SELECT count(*) FROM x1; 2221d0b0d4dcSdan } 2222d0b0d4dcSdan} {ok 33} 2223d0b0d4dcSdan 2224d0b0d4dcSdando_test pager1-24.1.5 { 2225d0b0d4dcSdan execsql { 2226d0b0d4dcSdan DELETE FROM x1; 2227d0b0d4dcSdan INSERT INTO x1 SELECT * FROM x2; 2228d0b0d4dcSdan } 2229c396d4afSdan recursive_select 64 x2 { db eval {CREATE TABLE x3(x, y, z)} } 2230d0b0d4dcSdan execsql { SELECT * FROM x3 } 2231d0b0d4dcSdan} {} 2232d0b0d4dcSdan 2233d0b0d4dcSdan#------------------------------------------------------------------------- 2234d0b0d4dcSdan# 2235d0b0d4dcSdando_test pager1-25-1 { 2236d0b0d4dcSdan faultsim_delete_and_reopen 2237d0b0d4dcSdan execsql { 2238d0b0d4dcSdan BEGIN; 2239d0b0d4dcSdan SAVEPOINT abc; 2240d0b0d4dcSdan CREATE TABLE t1(a, b); 2241d0b0d4dcSdan ROLLBACK TO abc; 2242d0b0d4dcSdan COMMIT; 2243d0b0d4dcSdan } 2244d0b0d4dcSdan db close 2245d0b0d4dcSdan} {} 2246d0b0d4dcSdanbreakpoint 2247d0b0d4dcSdando_test pager1-25-2 { 2248d0b0d4dcSdan faultsim_delete_and_reopen 2249d0b0d4dcSdan execsql { 2250d0b0d4dcSdan SAVEPOINT abc; 2251d0b0d4dcSdan CREATE TABLE t1(a, b); 2252d0b0d4dcSdan ROLLBACK TO abc; 2253d0b0d4dcSdan COMMIT; 2254d0b0d4dcSdan } 2255d0b0d4dcSdan db close 2256d0b0d4dcSdan} {} 22576b63ab47Sdan 2258c396d4afSdan#------------------------------------------------------------------------- 2259c396d4afSdan# Sector-size tests. 2260c396d4afSdan# 2261c396d4afSdando_test pager1-26.1 { 2262c396d4afSdan testvfs tv -default 1 2263c396d4afSdan tv sectorsize 4096 2264c396d4afSdan faultsim_delete_and_reopen 2265c396d4afSdan db func a_string a_string 2266c396d4afSdan execsql { 2267c396d4afSdan PRAGMA page_size = 512; 2268c396d4afSdan CREATE TABLE tbl(a PRIMARY KEY, b UNIQUE); 2269c396d4afSdan BEGIN; 2270c396d4afSdan INSERT INTO tbl VALUES(a_string(25), a_string(600)); 2271c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2272c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2273c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2274c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2275c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2276c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2277c396d4afSdan INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; 2278c396d4afSdan COMMIT; 2279c396d4afSdan } 2280c396d4afSdan} {} 2281c396d4afSdando_execsql_test pager1-26.1 { 2282c396d4afSdan UPDATE tbl SET b = a_string(550); 2283c396d4afSdan} {} 2284c396d4afSdandb close 2285c396d4afSdantv delete 2286c396d4afSdan 2287c396d4afSdan#------------------------------------------------------------------------- 228822b328b2Sdan# 2289c396d4afSdando_test pager1.27.1 { 2290c396d4afSdan faultsim_delete_and_reopen 2291c396d4afSdan sqlite3_pager_refcounts db 2292c396d4afSdan execsql { 2293c396d4afSdan BEGIN; 2294c396d4afSdan CREATE TABLE t1(a, b); 2295c396d4afSdan } 2296c396d4afSdan sqlite3_pager_refcounts db 2297c396d4afSdan execsql COMMIT 2298c396d4afSdan} {} 2299c396d4afSdan 230022b328b2Sdan#------------------------------------------------------------------------- 230122b328b2Sdan# Test that attempting to open a write-transaction with 230222b328b2Sdan# locking_mode=exclusive in WAL mode fails if there are other clients on 230322b328b2Sdan# the same database. 230422b328b2Sdan# 230522b328b2Sdancatch { db close } 23069091f775Sshanehifcapable wal { 230722b328b2Sdan do_multiclient_test tn { 230822b328b2Sdan do_test pager1-28.$tn.1 { 230922b328b2Sdan sql1 { 231022b328b2Sdan PRAGMA journal_mode = WAL; 231122b328b2Sdan CREATE TABLE t1(a, b); 231222b328b2Sdan INSERT INTO t1 VALUES('a', 'b'); 231322b328b2Sdan } 231422b328b2Sdan } {wal} 231522b328b2Sdan do_test pager1-28.$tn.2 { sql2 { SELECT * FROM t1 } } {a b} 231622b328b2Sdan 231722b328b2Sdan do_test pager1-28.$tn.3 { sql1 { PRAGMA locking_mode=exclusive } } {exclusive} 231822b328b2Sdan do_test pager1-28.$tn.4 { 231922b328b2Sdan csql1 { BEGIN; INSERT INTO t1 VALUES('c', 'd'); } 232022b328b2Sdan } {1 {database is locked}} 232122b328b2Sdan code2 { db2 close ; sqlite3 db2 test.db } 232222b328b2Sdan do_test pager1-28.$tn.4 { 232322b328b2Sdan sql1 { INSERT INTO t1 VALUES('c', 'd'); COMMIT } 232422b328b2Sdan } {} 232522b328b2Sdan } 23269091f775Sshaneh} 23275653e4daSdan 23285653e4daSdan#------------------------------------------------------------------------- 23295653e4daSdan# Normally, when changing from journal_mode=PERSIST to DELETE the pager 23305653e4daSdan# attempts to delete the journal file. However, if it cannot obtain a 23315653e4daSdan# RESERVED lock on the database file, this step is skipped. 23325653e4daSdan# 23335653e4daSdando_multiclient_test tn { 23345653e4daSdan do_test pager1-28.$tn.1 { 23355653e4daSdan sql1 { 23365653e4daSdan PRAGMA journal_mode = PERSIST; 23375653e4daSdan CREATE TABLE t1(a, b); 23385653e4daSdan INSERT INTO t1 VALUES('a', 'b'); 23395653e4daSdan } 23405653e4daSdan } {persist} 23415653e4daSdan do_test pager1-28.$tn.2 { file exists test.db-journal } 1 23425653e4daSdan do_test pager1-28.$tn.3 { sql1 { PRAGMA journal_mode = DELETE } } delete 23435653e4daSdan do_test pager1-28.$tn.4 { file exists test.db-journal } 0 23445653e4daSdan 23455653e4daSdan do_test pager1-28.$tn.5 { 23465653e4daSdan sql1 { 23475653e4daSdan PRAGMA journal_mode = PERSIST; 23485653e4daSdan INSERT INTO t1 VALUES('c', 'd'); 23495653e4daSdan } 23505653e4daSdan } {persist} 23515653e4daSdan do_test pager1-28.$tn.6 { file exists test.db-journal } 1 23525653e4daSdan do_test pager1-28.$tn.7 { 23535653e4daSdan sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); } 23545653e4daSdan } {} 23555653e4daSdan do_test pager1-28.$tn.8 { file exists test.db-journal } 1 23565653e4daSdan do_test pager1-28.$tn.9 { sql1 { PRAGMA journal_mode = DELETE } } delete 23575653e4daSdan do_test pager1-28.$tn.10 { file exists test.db-journal } 1 23585653e4daSdan 23595653e4daSdan do_test pager1-28.$tn.11 { sql2 COMMIT } {} 23605653e4daSdan do_test pager1-28.$tn.12 { file exists test.db-journal } 0 23615653e4daSdan 23625653e4daSdan do_test pager1-28-$tn.13 { 23635653e4daSdan code1 { set channel [db incrblob -readonly t1 a 2] } 23645653e4daSdan sql1 { 23655653e4daSdan PRAGMA journal_mode = PERSIST; 23665653e4daSdan INSERT INTO t1 VALUES('g', 'h'); 23675653e4daSdan } 23685653e4daSdan } {persist} 23695653e4daSdan do_test pager1-28.$tn.14 { file exists test.db-journal } 1 23705653e4daSdan do_test pager1-28.$tn.15 { 23715653e4daSdan sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); } 23725653e4daSdan } {} 23735653e4daSdan do_test pager1-28.$tn.16 { sql1 { PRAGMA journal_mode = DELETE } } delete 23745653e4daSdan do_test pager1-28.$tn.17 { file exists test.db-journal } 1 23755653e4daSdan 23765653e4daSdan do_test pager1-28.$tn.17 { csql2 { COMMIT } } {1 {database is locked}} 23775653e4daSdan do_test pager1-28-$tn.18 { code1 { read $channel } } c 23785653e4daSdan do_test pager1-28-$tn.19 { code1 { close $channel } } {} 23795653e4daSdan do_test pager1-28.$tn.20 { sql2 { COMMIT } } {} 23805653e4daSdan} 23815653e4daSdan 23821879b088Sdando_test pager1-29.1 { 23831879b088Sdan faultsim_delete_and_reopen 23841879b088Sdan execsql { 23851879b088Sdan PRAGMA page_size = 1024; 23861879b088Sdan PRAGMA auto_vacuum = full; 23871879b088Sdan PRAGMA locking_mode=exclusive; 23881879b088Sdan CREATE TABLE t1(a, b); 23891879b088Sdan INSERT INTO t1 VALUES(1, 2); 23901879b088Sdan } 23911879b088Sdan file size test.db 23921879b088Sdan} [expr 1024*3] 23931879b088Sdando_test pager1-29.2 { 23941879b088Sdan execsql { 23951879b088Sdan PRAGMA page_size = 4096; 23961879b088Sdan VACUUM; 23971879b088Sdan } 23981879b088Sdan file size test.db 23991879b088Sdan} [expr 4096*3] 24001879b088Sdan 2401e08c2066Sdan#------------------------------------------------------------------------- 2402e08c2066Sdan# Test that if an empty database file (size 0 bytes) is opened in 2403e08c2066Sdan# exclusive-locking mode, any journal file is deleted from the file-system 2404e08c2066Sdan# without being rolled back. And that the RESERVED lock obtained while 2405e08c2066Sdan# doing this is not released. 2406e08c2066Sdan# 2407e08c2066Sdando_test pager1-30.1 { 2408e08c2066Sdan db close 2409fda06befSmistachkin delete_file test.db 2410fda06befSmistachkin delete_file test.db-journal 2411e08c2066Sdan set fd [open test.db-journal w] 2412e08c2066Sdan seek $fd [expr 512+1032*2] 2413e08c2066Sdan puts -nonewline $fd x 2414e08c2066Sdan close $fd 2415e08c2066Sdan 2416e08c2066Sdan sqlite3 db test.db 2417e08c2066Sdan execsql { 2418e08c2066Sdan PRAGMA locking_mode=EXCLUSIVE; 2419e08c2066Sdan SELECT count(*) FROM sqlite_master; 2420e08c2066Sdan PRAGMA lock_status; 2421e08c2066Sdan } 2422e08c2066Sdan} {exclusive 0 main reserved temp closed} 2423e08c2066Sdan 2424e08c2066Sdan#------------------------------------------------------------------------- 2425e08c2066Sdan# Test that if the "page-size" field in a journal-header is 0, the journal 2426e08c2066Sdan# file can still be rolled back. This is required for backward compatibility - 2427e08c2066Sdan# versions of SQLite prior to 3.5.8 always set this field to zero. 2428e08c2066Sdan# 242933f5379cSdanif {$tcl_platform(platform)=="unix"} { 2430e08c2066Sdando_test pager1-31.1 { 2431e08c2066Sdan faultsim_delete_and_reopen 2432e08c2066Sdan execsql { 2433e08c2066Sdan PRAGMA cache_size = 10; 2434e08c2066Sdan PRAGMA page_size = 1024; 2435e08c2066Sdan CREATE TABLE t1(x, y, UNIQUE(x, y)); 2436e08c2066Sdan INSERT INTO t1 VALUES(randomblob(1500), randomblob(1500)); 2437e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2438e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2439e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2440e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2441e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2442e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2443e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2444e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2445e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2446e08c2066Sdan INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; 2447e08c2066Sdan BEGIN; 2448e08c2066Sdan UPDATE t1 SET y = randomblob(1499); 2449e08c2066Sdan } 2450fda06befSmistachkin copy_file test.db test.db2 2451fda06befSmistachkin copy_file test.db-journal test.db2-journal 2452e08c2066Sdan 2453e08c2066Sdan hexio_write test.db2-journal 24 00000000 2454e08c2066Sdan sqlite3 db2 test.db2 2455e08c2066Sdan execsql { PRAGMA integrity_check } db2 2456e08c2066Sdan} {ok} 245733f5379cSdan} 2458e08c2066Sdan 245931e80976Sdrh#------------------------------------------------------------------------- 246031e80976Sdrh# Test that a database file can be "pre-hinted" to a certain size and that 246131e80976Sdrh# subsequent spilling of the pager cache does not result in the database 246231e80976Sdrh# file being shrunk. 246331e80976Sdrh# 246431e80976Sdrhcatch {db close} 246531e80976Sdrhforcedelete test.db 246631e80976Sdrh 246731e80976Sdrhdo_test pager1-32.1 { 246831e80976Sdrh sqlite3 db test.db 246931e80976Sdrh execsql { 247031e80976Sdrh CREATE TABLE t1(x, y); 247131e80976Sdrh } 247231e80976Sdrh db close 247331e80976Sdrh sqlite3 db test.db 247431e80976Sdrh execsql { 247531e80976Sdrh BEGIN; 247631e80976Sdrh INSERT INTO t1 VALUES(1, randomblob(10000)); 247731e80976Sdrh } 24782f7820d8Sdrh file_control_chunksize_test db main 1024 247931e80976Sdrh file_control_sizehint_test db main 20971520; # 20MB 248031e80976Sdrh execsql { 248131e80976Sdrh PRAGMA cache_size = 10; 248231e80976Sdrh INSERT INTO t1 VALUES(1, randomblob(10000)); 248331e80976Sdrh INSERT INTO t1 VALUES(2, randomblob(10000)); 248431e80976Sdrh INSERT INTO t1 SELECT x+2, randomblob(10000) from t1; 248531e80976Sdrh INSERT INTO t1 SELECT x+4, randomblob(10000) from t1; 248631e80976Sdrh INSERT INTO t1 SELECT x+8, randomblob(10000) from t1; 248731e80976Sdrh INSERT INTO t1 SELECT x+16, randomblob(10000) from t1; 248831e80976Sdrh SELECT count(*) FROM t1; 248931e80976Sdrh COMMIT; 249031e80976Sdrh } 249131e80976Sdrh db close 249231e80976Sdrh file size test.db 249331e80976Sdrh} {20971520} 249431e80976Sdrh 249531e80976Sdrh# Cleanup 20MB file left by the previous test. 249631e80976Sdrhforcedelete test.db 24975653e4daSdan 24989fc5b4a5Sdan#------------------------------------------------------------------------- 24999fc5b4a5Sdan# Test that if a transaction is committed in journal_mode=DELETE mode, 25009fc5b4a5Sdan# and the call to unlink() returns an ENOENT error, the COMMIT does not 25019fc5b4a5Sdan# succeed. 25029fc5b4a5Sdan# 25039fc5b4a5Sdanif {$::tcl_platform(platform)=="unix"} { 25049fc5b4a5Sdan do_test pager1-33.1 { 25059fc5b4a5Sdan sqlite3 db test.db 25069fc5b4a5Sdan execsql { 25079fc5b4a5Sdan CREATE TABLE t1(x); 25089fc5b4a5Sdan INSERT INTO t1 VALUES('one'); 25099fc5b4a5Sdan INSERT INTO t1 VALUES('two'); 25109fc5b4a5Sdan BEGIN; 25119fc5b4a5Sdan INSERT INTO t1 VALUES('three'); 25129fc5b4a5Sdan INSERT INTO t1 VALUES('four'); 25139fc5b4a5Sdan } 25149fc5b4a5Sdan forcedelete bak-journal 25159fc5b4a5Sdan file rename test.db-journal bak-journal 25169fc5b4a5Sdan 25179fc5b4a5Sdan catchsql COMMIT 25189fc5b4a5Sdan } {1 {disk I/O error}} 25199fc5b4a5Sdan 25209fc5b4a5Sdan do_test pager1-33.2 { 25219fc5b4a5Sdan file rename bak-journal test.db-journal 25229fc5b4a5Sdan execsql { SELECT * FROM t1 } 25239fc5b4a5Sdan } {one two} 25249fc5b4a5Sdan} 25259fc5b4a5Sdan 2526d353331aSdanfinish_test 2527