1e91a54e1Sdan# 2010 June 15 2e91a54e1Sdan# 3e91a54e1Sdan# The author disclaims copyright to this source code. In place of 4e91a54e1Sdan# a legal notice, here is a blessing: 5e91a54e1Sdan# 6e91a54e1Sdan# May you do good and not evil. 7e91a54e1Sdan# May you find forgiveness for yourself and forgive others. 8e91a54e1Sdan# May you share freely, never taking more than you give. 9e91a54e1Sdan# 10e91a54e1Sdan#*********************************************************************** 11e91a54e1Sdan# 12e91a54e1Sdan 13e91a54e1Sdanset testdir [file dirname $argv0] 14e91a54e1Sdansource $testdir/tester.tcl 15e91a54e1Sdansource $testdir/lock_common.tcl 16e91a54e1Sdansource $testdir/malloc_common.tcl 17153eda0aSdansource $testdir/wal_common.tcl 1868928b6cSdan 1968928b6cSdan# Do not use a codec for tests in this file, as the database file is 2068928b6cSdan# manipulated directly using tcl scripts (using the [hexio_write] command). 2168928b6cSdan# 2268928b6cSdando_not_use_codec 23e91a54e1Sdan 24b0ac3e3aSdan# 25b0ac3e3aSdan# pager1-1.*: Test inter-process locking (clients in multiple processes). 26b0ac3e3aSdan# 27b0ac3e3aSdan# pager1-2.*: Test intra-process locking (multiple clients in this process). 28b0ac3e3aSdan# 29b0ac3e3aSdan# pager1-3.*: Savepoint related tests. 30b0ac3e3aSdan# 311f4cb65aSdan# pager1-4.*: Hot-journal related tests. 321f4cb65aSdan# 33de4996e2Sdan# pager1-5.*: Cases related to multi-file commits. 34de4996e2Sdan# 35146ed78bSdan# pager1-6.*: Cases related to "PRAGMA max_page_count" 36146ed78bSdan# 37153eda0aSdan# pager1-7.*: Cases specific to "PRAGMA journal_mode=TRUNCATE" 38153eda0aSdan# 390e986f51Sdan# pager1-8.*: Cases using temporary and in-memory databases. 400e986f51Sdan# 41dca321aeSdan# pager1-9.*: Tests related to the backup API. 42dca321aeSdan# 43ec6ffc1aSdan# pager1-10.*: Test that the assumed file-system sector-size is limited to 44ec6ffc1aSdan# 64KB. 45ec6ffc1aSdan# 46d353331aSdan# pager1-12.*: Tests involving "PRAGMA page_size" 47d353331aSdan# 48d353331aSdan# pager1-13.*: Cases specific to "PRAGMA journal_mode=PERSIST" 49d353331aSdan# 50d353331aSdan# pager1-14.*: Cases specific to "PRAGMA journal_mode=OFF" 51ec6ffc1aSdan# 52c8ce3972Sdan# pager1-15.*: Varying sqlite3_vfs.szOsFile 53c8ce3972Sdan# 54c8ce3972Sdan# pager1-16.*: Varying sqlite3_vfs.mxPathname 55c8ce3972Sdan# 56c8ce3972Sdan# pager1-17.*: Tests related to "PRAGMA omit_readlock" 57c8ce3972Sdan# 58c8ce3972Sdan# pager1-18.*: Test that the pager layer responds correctly if the b-tree 59c8ce3972Sdan# requests an invalid page number (due to db corruption). 60c8ce3972Sdan# 61b0ac3e3aSdan 6253f04f3bSdanset a_string_counter 1 6353f04f3bSdanproc a_string {n} { 6453f04f3bSdan global a_string_counter 6553f04f3bSdan incr a_string_counter 6653f04f3bSdan string range [string repeat "${a_string_counter}." $n] 1 $n 6753f04f3bSdan} 6853f04f3bSdandb func a_string a_string 6953f04f3bSdan 70a4a9095eSdando_multiclient_test tn { 71e91a54e1Sdan 72e91a54e1Sdan # Create and populate a database table using connection [db]. Check 73e91a54e1Sdan # that connections [db2] and [db3] can see the schema and content. 74e91a54e1Sdan # 75e91a54e1Sdan do_test pager1-$tn.1 { 76e91a54e1Sdan sql1 { 77e91a54e1Sdan CREATE TABLE t1(a PRIMARY KEY, b); 78e91a54e1Sdan CREATE INDEX i1 ON t1(b); 79d353331aSdan INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); 80e91a54e1Sdan } 81e91a54e1Sdan } {} 82e91a54e1Sdan do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two} 83e91a54e1Sdan do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two} 84e91a54e1Sdan 85e91a54e1Sdan # Open a transaction and add a row using [db]. This puts [db] in 86e91a54e1Sdan # RESERVED state. Check that connections [db2] and [db3] can still 87e91a54e1Sdan # read the database content as it was before the transaction was 88e91a54e1Sdan # opened. [db] should see the inserted row. 89e91a54e1Sdan # 90e91a54e1Sdan do_test pager1-$tn.4 { 91e91a54e1Sdan sql1 { 92e91a54e1Sdan BEGIN; 93e91a54e1Sdan INSERT INTO t1 VALUES(3, 'three'); 94e91a54e1Sdan } 95e91a54e1Sdan } {} 96e91a54e1Sdan do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two} 97e91a54e1Sdan do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} 98e91a54e1Sdan 99e91a54e1Sdan # [db] still has an open write transaction. Check that this prevents 100e91a54e1Sdan # other connections (specifically [db2]) from writing to the database. 101e91a54e1Sdan # 102e91a54e1Sdan # Even if [db2] opens a transaction first, it may not write to the 103e91a54e1Sdan # database. After the attempt to write the db within a transaction, 104e91a54e1Sdan # [db2] is left with an open transaction, but not a read-lock on 105e91a54e1Sdan # the main database. So it does not prevent [db] from committing. 106e91a54e1Sdan # 107e91a54e1Sdan do_test pager1-$tn.8 { 108e91a54e1Sdan csql2 { UPDATE t1 SET a = a + 10 } 109e91a54e1Sdan } {1 {database is locked}} 110e91a54e1Sdan do_test pager1-$tn.9 { 111e91a54e1Sdan csql2 { 112e91a54e1Sdan BEGIN; 113e91a54e1Sdan UPDATE t1 SET a = a + 10; 114e91a54e1Sdan } 115e91a54e1Sdan } {1 {database is locked}} 116e91a54e1Sdan 117e91a54e1Sdan # Have [db] commit its transactions. Check the other connections can 118e91a54e1Sdan # now see the new database content. 119e91a54e1Sdan # 120e91a54e1Sdan do_test pager1-$tn.10 { sql1 { COMMIT } } {} 121e91a54e1Sdan do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} 122e91a54e1Sdan do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 123e91a54e1Sdan do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 124e91a54e1Sdan 125e91a54e1Sdan # Check that, as noted above, [db2] really did keep an open transaction 126e91a54e1Sdan # after the attempt to write the database failed. 127e91a54e1Sdan # 128e91a54e1Sdan do_test pager1-$tn.14 { 129e91a54e1Sdan csql2 { BEGIN } 130e91a54e1Sdan } {1 {cannot start a transaction within a transaction}} 131e91a54e1Sdan do_test pager1-$tn.15 { sql2 { ROLLBACK } } {} 132e91a54e1Sdan 133e91a54e1Sdan # Have [db2] open a transaction and take a read-lock on the database. 134e91a54e1Sdan # Check that this prevents [db] from writing to the database (outside 135e91a54e1Sdan # of any transaction). After this fails, check that [db3] can read 136e91a54e1Sdan # the db (showing that [db] did not take a PENDING lock etc.) 137e91a54e1Sdan # 138e91a54e1Sdan do_test pager1-$tn.15 { 139e91a54e1Sdan sql2 { BEGIN; SELECT * FROM t1; } 140e91a54e1Sdan } {1 one 2 two 3 three} 141e91a54e1Sdan do_test pager1-$tn.16 { 142e91a54e1Sdan csql1 { UPDATE t1 SET a = a + 10 } 143e91a54e1Sdan } {1 {database is locked}} 144e91a54e1Sdan do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 145e91a54e1Sdan 146e91a54e1Sdan # This time, have [db] open a transaction before writing the database. 147e91a54e1Sdan # This works - [db] gets a RESERVED lock which does not conflict with 148e91a54e1Sdan # the SHARED lock [db2] is holding. 149e91a54e1Sdan # 150e91a54e1Sdan do_test pager1-$tn.18 { 151e91a54e1Sdan sql1 { 152e91a54e1Sdan BEGIN; 153e91a54e1Sdan UPDATE t1 SET a = a + 10; 154e91a54e1Sdan } 155e91a54e1Sdan } {} 156e91a54e1Sdan do_test pager1-$tn-19 { 157e91a54e1Sdan sql1 { PRAGMA lock_status } 158e91a54e1Sdan } {main reserved temp closed} 159e91a54e1Sdan do_test pager1-$tn-20 { 160e91a54e1Sdan sql2 { PRAGMA lock_status } 161e91a54e1Sdan } {main shared temp closed} 162e91a54e1Sdan 163e91a54e1Sdan # Check that all connections can still read the database. Only [db] sees 164e91a54e1Sdan # the updated content (as the transaction has not been committed yet). 165e91a54e1Sdan # 166e91a54e1Sdan do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} 167e91a54e1Sdan do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 168e91a54e1Sdan do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 169e91a54e1Sdan 170e91a54e1Sdan # Because [db2] still has the SHARED lock, [db] is unable to commit the 171e91a54e1Sdan # transaction. If it tries, an error is returned and the connection 172e91a54e1Sdan # upgrades to a PENDING lock. 173e91a54e1Sdan # 174e91a54e1Sdan # Once this happens, [db] can read the database and see the new content, 175e91a54e1Sdan # [db2] (still holding SHARED) can still read the old content, but [db3] 176e91a54e1Sdan # (not holding any lock) is prevented by [db]'s PENDING from reading 177e91a54e1Sdan # the database. 178e91a54e1Sdan # 179e91a54e1Sdan do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}} 180e91a54e1Sdan do_test pager1-$tn-25 { 181e91a54e1Sdan sql1 { PRAGMA lock_status } 182e91a54e1Sdan } {main pending temp closed} 183e91a54e1Sdan do_test pager1-$tn.26 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} 184e91a54e1Sdan do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 185e91a54e1Sdan do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} 186e91a54e1Sdan 187e91a54e1Sdan # Have [db2] commit its read transaction, releasing the SHARED lock it 188e91a54e1Sdan # is holding. Now, neither [db2] nor [db3] may read the database (as [db] 189e91a54e1Sdan # is still holding a PENDING). 190e91a54e1Sdan # 191e91a54e1Sdan do_test pager1-$tn.29 { sql2 { COMMIT } } {} 192e91a54e1Sdan do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}} 193e91a54e1Sdan do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} 194e91a54e1Sdan 195e91a54e1Sdan # [db] is now able to commit the transaction. Once the transaction is 196e91a54e1Sdan # committed, all three connections can read the new content. 197e91a54e1Sdan # 198e91a54e1Sdan do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {} 199e91a54e1Sdan do_test pager1-$tn.26 { sql1 { COMMIT } } {} 200e91a54e1Sdan do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three} 201e91a54e1Sdan do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three} 202e91a54e1Sdan do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three} 203d353331aSdan 204d353331aSdan # Install a busy-handler for connection [db]. 205d353331aSdan # 206d353331aSdan set ::nbusy [list] 207d353331aSdan proc busy {n} { 208d353331aSdan lappend ::nbusy $n 209d353331aSdan if {$n>5} { sql2 COMMIT } 210d353331aSdan return 0 211d353331aSdan } 212d353331aSdan db busy busy 213d353331aSdan 214d353331aSdan do_test pager1-$tn.29 { 215d353331aSdan sql1 { BEGIN ; INSERT INTO t1 VALUES('x', 'y') } 216d353331aSdan } {} 217d353331aSdan do_test pager1-$tn.30 { 218d353331aSdan sql2 { BEGIN ; SELECT * FROM t1 } 219d353331aSdan } {21 one 22 two 23 three} 220d353331aSdan do_test pager1-$tn.31 { sql1 COMMIT } {} 221d353331aSdan do_test pager1-$tn.32 { set ::nbusy } {0 1 2 3 4 5 6} 222e91a54e1Sdan} 223e91a54e1Sdan 22453f04f3bSdan#------------------------------------------------------------------------- 22553f04f3bSdan# Savepoint related test cases. 22653f04f3bSdan# 227dca321aeSdan# pager1-3.1.2.*: Force a savepoint rollback to cause the database file 228dca321aeSdan# to grow. 229dca321aeSdan# 230273f3f0dSdan# pager1-3.1.3.*: Use a journal created in synchronous=off mode as part 231273f3f0dSdan# of a savepoint rollback. 232273f3f0dSdan# 2330e986f51Sdando_test pager1-3.1.1 { 234b0ac3e3aSdan faultsim_delete_and_reopen 235b0ac3e3aSdan execsql { 236b0ac3e3aSdan CREATE TABLE t1(a PRIMARY KEY, b); 237b0ac3e3aSdan CREATE TABLE counter( 238b0ac3e3aSdan i CHECK (i<5), 239b0ac3e3aSdan u CHECK (u<10) 240b0ac3e3aSdan ); 241b0ac3e3aSdan INSERT INTO counter VALUES(0, 0); 242b0ac3e3aSdan CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN 243b0ac3e3aSdan UPDATE counter SET i = i+1; 244b0ac3e3aSdan END; 245b0ac3e3aSdan CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN 246b0ac3e3aSdan UPDATE counter SET u = u+1; 247b0ac3e3aSdan END; 248b0ac3e3aSdan } 249b0ac3e3aSdan execsql { SELECT * FROM counter } 250b0ac3e3aSdan} {0 0} 251b0ac3e3aSdan 2520e986f51Sdando_execsql_test pager1-3.1.2 { 253d353331aSdan PRAGMA cache_size = 10; 254b0ac3e3aSdan BEGIN; 255b0ac3e3aSdan INSERT INTO t1 VALUES(1, randomblob(1500)); 256b0ac3e3aSdan INSERT INTO t1 VALUES(2, randomblob(1500)); 257b0ac3e3aSdan INSERT INTO t1 VALUES(3, randomblob(1500)); 258b0ac3e3aSdan SELECT * FROM counter; 259b0ac3e3aSdan} {3 0} 2600e986f51Sdando_catchsql_test pager1-3.1.3 { 261b0ac3e3aSdan INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1 262b0ac3e3aSdan} {1 {constraint failed}} 263b0ac3e3aSdando_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0} 264b0ac3e3aSdando_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3} 265b0ac3e3aSdando_execsql_test pager1-3.6 { COMMIT } {} 266b0ac3e3aSdan 267273f3f0dSdanforeach {tn sql tcl} { 268d353331aSdan 7 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 0 } { 269273f3f0dSdan testvfs tv -default 1 270273f3f0dSdan tv devchar safe_append 271273f3f0dSdan } 272d353331aSdan 8 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 2 } { 273d353331aSdan testvfs tv -default 1 274d353331aSdan tv devchar sequential 275d353331aSdan } 276d353331aSdan 9 { PRAGMA synchronous = FULL } { } 277d353331aSdan 10 { PRAGMA synchronous = NORMAL } { } 278d353331aSdan 11 { PRAGMA synchronous = OFF } { } 279d353331aSdan 12 { PRAGMA synchronous = FULL ; PRAGMA fullfsync = 1 } { } 280d353331aSdan 13 { PRAGMA synchronous = FULL } { 281d353331aSdan testvfs tv -default 1 282d353331aSdan tv devchar sequential 283d353331aSdan } 284273f3f0dSdan} { 285273f3f0dSdan do_test pager1-3.$tn.1 { 286273f3f0dSdan eval $tcl 287dca321aeSdan faultsim_delete_and_reopen 288dca321aeSdan db func a_string a_string 289273f3f0dSdan execsql $sql 290dca321aeSdan execsql { 291dca321aeSdan PRAGMA auto_vacuum = 2; 292dca321aeSdan PRAGMA cache_size = 10; 293dca321aeSdan CREATE TABLE z(x INTEGER PRIMARY KEY, y); 294dca321aeSdan BEGIN; 295dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 296dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 2 297dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 4 298dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 8 299dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 16 300dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 32 301dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 64 302dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 128 303dca321aeSdan INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 256 304dca321aeSdan COMMIT; 305dca321aeSdan } 306dca321aeSdan execsql { PRAGMA auto_vacuum } 307dca321aeSdan } {2} 308273f3f0dSdan do_execsql_test pager1-3.$tn.2 { 309dca321aeSdan BEGIN; 310dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 311dca321aeSdan INSERT INTO z VALUES(NULL, a_string(800)); 312dca321aeSdan SAVEPOINT one; 313273f3f0dSdan UPDATE z SET y = NULL WHERE x>256; 314dca321aeSdan PRAGMA incremental_vacuum; 315dca321aeSdan SELECT count(*) FROM z WHERE x < 100; 316dca321aeSdan ROLLBACK TO one; 317dca321aeSdan COMMIT; 318dca321aeSdan } {99} 319dca321aeSdan 320273f3f0dSdan do_execsql_test pager1-3.$tn.3 { 321273f3f0dSdan BEGIN; 322273f3f0dSdan SAVEPOINT one; 323273f3f0dSdan UPDATE z SET y = y||x; 324273f3f0dSdan ROLLBACK TO one; 325273f3f0dSdan COMMIT; 326273f3f0dSdan SELECT count(*) FROM z; 327273f3f0dSdan } {258} 328273f3f0dSdan 329273f3f0dSdan do_execsql_test pager1-3.$tn.4 { 330273f3f0dSdan SAVEPOINT one; 331273f3f0dSdan UPDATE z SET y = y||x; 332273f3f0dSdan ROLLBACK TO one; 333273f3f0dSdan } {} 334273f3f0dSdan do_execsql_test pager1-3.$tn.5 { 335273f3f0dSdan SELECT count(*) FROM z; 336273f3f0dSdan RELEASE one; 337273f3f0dSdan PRAGMA integrity_check; 338273f3f0dSdan } {258 ok} 339273f3f0dSdan 340273f3f0dSdan db close 341273f3f0dSdan catch { tv delete } 342273f3f0dSdan} 343273f3f0dSdan 34453f04f3bSdan#------------------------------------------------------------------------- 34553f04f3bSdan# Hot journal rollback related test cases. 34653f04f3bSdan# 34753f04f3bSdan# pager1.4.1.*: Test that the pager module deletes very small invalid 34853f04f3bSdan# journal files. 34953f04f3bSdan# 35053f04f3bSdan# pager1.4.2.*: Test that if the master journal pointer at the end of a 35153f04f3bSdan# hot-journal file appears to be corrupt (checksum does not 35253f04f3bSdan# compute) the associated journal is rolled back (and no 35353f04f3bSdan# xAccess() call to check for the presence of any master 35453f04f3bSdan# journal file is made). 35553f04f3bSdan# 356de4996e2Sdan# pager1.4.3.*: Test that the contents of a hot-journal are ignored if the 357de4996e2Sdan# page-size or sector-size in the journal header appear to 358de4996e2Sdan# be invalid (too large, too small or not a power of 2). 359de4996e2Sdan# 360e08341c6Sdan# pager1.4.4.*: Test hot-journal rollback of journal file with a master 361e08341c6Sdan# journal pointer generated in various "PRAGMA synchronous" 362e08341c6Sdan# modes. 363e08341c6Sdan# 364e08341c6Sdan# pager1.4.5.*: Test that hot-journal rollback stops if it encounters a 365e08341c6Sdan# journal-record for which the checksum fails. 366e08341c6Sdan# 367ec6ffc1aSdan# pager1.4.6.*: Test that when rolling back a hot-journal that contains a 368ec6ffc1aSdan# master journal pointer, the master journal file is deleted 369ec6ffc1aSdan# after all the hot-journals that refer to it are deleted. 370ec6ffc1aSdan# 371c8ce3972Sdan# pager1.4.7.*: Test that if a hot-journal file exists but a client can 372c8ce3972Sdan# open it for reading only, the database cannot be accessed and 373c8ce3972Sdan# SQLITE_CANTOPEN is returned. 374c8ce3972Sdan# 37553f04f3bSdando_test pager1.4.1.1 { 37653f04f3bSdan faultsim_delete_and_reopen 37753f04f3bSdan execsql { 37853f04f3bSdan CREATE TABLE x(y, z); 37953f04f3bSdan INSERT INTO x VALUES(1, 2); 38053f04f3bSdan } 38153f04f3bSdan set fd [open test.db-journal w] 38253f04f3bSdan puts -nonewline $fd "helloworld" 38353f04f3bSdan close $fd 38453f04f3bSdan file exists test.db-journal 38553f04f3bSdan} {1} 38653f04f3bSdando_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2} 38753f04f3bSdando_test pager1.4.1.3 { file exists test.db-journal } {0} 38853f04f3bSdan 38953f04f3bSdan# Set up a [testvfs] to snapshot the file-system just before SQLite 39053f04f3bSdan# deletes the master-journal to commit a multi-file transaction. 39153f04f3bSdan# 39253f04f3bSdan# In subsequent test cases, invoking [faultsim_restore_and_reopen] sets 39353f04f3bSdan# up the file system to contain two databases, two hot-journal files and 39453f04f3bSdan# a master-journal. 39553f04f3bSdan# 39653f04f3bSdando_test pager1.4.2.1 { 39753f04f3bSdan testvfs tstvfs -default 1 39853f04f3bSdan tstvfs filter xDelete 39953f04f3bSdan tstvfs script xDeleteCallback 40053f04f3bSdan proc xDeleteCallback {method file args} { 40153f04f3bSdan set file [file tail $file] 40253f04f3bSdan if { [string match *mj* $file] } { faultsim_save } 40353f04f3bSdan } 40453f04f3bSdan faultsim_delete_and_reopen 40553f04f3bSdan db func a_string a_string 40653f04f3bSdan execsql { 40753f04f3bSdan ATTACH 'test.db2' AS aux; 40853f04f3bSdan PRAGMA journal_mode = DELETE; 40953f04f3bSdan PRAGMA main.cache_size = 10; 41053f04f3bSdan PRAGMA aux.cache_size = 10; 41153f04f3bSdan CREATE TABLE t1(a UNIQUE, b UNIQUE); 41253f04f3bSdan CREATE TABLE aux.t2(a UNIQUE, b UNIQUE); 41353f04f3bSdan INSERT INTO t1 VALUES(a_string(200), a_string(300)); 41453f04f3bSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 41553f04f3bSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 41653f04f3bSdan INSERT INTO t2 SELECT * FROM t1; 41753f04f3bSdan BEGIN; 41853f04f3bSdan INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1; 41953f04f3bSdan INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1; 42053f04f3bSdan INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1; 42153f04f3bSdan INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1; 42253f04f3bSdan REPLACE INTO t2 SELECT * FROM t1; 42353f04f3bSdan COMMIT; 42453f04f3bSdan } 42553f04f3bSdan db close 42653f04f3bSdan tstvfs delete 42753f04f3bSdan} {} 42853f04f3bSdando_test pager1.4.2.2 { 42953f04f3bSdan faultsim_restore_and_reopen 43053f04f3bSdan execsql { 43153f04f3bSdan SELECT count(*) FROM t1; 43253f04f3bSdan PRAGMA integrity_check; 43353f04f3bSdan } 43453f04f3bSdan} {4 ok} 43553f04f3bSdando_test pager1.4.2.3 { 43653f04f3bSdan faultsim_restore_and_reopen 43753f04f3bSdan foreach f [glob test.db-mj*] { file delete -force $f } 43853f04f3bSdan execsql { 43953f04f3bSdan SELECT count(*) FROM t1; 44053f04f3bSdan PRAGMA integrity_check; 44153f04f3bSdan } 44253f04f3bSdan} {64 ok} 44353f04f3bSdando_test pager1.4.2.4 { 44453f04f3bSdan faultsim_restore_and_reopen 44553f04f3bSdan hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456 44653f04f3bSdan execsql { 44753f04f3bSdan SELECT count(*) FROM t1; 44853f04f3bSdan PRAGMA integrity_check; 44953f04f3bSdan } 45053f04f3bSdan} {4 ok} 45153f04f3bSdando_test pager1.4.2.5 { 45253f04f3bSdan faultsim_restore_and_reopen 45353f04f3bSdan hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456 45453f04f3bSdan foreach f [glob test.db-mj*] { file delete -force $f } 45553f04f3bSdan execsql { 45653f04f3bSdan SELECT count(*) FROM t1; 45753f04f3bSdan PRAGMA integrity_check; 45853f04f3bSdan } 45953f04f3bSdan} {4 ok} 46053f04f3bSdan 461de4996e2Sdando_test pager1.4.3.1 { 462de4996e2Sdan testvfs tstvfs -default 1 463de4996e2Sdan tstvfs filter xSync 464de4996e2Sdan tstvfs script xSyncCallback 465de4996e2Sdan proc xSyncCallback {method file args} { 466de4996e2Sdan set file [file tail $file] 467de4996e2Sdan if { 0==[string match *journal $file] } { faultsim_save } 468de4996e2Sdan } 469de4996e2Sdan faultsim_delete_and_reopen 470de4996e2Sdan execsql { 471de4996e2Sdan PRAGMA journal_mode = DELETE; 472de4996e2Sdan CREATE TABLE t1(a, b); 473de4996e2Sdan INSERT INTO t1 VALUES(1, 2); 474de4996e2Sdan INSERT INTO t1 VALUES(3, 4); 475de4996e2Sdan } 476de4996e2Sdan db close 477de4996e2Sdan tstvfs delete 478de4996e2Sdan} {} 479de4996e2Sdan 480de4996e2Sdanforeach {tn ofst value result} { 481de4996e2Sdan 2 20 31 {1 2 3 4} 482de4996e2Sdan 3 20 32 {1 2 3 4} 483de4996e2Sdan 4 20 33 {1 2 3 4} 484de4996e2Sdan 5 20 65536 {1 2 3 4} 485de4996e2Sdan 6 20 131072 {1 2 3 4} 486de4996e2Sdan 487de4996e2Sdan 7 24 511 {1 2 3 4} 488de4996e2Sdan 8 24 513 {1 2 3 4} 489de4996e2Sdan 9 24 65536 {1 2 3 4} 490de4996e2Sdan 491de4996e2Sdan 10 32 65536 {1 2} 492de4996e2Sdan} { 493de4996e2Sdan do_test pager1.4.3.$tn { 494de4996e2Sdan faultsim_restore_and_reopen 495de4996e2Sdan hexio_write test.db-journal $ofst [format %.8x $value] 496de4996e2Sdan execsql { SELECT * FROM t1 } 497de4996e2Sdan } $result 498de4996e2Sdan} 499de4996e2Sdandb close 500de4996e2Sdan 501e08341c6Sdan# Set up a VFS that snapshots the file-system just before a master journal 502e08341c6Sdan# file is deleted to commit a multi-file transaction. Specifically, the 503e08341c6Sdan# file-system is saved just before the xDelete() call to remove the 504e08341c6Sdan# master journal file from the file-system. 505e08341c6Sdan# 506e08341c6Sdantestvfs tv -default 1 507e08341c6Sdantv script copy_on_mj_delete 508e08341c6Sdanset ::mj_filename_length 0 509e08341c6Sdanproc copy_on_mj_delete {method filename args} { 510e08341c6Sdan if {[string match *mj* [file tail $filename]]} { 511e08341c6Sdan set ::mj_filename_length [string length $filename] 512e08341c6Sdan faultsim_save 513e08341c6Sdan } 514e08341c6Sdan return SQLITE_OK 515e08341c6Sdan} 516e08341c6Sdan 517e08341c6Sdanset pwd [pwd] 518e08341c6Sdanforeach {tn1 tcl} { 519e08341c6Sdan 1 { set prefix "test.db" } 520e08341c6Sdan 2 { 521e08341c6Sdan # This test depends on the underlying VFS being able to open paths 522e08341c6Sdan # 512 bytes in length. The idea is to create a hot-journal file that 523e08341c6Sdan # contains a master-journal pointer so large that it could contain 524e08341c6Sdan # a valid page record (if the file page-size is 512 bytes). So as to 525e08341c6Sdan # make sure SQLite doesn't get confused by this. 526e08341c6Sdan # 527e08341c6Sdan set nPadding [expr 511 - $::mj_filename_length] 528e08341c6Sdan 529e08341c6Sdan # We cannot just create a really long database file name to open, as 530e08341c6Sdan # Linux limits a single component of a path to 255 bytes by default 531e08341c6Sdan # (and presumably other systems have limits too). So create a directory 532e08341c6Sdan # hierarchy to work in. 533e08341c6Sdan # 534e08341c6Sdan set dirname "d123456789012345678901234567890/" 535e08341c6Sdan set nDir [expr $nPadding / 32] 536e08341c6Sdan if { $nDir } { 537e08341c6Sdan set p [string repeat $dirname $nDir] 538e08341c6Sdan file mkdir $p 539e08341c6Sdan cd $p 540e08341c6Sdan } 541e08341c6Sdan 542e08341c6Sdan set padding [string repeat x [expr $nPadding %32]] 543e08341c6Sdan set prefix "test.db${padding}" 544e08341c6Sdan } 545e08341c6Sdan} { 546e08341c6Sdan eval $tcl 547e08341c6Sdan foreach {tn2 sql} { 548e08341c6Sdan o { 549e08341c6Sdan PRAGMA main.synchronous=OFF; 550e08341c6Sdan PRAGMA aux.synchronous=OFF; 551e08341c6Sdan } 552e08341c6Sdan o512 { 553e08341c6Sdan PRAGMA main.synchronous=OFF; 554e08341c6Sdan PRAGMA aux.synchronous=OFF; 555e08341c6Sdan PRAGMA main.page_size = 512; 556e08341c6Sdan PRAGMA aux.page_size = 512; 557e08341c6Sdan } 558e08341c6Sdan n { 559e08341c6Sdan PRAGMA main.synchronous=NORMAL; 560e08341c6Sdan PRAGMA aux.synchronous=NORMAL; 561e08341c6Sdan } 562e08341c6Sdan f { 563e08341c6Sdan PRAGMA main.synchronous=FULL; 564e08341c6Sdan PRAGMA aux.synchronous=FULL; 565e08341c6Sdan } 566e08341c6Sdan } { 567e08341c6Sdan 568e08341c6Sdan set tn "${tn1}.${tn2}" 569e08341c6Sdan 570e08341c6Sdan # Set up a connection to have two databases, test.db (main) and 571e08341c6Sdan # test.db2 (aux). Then run a multi-file transaction on them. The 572e08341c6Sdan # VFS will snapshot the file-system just before the master-journal 573e08341c6Sdan # file is deleted to commit the transaction. 574e08341c6Sdan # 575e08341c6Sdan tv filter xDelete 576e08341c6Sdan do_test pager1-4.4.$tn.1 { 577e08341c6Sdan faultsim_delete_and_reopen $prefix 578e08341c6Sdan execsql " 579e08341c6Sdan ATTACH '${prefix}2' AS aux; 580e08341c6Sdan $sql 581e08341c6Sdan CREATE TABLE a(x); 582e08341c6Sdan CREATE TABLE aux.b(x); 583e08341c6Sdan INSERT INTO a VALUES('double-you'); 584e08341c6Sdan INSERT INTO a VALUES('why'); 585e08341c6Sdan INSERT INTO a VALUES('zed'); 586e08341c6Sdan INSERT INTO b VALUES('won'); 587e08341c6Sdan INSERT INTO b VALUES('too'); 588e08341c6Sdan INSERT INTO b VALUES('free'); 589e08341c6Sdan " 590e08341c6Sdan execsql { 591e08341c6Sdan BEGIN; 592e08341c6Sdan INSERT INTO a SELECT * FROM b WHERE rowid<=3; 593e08341c6Sdan INSERT INTO b SELECT * FROM a WHERE rowid<=3; 594e08341c6Sdan COMMIT; 595e08341c6Sdan } 596e08341c6Sdan } {} 597e08341c6Sdan tv filter {} 598e08341c6Sdan 599e08341c6Sdan # Check that the transaction was committed successfully. 600e08341c6Sdan # 601e08341c6Sdan do_execsql_test pager1-4.4.$tn.2 { 602e08341c6Sdan SELECT * FROM a 603e08341c6Sdan } {double-you why zed won too free} 604e08341c6Sdan do_execsql_test pager1-4.4.$tn.3 { 605e08341c6Sdan SELECT * FROM b 606e08341c6Sdan } {won too free double-you why zed} 607e08341c6Sdan 608e08341c6Sdan # Restore the file-system and reopen the databases. Check that it now 609e08341c6Sdan # appears that the transaction was not committed (because the file-system 610e08341c6Sdan # was restored to the state where it had not been). 611e08341c6Sdan # 612e08341c6Sdan do_test pager1-4.4.$tn.4 { 613e08341c6Sdan faultsim_restore_and_reopen $prefix 614e08341c6Sdan execsql "ATTACH '${prefix}2' AS aux" 615e08341c6Sdan } {} 616e08341c6Sdan do_execsql_test pager1-4.4.$tn.5 {SELECT * FROM a} {double-you why zed} 617e08341c6Sdan do_execsql_test pager1-4.4.$tn.6 {SELECT * FROM b} {won too free} 618e08341c6Sdan 619e08341c6Sdan # Restore the file-system again. This time, before reopening the databases, 620e08341c6Sdan # delete the master-journal file from the file-system. It now appears that 621e08341c6Sdan # the transaction was committed (no master-journal file == no rollback). 622e08341c6Sdan # 623e08341c6Sdan do_test pager1-4.4.$tn.7 { 624e08341c6Sdan faultsim_restore_and_reopen $prefix 625e08341c6Sdan foreach f [glob ${prefix}-mj*] { file delete -force $f } 626e08341c6Sdan execsql "ATTACH '${prefix}2' AS aux" 627e08341c6Sdan } {} 628e08341c6Sdan do_execsql_test pager1-4.4.$tn.8 { 629e08341c6Sdan SELECT * FROM a 630e08341c6Sdan } {double-you why zed won too free} 631e08341c6Sdan do_execsql_test pager1-4.4.$tn.9 { 632e08341c6Sdan SELECT * FROM b 633e08341c6Sdan } {won too free double-you why zed} 634e08341c6Sdan } 635e08341c6Sdan 636e08341c6Sdan cd $pwd 637e08341c6Sdan} 638e08341c6Sdandb close 639e08341c6Sdantv delete 6400e986f51Sdanfile delete -force $dirname 6410e986f51Sdan 6420e986f51Sdan 6430e986f51Sdan# Set up a VFS to make a copy of the file-system just before deleting a 6440e986f51Sdan# journal file to commit a transaction. The transaction modifies exactly 6450e986f51Sdan# two database pages (and page 1 - the change counter). 6460e986f51Sdan# 6470e986f51Sdantestvfs tv -default 1 6480e986f51Sdantv sectorsize 512 6490e986f51Sdantv script copy_on_journal_delete 6500e986f51Sdantv filter xDelete 6510e986f51Sdanproc copy_on_journal_delete {method filename args} { 6520e986f51Sdan if {[string match *journal $filename]} faultsim_save 6530e986f51Sdan return SQLITE_OK 6540e986f51Sdan} 6550e986f51Sdanfaultsim_delete_and_reopen 6560e986f51Sdando_execsql_test pager1.4.5.1 { 6570e986f51Sdan PRAGMA page_size = 1024; 6580e986f51Sdan CREATE TABLE t1(a, b); 6590e986f51Sdan CREATE TABLE t2(a, b); 6600e986f51Sdan INSERT INTO t1 VALUES('I', 'II'); 6610e986f51Sdan INSERT INTO t2 VALUES('III', 'IV'); 6620e986f51Sdan BEGIN; 6630e986f51Sdan INSERT INTO t1 VALUES(1, 2); 6640e986f51Sdan INSERT INTO t2 VALUES(3, 4); 6650e986f51Sdan COMMIT; 6660e986f51Sdan} {} 6670e986f51Sdantv filter {} 6680e986f51Sdan 6690e986f51Sdan# Check the transaction was committed: 6700e986f51Sdan# 6710e986f51Sdando_execsql_test pager1.4.5.2 { 6720e986f51Sdan SELECT * FROM t1; 6730e986f51Sdan SELECT * FROM t2; 6740e986f51Sdan} {I II 1 2 III IV 3 4} 6750e986f51Sdan 676ec6ffc1aSdan# Now try four tests: 6770e986f51Sdan# 6780e986f51Sdan# pager1-4.5.3: Restore the file-system. Check that the whole transaction 6790e986f51Sdan# is rolled back. 6800e986f51Sdan# 6810e986f51Sdan# pager1-4.5.4: Restore the file-system. Corrupt the first record in the 6820e986f51Sdan# journal. Check the transaction is not rolled back. 6830e986f51Sdan# 6840e986f51Sdan# pager1-4.5.5: Restore the file-system. Corrupt the second record in the 6850e986f51Sdan# journal. Check that the first record in the transaction is 6860e986f51Sdan# played back, but not the second. 6870e986f51Sdan# 68810f5a50eSdan# pager1-4.5.6: Restore the file-system. Try to open the database with a 68910f5a50eSdan# readonly connection. This should fail, as a read-only 69010f5a50eSdan# connection cannot roll back the database file. 69110f5a50eSdan# 6920e986f51Sdanfaultsim_restore_and_reopen 6930e986f51Sdando_execsql_test pager1.4.5.3 { 6940e986f51Sdan SELECT * FROM t1; 6950e986f51Sdan SELECT * FROM t2; 6960e986f51Sdan} {I II III IV} 6970e986f51Sdanfaultsim_restore_and_reopen 6980e986f51Sdanhexio_write test.db-journal [expr 512+4+1024 - 202] 0123456789ABCDEF 6990e986f51Sdando_execsql_test pager1.4.5.4 { 7000e986f51Sdan SELECT * FROM t1; 7010e986f51Sdan SELECT * FROM t2; 7020e986f51Sdan} {I II 1 2 III IV 3 4} 7030e986f51Sdanfaultsim_restore_and_reopen 7040e986f51Sdanhexio_write test.db-journal [expr 512+4+1024+4+4+1024 - 202] 0123456789ABCDEF 7050e986f51Sdando_execsql_test pager1.4.5.5 { 7060e986f51Sdan SELECT * FROM t1; 7070e986f51Sdan SELECT * FROM t2; 7080e986f51Sdan} {I II III IV 3 4} 7090e986f51Sdan 71010f5a50eSdanfaultsim_restore_and_reopen 71110f5a50eSdandb close 71210f5a50eSdansqlite3 db test.db -readonly 1 71310f5a50eSdando_catchsql_test pager1.4.5.6 { 71410f5a50eSdan SELECT * FROM t1; 71510f5a50eSdan SELECT * FROM t2; 71610f5a50eSdan} {1 {disk I/O error}} 717ec6ffc1aSdandb close 718ec6ffc1aSdan 719ec6ffc1aSdan# Snapshot the file-system just before multi-file commit. Save the name 720ec6ffc1aSdan# of the master journal file in $::mj_filename. 721ec6ffc1aSdan# 722ec6ffc1aSdantv script copy_on_mj_delete 723ec6ffc1aSdantv filter xDelete 724ec6ffc1aSdanproc copy_on_mj_delete {method filename args} { 725ec6ffc1aSdan if {[string match *mj* [file tail $filename]]} { 726ec6ffc1aSdan set ::mj_filename $filename 727ec6ffc1aSdan faultsim_save 728ec6ffc1aSdan } 729ec6ffc1aSdan return SQLITE_OK 730ec6ffc1aSdan} 731ec6ffc1aSdando_test pager1.4.6.1 { 732ec6ffc1aSdan faultsim_delete_and_reopen 733ec6ffc1aSdan execsql { 734ec6ffc1aSdan ATTACH 'test.db2' AS two; 735ec6ffc1aSdan CREATE TABLE t1(a, b); 736ec6ffc1aSdan CREATE TABLE two.t2(a, b); 737ec6ffc1aSdan INSERT INTO t1 VALUES(1, 't1.1'); 738ec6ffc1aSdan INSERT INTO t2 VALUES(1, 't2.1'); 739ec6ffc1aSdan BEGIN; 740ec6ffc1aSdan UPDATE t1 SET b = 't1.2'; 741ec6ffc1aSdan UPDATE t2 SET b = 't2.2'; 742ec6ffc1aSdan COMMIT; 743ec6ffc1aSdan } 744ec6ffc1aSdan tv filter {} 745ec6ffc1aSdan db close 746ec6ffc1aSdan} {} 747ec6ffc1aSdan 748ec6ffc1aSdanfaultsim_restore_and_reopen 749ec6ffc1aSdando_execsql_test pager1.4.6.2 { SELECT * FROM t1 } {1 t1.1} 750ec6ffc1aSdando_test pager1.4.6.3 { file exists $::mj_filename } {1} 751ec6ffc1aSdando_execsql_test pager1.4.6.4 { 752ec6ffc1aSdan ATTACH 'test.db2' AS two; 753ec6ffc1aSdan SELECT * FROM t2; 754ec6ffc1aSdan} {1 t2.1} 755ec6ffc1aSdando_test pager1.4.6.5 { file exists $::mj_filename } {0} 756ec6ffc1aSdan 757ec6ffc1aSdanfaultsim_restore_and_reopen 758ec6ffc1aSdandb close 759ec6ffc1aSdando_test pager1.4.6.8 { 760ec6ffc1aSdan set ::mj_filename1 $::mj_filename 761ec6ffc1aSdan tv filter xDelete 762ec6ffc1aSdan sqlite3 db test.db2 763ec6ffc1aSdan execsql { 764ec6ffc1aSdan ATTACH 'test.db3' AS three; 765ec6ffc1aSdan CREATE TABLE three.t3(a, b); 766ec6ffc1aSdan INSERT INTO t3 VALUES(1, 't3.1'); 767ec6ffc1aSdan BEGIN; 768ec6ffc1aSdan UPDATE t2 SET b = 't2.3'; 769ec6ffc1aSdan UPDATE t3 SET b = 't3.3'; 770ec6ffc1aSdan COMMIT; 771ec6ffc1aSdan } 772ec6ffc1aSdan expr {$::mj_filename1 != $::mj_filename} 773ec6ffc1aSdan} {1} 774ec6ffc1aSdanfaultsim_restore_and_reopen 775ec6ffc1aSdantv filter {} 776ec6ffc1aSdan 777ec6ffc1aSdan# The file-system now contains: 778ec6ffc1aSdan# 779ec6ffc1aSdan# * three databases 780ec6ffc1aSdan# * three hot-journal files 781ec6ffc1aSdan# * two master-journal files. 782ec6ffc1aSdan# 783ec6ffc1aSdan# The hot-journals associated with test.db2 and test.db3 point to 784ec6ffc1aSdan# master journal $::mj_filename. The hot-journal file associated with 785ec6ffc1aSdan# test.db points to master journal $::mj_filename1. So reading from 786ec6ffc1aSdan# test.db should delete $::mj_filename1. 787ec6ffc1aSdan# 788ec6ffc1aSdando_test pager1.4.6.9 { 789ec6ffc1aSdan lsort [glob test.db*] 790ec6ffc1aSdan} [lsort [list \ 791ec6ffc1aSdan test.db test.db2 test.db3 \ 792ec6ffc1aSdan test.db-journal test.db2-journal test.db3-journal \ 793ec6ffc1aSdan [file tail $::mj_filename] [file tail $::mj_filename1] 794ec6ffc1aSdan]] 795ec6ffc1aSdan 796ec6ffc1aSdan# The master-journal $::mj_filename1 contains pointers to test.db and 797ec6ffc1aSdan# test.db2. However the hot-journal associated with test.db2 points to 798ec6ffc1aSdan# a different master-journal. Therefore, reading from test.db only should 799ec6ffc1aSdan# be enough to cause SQLite to delete $::mj_filename1. 800ec6ffc1aSdan# 801ec6ffc1aSdando_test pager1.4.6.10 { file exists $::mj_filename } {1} 802ec6ffc1aSdando_test pager1.4.6.11 { file exists $::mj_filename1 } {1} 803ec6ffc1aSdando_execsql_test pager1.4.6.12 { SELECT * FROM t1 } {1 t1.1} 804ec6ffc1aSdando_test pager1.4.6.13 { file exists $::mj_filename } {1} 805ec6ffc1aSdando_test pager1.4.6.14 { file exists $::mj_filename1 } {0} 806ec6ffc1aSdan 807ec6ffc1aSdando_execsql_test pager1.4.6.12 { 808ec6ffc1aSdan ATTACH 'test.db2' AS two; 809ec6ffc1aSdan SELECT * FROM t2; 810ec6ffc1aSdan} {1 t2.1} 811ec6ffc1aSdando_test pager1.4.6.13 { file exists $::mj_filename } {1} 812ec6ffc1aSdando_execsql_test pager1.4.6.14 { 813ec6ffc1aSdan ATTACH 'test.db3' AS three; 814ec6ffc1aSdan SELECT * FROM t3; 815ec6ffc1aSdan} {1 t3.1} 816ec6ffc1aSdando_test pager1.4.6.15 { file exists $::mj_filename } {0} 81710f5a50eSdan 8180e986f51Sdandb close 8190e986f51Sdantv delete 820e08341c6Sdan 821c8ce3972Sdantestvfs tv -default 1 822c8ce3972Sdantv sectorsize 512 823c8ce3972Sdantv script copy_on_journal_delete 824c8ce3972Sdantv filter xDelete 825c8ce3972Sdanproc copy_on_journal_delete {method filename args} { 826c8ce3972Sdan if {[string match *journal $filename]} faultsim_save 827c8ce3972Sdan return SQLITE_OK 828c8ce3972Sdan} 829c8ce3972Sdanfaultsim_delete_and_reopen 830c8ce3972Sdando_execsql_test pager1.4.7.1 { 831c8ce3972Sdan CREATE TABLE t1(x PRIMARY KEY, y); 832c8ce3972Sdan CREATE INDEX i1 ON t1(y); 833c8ce3972Sdan INSERT INTO t1 VALUES('I', 'one'); 834c8ce3972Sdan INSERT INTO t1 VALUES('II', 'four'); 835c8ce3972Sdan INSERT INTO t1 VALUES('III', 'nine'); 836c8ce3972Sdan BEGIN; 837c8ce3972Sdan INSERT INTO t1 VALUES('IV', 'sixteen'); 838c8ce3972Sdan INSERT INTO t1 VALUES('V' , 'twentyfive'); 839c8ce3972Sdan COMMIT; 840c8ce3972Sdan} {} 841c8ce3972Sdantv filter {} 842c8ce3972Sdandb close 843c8ce3972Sdantv delete 844c8ce3972Sdando_test pager1.4.7.2 { 845c8ce3972Sdan faultsim_restore_and_reopen 846c8ce3972Sdan catch {file attributes test.db-journal -permissions r--------} 847c8ce3972Sdan catch {file attributes test.db-journal -readonly 1} 848c8ce3972Sdan catchsql { SELECT * FROM t1 } 849c8ce3972Sdan} {1 {unable to open database file}} 850c8ce3972Sdando_test pager1.4.7.3 { 851c8ce3972Sdan db close 852c8ce3972Sdan catch {file attributes test.db-journal -permissions rw-rw-rw-} 853c8ce3972Sdan catch {file attributes test.db-journal -readonly 0} 854c8ce3972Sdan file delete test.db-journal 855c8ce3972Sdan file exists test.db-journal 856c8ce3972Sdan} {0} 857c8ce3972Sdan 858de4996e2Sdan#------------------------------------------------------------------------- 859146ed78bSdan# The following tests deal with multi-file commits. 860de4996e2Sdan# 861146ed78bSdan# pager1-5.1.*: The case where a multi-file cannot be committed because 862146ed78bSdan# another connection is holding a SHARED lock on one of the 863146ed78bSdan# files. After the SHARED lock is removed, the COMMIT succeeds. 864146ed78bSdan# 865146ed78bSdan# pager1-5.2.*: Multi-file commits with journal_mode=memory. 866146ed78bSdan# 867146ed78bSdan# pager1-5.3.*: Multi-file commits with journal_mode=memory. 868146ed78bSdan# 869146ed78bSdan# pager1-5.4.*: Check that with synchronous=normal, the master-journal file 870146ed78bSdan# name is added to a journal file immediately after the last 871146ed78bSdan# journal record. But with synchronous=full, extra unused space 872146ed78bSdan# is allocated between the last journal record and the 873146ed78bSdan# master-journal file name so that the master-journal file 874146ed78bSdan# name does not lie on the same sector as the last journal file 875146ed78bSdan# record. 876146ed78bSdan# 877e08341c6Sdan# pager1-5.5.*: Check that in journal_mode=PERSIST mode, a journal file is 878e08341c6Sdan# truncated to zero bytes when a multi-file transaction is 879e08341c6Sdan# committed (instead of the first couple of bytes being zeroed). 880e08341c6Sdan# 881146ed78bSdan# 882146ed78bSdando_test pager1-5.1.1 { 883146ed78bSdan faultsim_delete_and_reopen 884146ed78bSdan execsql { 885146ed78bSdan ATTACH 'test.db2' AS aux; 886146ed78bSdan CREATE TABLE t1(a, b); 887146ed78bSdan CREATE TABLE aux.t2(a, b); 888146ed78bSdan INSERT INTO t1 VALUES(17, 'Lenin'); 889146ed78bSdan INSERT INTO t1 VALUES(22, 'Stalin'); 890146ed78bSdan INSERT INTO t1 VALUES(53, 'Khrushchev'); 891146ed78bSdan } 892146ed78bSdan} {} 893146ed78bSdando_test pager1-5.1.2 { 894146ed78bSdan execsql { 895146ed78bSdan BEGIN; 896146ed78bSdan INSERT INTO t1 VALUES(64, 'Brezhnev'); 897146ed78bSdan INSERT INTO t2 SELECT * FROM t1; 898146ed78bSdan } 899146ed78bSdan sqlite3 db2 test.db2 900146ed78bSdan execsql { 901146ed78bSdan BEGIN; 902146ed78bSdan SELECT * FROM t2; 903146ed78bSdan } db2 904146ed78bSdan} {} 905146ed78bSdando_test pager1-5.1.3 { 906146ed78bSdan catchsql COMMIT 907146ed78bSdan} {1 {database is locked}} 908146ed78bSdando_test pager1-5.1.4 { 909146ed78bSdan execsql COMMIT db2 910146ed78bSdan execsql COMMIT 911146ed78bSdan execsql { SELECT * FROM t2 } db2 912146ed78bSdan} {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev} 913146ed78bSdando_test pager1-5.1.5 { 914146ed78bSdan db2 close 915146ed78bSdan} {} 916146ed78bSdan 917146ed78bSdando_test pager1-5.2.1 { 918146ed78bSdan execsql { 919146ed78bSdan PRAGMA journal_mode = memory; 920146ed78bSdan BEGIN; 921146ed78bSdan INSERT INTO t1 VALUES(84, 'Andropov'); 922146ed78bSdan INSERT INTO t2 VALUES(84, 'Andropov'); 923146ed78bSdan COMMIT; 924146ed78bSdan } 925146ed78bSdan} {memory} 926146ed78bSdando_test pager1-5.3.1 { 927146ed78bSdan execsql { 928146ed78bSdan PRAGMA journal_mode = off; 929146ed78bSdan BEGIN; 930146ed78bSdan INSERT INTO t1 VALUES(85, 'Gorbachev'); 931146ed78bSdan INSERT INTO t2 VALUES(85, 'Gorbachev'); 932146ed78bSdan COMMIT; 933146ed78bSdan } 934146ed78bSdan} {off} 935146ed78bSdan 936146ed78bSdando_test pager1-5.4.1 { 937146ed78bSdan db close 938146ed78bSdan testvfs tv 939146ed78bSdan sqlite3 db test.db -vfs tv 940146ed78bSdan execsql { ATTACH 'test.db2' AS aux } 941146ed78bSdan 942146ed78bSdan tv filter xDelete 943146ed78bSdan tv script max_journal_size 944146ed78bSdan tv sectorsize 512 945146ed78bSdan set ::max_journal 0 946146ed78bSdan proc max_journal_size {method args} { 947146ed78bSdan set sz 0 948146ed78bSdan catch { set sz [file size test.db-journal] } 949146ed78bSdan if {$sz > $::max_journal} { 950146ed78bSdan set ::max_journal $sz 951146ed78bSdan } 952146ed78bSdan return SQLITE_OK 953146ed78bSdan } 954146ed78bSdan execsql { 955146ed78bSdan PRAGMA journal_mode = DELETE; 956146ed78bSdan PRAGMA synchronous = NORMAL; 957146ed78bSdan BEGIN; 958146ed78bSdan INSERT INTO t1 VALUES(85, 'Gorbachev'); 959146ed78bSdan INSERT INTO t2 VALUES(85, 'Gorbachev'); 960146ed78bSdan COMMIT; 961146ed78bSdan } 962146ed78bSdan set ::max_journal 963146ed78bSdan} [expr 2615+[string length [pwd]]] 964146ed78bSdando_test pager1-5.4.2 { 965146ed78bSdan set ::max_journal 0 966146ed78bSdan execsql { 967146ed78bSdan PRAGMA synchronous = full; 968146ed78bSdan BEGIN; 969146ed78bSdan DELETE FROM t1 WHERE b = 'Lenin'; 970146ed78bSdan DELETE FROM t2 WHERE b = 'Lenin'; 971146ed78bSdan COMMIT; 972146ed78bSdan } 973146ed78bSdan set ::max_journal 974146ed78bSdan} [expr 3111+[string length [pwd]]] 975146ed78bSdandb close 976146ed78bSdantv delete 977146ed78bSdan 978146ed78bSdando_test pager1-5.5.1 { 979146ed78bSdan sqlite3 db test.db 980146ed78bSdan execsql { 981146ed78bSdan ATTACH 'test.db2' AS aux; 982146ed78bSdan PRAGMA journal_mode = PERSIST; 983146ed78bSdan CREATE TABLE t3(a, b); 984146ed78bSdan INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1; 985146ed78bSdan UPDATE t3 SET b = randomblob(1500); 986146ed78bSdan } 987146ed78bSdan expr [file size test.db-journal] > 15000 988146ed78bSdan} {1} 989146ed78bSdando_test pager1-5.5.2 { 990146ed78bSdan execsql { 991146ed78bSdan PRAGMA synchronous = full; 992146ed78bSdan BEGIN; 993146ed78bSdan DELETE FROM t1 WHERE b = 'Stalin'; 994146ed78bSdan DELETE FROM t2 WHERE b = 'Stalin'; 995146ed78bSdan COMMIT; 996146ed78bSdan } 997146ed78bSdan file size test.db-journal 998146ed78bSdan} {0} 999146ed78bSdan 1000146ed78bSdan 1001146ed78bSdan#------------------------------------------------------------------------- 1002146ed78bSdan# The following tests work with "PRAGMA max_page_count" 1003146ed78bSdan# 1004146ed78bSdando_test pager1-6.1 { 1005146ed78bSdan faultsim_delete_and_reopen 1006146ed78bSdan execsql { 1007146ed78bSdan PRAGMA max_page_count = 10; 1008146ed78bSdan CREATE TABLE t2(a, b); 1009146ed78bSdan CREATE TABLE t3(a, b); 1010146ed78bSdan CREATE TABLE t4(a, b); 1011146ed78bSdan CREATE TABLE t5(a, b); 1012146ed78bSdan CREATE TABLE t6(a, b); 1013146ed78bSdan CREATE TABLE t7(a, b); 1014146ed78bSdan CREATE TABLE t8(a, b); 1015146ed78bSdan CREATE TABLE t9(a, b); 1016146ed78bSdan CREATE TABLE t10(a, b); 1017146ed78bSdan } 1018146ed78bSdan} {10} 1019d353331aSdando_catchsql_test pager1-6.2 { 1020d353331aSdan CREATE TABLE t11(a, b) 1021146ed78bSdan} {1 {database or disk is full}} 1022d353331aSdando_execsql_test pager1-6.4 { PRAGMA max_page_count } {10} 1023d353331aSdando_execsql_test pager1-6.5 { PRAGMA max_page_count = 15 } {15} 1024d353331aSdando_execsql_test pager1-6.6 { CREATE TABLE t11(a, b) } {} 1025d353331aSdando_execsql_test pager1-6.7 { 1026d353331aSdan BEGIN; 1027d353331aSdan INSERT INTO t11 VALUES(1, 2); 1028d353331aSdan PRAGMA max_page_count = 13; 1029d353331aSdan} {13} 1030d353331aSdando_execsql_test pager1-6.8 { 1031d353331aSdan INSERT INTO t11 VALUES(3, 4); 1032d353331aSdan PRAGMA max_page_count = 10; 1033d353331aSdan} {11} 1034d353331aSdando_execsql_test pager1-6.9 { COMMIT } {} 1035de4996e2Sdan 1036153eda0aSdan 1037153eda0aSdan#------------------------------------------------------------------------- 1038153eda0aSdan# The following tests work with "PRAGMA journal_mode=TRUNCATE" and 1039153eda0aSdan# "PRAGMA locking_mode=EXCLUSIVE". 1040153eda0aSdan# 1041153eda0aSdan# Each test is specified with 5 variables. As follows: 1042153eda0aSdan# 1043153eda0aSdan# $tn: Test Number. Used as part of the [do_test] test names. 1044153eda0aSdan# $sql: SQL to execute. 1045153eda0aSdan# $res: Expected result of executing $sql. 1046153eda0aSdan# $js: The expected size of the journal file, in bytes, after executing 1047153eda0aSdan# the SQL script. Or -1 if the journal is not expected to exist. 1048153eda0aSdan# $ws: The expected size of the WAL file, in bytes, after executing 1049153eda0aSdan# the SQL script. Or -1 if the WAL is not expected to exist. 1050153eda0aSdan# 105138e1a279Sdanifcapable wal { 1052153eda0aSdan faultsim_delete_and_reopen 1053153eda0aSdan foreach {tn sql res js ws} [subst { 1054153eda0aSdan 1055153eda0aSdan 1 { 1056153eda0aSdan CREATE TABLE t1(a, b); 1057153eda0aSdan PRAGMA auto_vacuum=OFF; 1058153eda0aSdan PRAGMA synchronous=NORMAL; 1059153eda0aSdan PRAGMA page_size=1024; 1060153eda0aSdan PRAGMA locking_mode=EXCLUSIVE; 1061153eda0aSdan PRAGMA journal_mode=TRUNCATE; 1062153eda0aSdan INSERT INTO t1 VALUES(1, 2); 1063153eda0aSdan } {exclusive truncate} 0 -1 1064153eda0aSdan 1065153eda0aSdan 2 { 1066153eda0aSdan BEGIN IMMEDIATE; 1067153eda0aSdan SELECT * FROM t1; 1068153eda0aSdan COMMIT; 1069153eda0aSdan } {1 2} 0 -1 1070153eda0aSdan 1071153eda0aSdan 3 { 1072153eda0aSdan BEGIN; 1073153eda0aSdan SELECT * FROM t1; 1074153eda0aSdan COMMIT; 1075153eda0aSdan } {1 2} 0 -1 1076153eda0aSdan 1077153eda0aSdan 4 { PRAGMA journal_mode = WAL } wal -1 -1 1078153eda0aSdan 5 { INSERT INTO t1 VALUES(3, 4) } {} -1 [wal_file_size 1 1024] 1079153eda0aSdan 6 { PRAGMA locking_mode = NORMAL } normal -1 [wal_file_size 1 1024] 1080153eda0aSdan 7 { INSERT INTO t1 VALUES(5, 6); } {} -1 [wal_file_size 2 1024] 1081153eda0aSdan 1082153eda0aSdan 8 { PRAGMA journal_mode = TRUNCATE } truncate 0 -1 1083153eda0aSdan 9 { INSERT INTO t1 VALUES(7, 8) } {} 0 -1 1084153eda0aSdan 10 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8} 0 -1 1085153eda0aSdan 1086153eda0aSdan }] { 1087153eda0aSdan do_execsql_test pager1-7.1.$tn.1 $sql $res 1088153eda0aSdan catch { set J -1 ; set J [file size test.db-journal] } 1089153eda0aSdan catch { set W -1 ; set W [file size test.db-wal] } 1090153eda0aSdan do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws] 1091153eda0aSdan } 109238e1a279Sdan} 1093153eda0aSdan 1094d353331aSdan#------------------------------------------------------------------------- 1095d353331aSdan# The following tests, pager1-8.*, test that the special filenames 1096d353331aSdan# ":memory:" and "" open temporary databases. 1097d353331aSdan# 10980e986f51Sdanforeach {tn filename} { 10990e986f51Sdan 1 :memory: 11000e986f51Sdan 2 "" 11010e986f51Sdan} { 11020e986f51Sdan do_test pager1-8.$tn.1 { 1103153eda0aSdan faultsim_delete_and_reopen 1104153eda0aSdan db close 11050e986f51Sdan sqlite3 db $filename 1106153eda0aSdan execsql { 1107c8ce3972Sdan PRAGMA auto_vacuum = 1; 1108153eda0aSdan CREATE TABLE x1(x); 1109153eda0aSdan INSERT INTO x1 VALUES('Charles'); 1110153eda0aSdan INSERT INTO x1 VALUES('James'); 1111153eda0aSdan INSERT INTO x1 VALUES('Mary'); 1112153eda0aSdan SELECT * FROM x1; 1113153eda0aSdan } 1114153eda0aSdan } {Charles James Mary} 11150e986f51Sdan 11160e986f51Sdan do_test pager1-8.$tn.2 { 11170e986f51Sdan sqlite3 db2 $filename 11180e986f51Sdan catchsql { SELECT * FROM x1 } db2 1119153eda0aSdan } {1 {no such table: x1}} 1120153eda0aSdan 11210e986f51Sdan do_execsql_test pager1-8.$tn.3 { 11220e986f51Sdan BEGIN; 11230e986f51Sdan INSERT INTO x1 VALUES('William'); 11240e986f51Sdan INSERT INTO x1 VALUES('Anne'); 11250e986f51Sdan ROLLBACK; 11260e986f51Sdan } {} 11270e986f51Sdan} 11280e986f51Sdan 1129dca321aeSdan#------------------------------------------------------------------------- 1130dca321aeSdan# The next block of tests - pager1-9.* - deal with interactions between 1131dca321aeSdan# the pager and the backup API. Test cases: 1132dca321aeSdan# 1133dca321aeSdan# pager1-9.1.*: Test that a backup completes successfully even if the 1134dca321aeSdan# source db is written to during the backup op. 1135dca321aeSdan# 1136dca321aeSdan# pager1-9.2.*: Test that a backup completes successfully even if the 1137dca321aeSdan# source db is written to and then rolled back during a 1138dca321aeSdan# backup operation. 1139dca321aeSdan# 1140dca321aeSdando_test pager1-9.0.1 { 1141dca321aeSdan faultsim_delete_and_reopen 1142dca321aeSdan db func a_string a_string 1143dca321aeSdan execsql { 1144dca321aeSdan PRAGMA cache_size = 10; 1145dca321aeSdan BEGIN; 1146dca321aeSdan CREATE TABLE ab(a, b, UNIQUE(a, b)); 1147dca321aeSdan INSERT INTO ab VALUES( a_string(200), a_string(300) ); 1148dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1149dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1150dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1151dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1152dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1153dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1154dca321aeSdan INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; 1155dca321aeSdan COMMIT; 1156dca321aeSdan } 1157dca321aeSdan} {} 1158dca321aeSdando_test pager1-9.0.2 { 1159dca321aeSdan sqlite3 db2 test.db2 1160dca321aeSdan db2 eval { PRAGMA cache_size = 10 } 1161dca321aeSdan sqlite3_backup B db2 main db main 1162dca321aeSdan list [B step 10000] [B finish] 1163dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1164dca321aeSdando_test pager1-9.0.3 { 1165dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1166dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1167dca321aeSdan 1168dca321aeSdando_test pager1-9.1.1 { 1169dca321aeSdan execsql { UPDATE ab SET a = a_string(201) } 1170dca321aeSdan sqlite3_backup B db2 main db main 1171dca321aeSdan B step 30 1172dca321aeSdan} {SQLITE_OK} 1173dca321aeSdando_test pager1-9.1.2 { 1174dca321aeSdan execsql { UPDATE ab SET b = a_string(301) } 1175dca321aeSdan list [B step 10000] [B finish] 1176dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1177dca321aeSdando_test pager1-9.1.3 { 1178dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1179dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1180dca321aeSdando_test pager1-9.1.4 { execsql { SELECT count(*) FROM ab } } {128} 1181dca321aeSdan 1182dca321aeSdando_test pager1-9.2.1 { 1183dca321aeSdan execsql { UPDATE ab SET a = a_string(202) } 1184dca321aeSdan sqlite3_backup B db2 main db main 1185dca321aeSdan B step 30 1186dca321aeSdan} {SQLITE_OK} 1187dca321aeSdando_test pager1-9.2.2 { 1188dca321aeSdan execsql { 1189dca321aeSdan BEGIN; 1190dca321aeSdan UPDATE ab SET b = a_string(301); 1191dca321aeSdan ROLLBACK; 1192dca321aeSdan } 1193dca321aeSdan list [B step 10000] [B finish] 1194dca321aeSdan} {SQLITE_DONE SQLITE_OK} 1195dca321aeSdando_test pager1-9.2.3 { 1196dca321aeSdan db one {SELECT md5sum(a, b) FROM ab} 1197dca321aeSdan} [db2 one {SELECT md5sum(a, b) FROM ab}] 1198dca321aeSdando_test pager1-9.2.4 { execsql { SELECT count(*) FROM ab } } {128} 1199ec6ffc1aSdandb close 1200ec6ffc1aSdandb2 close 1201ec6ffc1aSdan 1202ec6ffc1aSdan#------------------------------------------------------------------------- 1203ec6ffc1aSdan# Test that regardless of the value returned by xSectorSize(), the 1204ec6ffc1aSdan# minimum effective sector-size is 512 and the maximum 65536 bytes. 1205ec6ffc1aSdan# 1206ec6ffc1aSdantestvfs tv -default 1 1207ec6ffc1aSdanforeach sectorsize { 1208ec6ffc1aSdan 32 64 128 256 512 1024 2048 1209ec6ffc1aSdan 4096 8192 16384 32768 65536 131072 262144 1210ec6ffc1aSdan} { 1211ec6ffc1aSdan tv sectorsize $sectorsize 1212ec6ffc1aSdan set eff $sectorsize 1213ec6ffc1aSdan if {$sectorsize < 512} { set eff 512 } 1214ec6ffc1aSdan if {$sectorsize > 65536} { set eff 65536 } 1215ec6ffc1aSdan 1216ec6ffc1aSdan do_test pager1-10.$sectorsize { 1217ec6ffc1aSdan faultsim_delete_and_reopen 1218ec6ffc1aSdan execsql { 1219ec6ffc1aSdan PRAGMA journal_mode = PERSIST; 1220ec6ffc1aSdan PRAGMA page_size = 1024; 1221ec6ffc1aSdan CREATE TABLE t1(a, b); 1222ec6ffc1aSdan } 1223ec6ffc1aSdan file size test.db-journal 1224ec6ffc1aSdan } [expr $sectorsize > 65536 ? 65536 : $sectorsize] 1225ec6ffc1aSdan} 1226ec6ffc1aSdandb close 1227ec6ffc1aSdantv delete 1228ec6ffc1aSdan 1229ec6ffc1aSdantestvfs tv -default 1 1230ec6ffc1aSdanfaultsim_delete_and_reopen 1231ec6ffc1aSdandb func a_string a_string 1232ec6ffc1aSdando_execsql_test pager1-11.1 { 1233ec6ffc1aSdan PRAGMA cache_size = 10; 1234ec6ffc1aSdan BEGIN; 1235ec6ffc1aSdan CREATE TABLE zz(top PRIMARY KEY); 1236ec6ffc1aSdan INSERT INTO zz VALUES(a_string(222)); 1237ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1238ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1239ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1240ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1241ec6ffc1aSdan INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; 1242ec6ffc1aSdan COMMIT; 1243ec6ffc1aSdan BEGIN; 1244ec6ffc1aSdan UPDATE zz SET top = a_string(345); 1245ec6ffc1aSdan} {} 1246ec6ffc1aSdan 1247ec6ffc1aSdanproc lockout {method args} { return SQLITE_IOERR } 1248ec6ffc1aSdantv script lockout 1249ec6ffc1aSdantv filter {xWrite xTruncate xSync} 1250ec6ffc1aSdando_catchsql_test pager1-11.2 { COMMIT } {1 {disk I/O error}} 1251ec6ffc1aSdan 1252ec6ffc1aSdantv script {} 1253ec6ffc1aSdando_test pager1-11.3 { 1254ec6ffc1aSdan sqlite3 db2 test.db 1255ec6ffc1aSdan execsql { 1256ec6ffc1aSdan PRAGMA journal_mode = TRUNCATE; 1257ec6ffc1aSdan PRAGMA integrity_check; 1258ec6ffc1aSdan } db2 1259ec6ffc1aSdan} {truncate ok} 1260ec6ffc1aSdando_test pager1-11.4 { 1261ec6ffc1aSdan db2 close 1262ec6ffc1aSdan file size test.db-journal 1263ec6ffc1aSdan} {0} 1264ec6ffc1aSdando_execsql_test pager1-11.5 { SELECT count(*) FROM zz } {32} 1265f9b4419dSdandb close 1266f9b4419dSdantv delete 1267ec6ffc1aSdan 1268f9b4419dSdan#------------------------------------------------------------------------- 1269f9b4419dSdan# Test "PRAGMA page_size" 1270f9b4419dSdan# 1271f9b4419dSdanforeach pagesize { 1272f9b4419dSdan 512 1024 2048 4096 8192 16384 32768 1273f9b4419dSdan} { 1274f9b4419dSdan faultsim_delete_and_reopen 1275f9b4419dSdan 1276f9b4419dSdan do_test pager1-12.$pagesize.1 { 1277f9b4419dSdan sqlite3 db2 test.db 1278f9b4419dSdan execsql " 1279f9b4419dSdan PRAGMA page_size = $pagesize; 1280f9b4419dSdan CREATE VIEW v AS SELECT * FROM sqlite_master; 1281f9b4419dSdan " db2 1282f9b4419dSdan file size test.db 1283f9b4419dSdan } $pagesize 1284f9b4419dSdan do_test pager1-12.$pagesize.2 { 1285f9b4419dSdan sqlite3 db2 test.db 1286f9b4419dSdan execsql { 1287f9b4419dSdan SELECT count(*) FROM v; 1288f9b4419dSdan PRAGMA main.page_size; 1289f9b4419dSdan } db2 1290f9b4419dSdan } [list 1 $pagesize] 1291f9b4419dSdan do_test pager1-12.$pagesize.3 { 1292f9b4419dSdan execsql { 1293f9b4419dSdan SELECT count(*) FROM v; 1294f9b4419dSdan PRAGMA main.page_size; 1295f9b4419dSdan } 1296f9b4419dSdan } [list 1 $pagesize] 1297f9b4419dSdan db2 close 1298f9b4419dSdan} 1299dca321aeSdan 1300d353331aSdan#------------------------------------------------------------------------- 1301d353331aSdan# Test specal "PRAGMA journal_mode=PERSIST" test cases. 1302d353331aSdan# 1303d353331aSdan# pager1-13.1.*: This tests a special case encountered in persistent 1304d353331aSdan# journal mode: If the journal associated with a transaction 1305d353331aSdan# is smaller than the journal file (because a previous 1306d353331aSdan# transaction left a very large non-hot journal file in the 1307d353331aSdan# file-system), then SQLite has to be careful that there is 1308d353331aSdan# not a journal-header left over from a previous transaction 1309d353331aSdan# immediately following the journal content just written. 1310d353331aSdan# If there is, and the process crashes so that the journal 1311d353331aSdan# becomes a hot-journal and must be rolled back by another 1312d353331aSdan# process, there is a danger that the other process may roll 1313d353331aSdan# back the aborted transaction, then continue copying data 1314d353331aSdan# from an older transaction from the remainder of the journal. 1315d353331aSdan# See the syncJournal() function for details. 1316d353331aSdan# 1317d353331aSdan# pager1-13.2.*: Same test as the previous. This time, throw an index into 1318d353331aSdan# the mix to make the integrity-check more likely to catch 1319d353331aSdan# errors. 1320d353331aSdan# 1321d353331aSdantestvfs tv -default 1 1322d353331aSdantv script xSyncCb 1323d353331aSdantv filter xSync 1324d353331aSdanproc xSyncCb {method filename args} { 1325d353331aSdan set t [file tail $filename] 1326d353331aSdan if {$t == "test.db"} faultsim_save 1327d353331aSdan return SQLITE_OK 1328d353331aSdan} 1329d353331aSdanfaultsim_delete_and_reopen 1330d353331aSdandb func a_string a_string 1331e91a54e1Sdan 1332d353331aSdan# The UPDATE statement at the end of this test case creates a really big 1333d353331aSdan# journal. Since the cache-size is only 10 pages, the journal contains 1334d353331aSdan# frequent journal headers. 1335d353331aSdan# 1336d353331aSdando_execsql_test pager1-13.1.1 { 1337d353331aSdan PRAGMA page_size = 1024; 1338d353331aSdan PRAGMA journal_mode = PERSIST; 1339d353331aSdan PRAGMA cache_size = 10; 1340d353331aSdan BEGIN; 1341d353331aSdan CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB); 1342d353331aSdan INSERT INTO t1 VALUES(NULL, a_string(400)); 1343d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 2 */ 1344d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 4 */ 1345d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 8 */ 1346d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 16 */ 1347d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 32 */ 1348d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 64 */ 1349d353331aSdan INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 128 */ 1350d353331aSdan COMMIT; 1351d353331aSdan UPDATE t1 SET b = a_string(400); 1352d353331aSdan} {persist} 1353d353331aSdan 1354d353331aSdan# Run transactions of increasing sizes. Eventually, one (or more than one) 1355d353331aSdan# of these will write just enough content that one of the old headers created 1356d353331aSdan# by the transaction in the block above lies immediately after the content 1357d353331aSdan# journalled by the current transaction. 1358d353331aSdan# 1359d353331aSdanfor {set nUp 1} {$nUp<64} {incr nUp} { 1360d353331aSdan do_execsql_test pager1-13.1.2.$nUp.1 { 1361d353331aSdan UPDATE t1 SET b = a_string(399) WHERE a <= $nUp 1362d353331aSdan } {} 1363d353331aSdan do_execsql_test pager1-13.1.2.$nUp.2 { PRAGMA integrity_check } {ok} 1364d353331aSdan 1365d353331aSdan # Try to access the snapshot of the file-system. 1366d353331aSdan # 1367d353331aSdan sqlite3 db2 sv_test.db 1368d353331aSdan do_test pager1-13.1.2.$nUp.3 { 1369d353331aSdan execsql { SELECT sum(length(b)) FROM t1 } db2 1370d353331aSdan } [expr {128*400 - ($nUp-1)}] 1371d353331aSdan do_test pager1-13.1.2.$nUp.4 { 1372d353331aSdan execsql { PRAGMA integrity_check } db2 1373d353331aSdan } {ok} 1374d353331aSdan db2 close 1375d353331aSdan} 1376d353331aSdan 1377d353331aSdan# Same test as above. But this time with an index on the table. 1378d353331aSdan# 1379d353331aSdando_execsql_test pager1-13.2.1 { 1380d353331aSdan CREATE INDEX i1 ON t1(b); 1381d353331aSdan UPDATE t1 SET b = a_string(400); 1382d353331aSdan} {} 1383d353331aSdanfor {set nUp 1} {$nUp<64} {incr nUp} { 1384d353331aSdan do_execsql_test pager1-13.2.2.$nUp.1 { 1385d353331aSdan UPDATE t1 SET b = a_string(399) WHERE a <= $nUp 1386d353331aSdan } {} 1387d353331aSdan do_execsql_test pager1-13.2.2.$nUp.2 { PRAGMA integrity_check } {ok} 1388d353331aSdan sqlite3 db2 sv_test.db 1389d353331aSdan do_test pager1-13.2.2.$nUp.3 { 1390d353331aSdan execsql { SELECT sum(length(b)) FROM t1 } db2 1391d353331aSdan } [expr {128*400 - ($nUp-1)}] 1392d353331aSdan do_test pager1-13.2.2.$nUp.4 { 1393d353331aSdan execsql { PRAGMA integrity_check } db2 1394d353331aSdan } {ok} 1395d353331aSdan db2 close 1396d353331aSdan} 1397d353331aSdan 1398d353331aSdandb close 1399d353331aSdantv delete 1400d353331aSdan 1401d353331aSdan#------------------------------------------------------------------------- 1402d353331aSdan# Test specal "PRAGMA journal_mode=OFF" test cases. 1403d353331aSdan# 1404d353331aSdanfaultsim_delete_and_reopen 1405d353331aSdando_execsql_test pager1-14.1.1 { 1406d353331aSdan PRAGMA journal_mode = OFF; 1407d353331aSdan CREATE TABLE t1(a, b); 1408d353331aSdan BEGIN; 1409d353331aSdan INSERT INTO t1 VALUES(1, 2); 1410d353331aSdan COMMIT; 1411d353331aSdan SELECT * FROM t1; 1412d353331aSdan} {off 1 2} 1413d353331aSdando_catchsql_test pager1-14.1.2 { 1414d353331aSdan BEGIN; 1415d353331aSdan INSERT INTO t1 VALUES(3, 4); 1416d353331aSdan ROLLBACK; 1417d353331aSdan} {0 {}} 1418d353331aSdando_execsql_test pager1-14.1.3 { 1419d353331aSdan SELECT * FROM t1; 1420d353331aSdan} {1 2 3 4} 1421d353331aSdando_catchsql_test pager1-14.1.4 { 1422d353331aSdan BEGIN; 1423d353331aSdan INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; 1424d353331aSdan INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; 1425d353331aSdan} {1 {PRIMARY KEY must be unique}} 1426d353331aSdando_execsql_test pager1-14.1.5 { 1427d353331aSdan COMMIT; 1428d353331aSdan SELECT * FROM t1; 1429d353331aSdan} {1 2 3 4 2 2 4 4} 1430d353331aSdan 1431c8ce3972Sdan#------------------------------------------------------------------------- 1432c8ce3972Sdan# Test opening and closing the pager sub-system with different values 1433c8ce3972Sdan# for the sqlite3_vfs.szOsFile variable. 1434c8ce3972Sdan# 1435c8ce3972Sdanfaultsim_delete_and_reopen 1436c8ce3972Sdando_execsql_test pager1-15.0 { 1437c8ce3972Sdan CREATE TABLE tx(y, z); 1438c8ce3972Sdan INSERT INTO tx VALUES('Ayutthaya', 'Beijing'); 1439c8ce3972Sdan INSERT INTO tx VALUES('London', 'Tokyo'); 1440c8ce3972Sdan} {} 1441c8ce3972Sdandb close 1442c8ce3972Sdanfor {set i 0} {$i<513} {incr i 3} { 1443c8ce3972Sdan testvfs tv -default 1 -szosfile $i 1444c8ce3972Sdan sqlite3 db test.db 1445c8ce3972Sdan do_execsql_test pager1-15.$i.1 { 1446c8ce3972Sdan SELECT * FROM tx; 1447c8ce3972Sdan } {Ayutthaya Beijing London Tokyo} 1448c8ce3972Sdan db close 1449c8ce3972Sdan tv delete 1450c8ce3972Sdan} 1451c8ce3972Sdan 1452c8ce3972Sdan#------------------------------------------------------------------------- 1453c8ce3972Sdan# Check that it is not possible to open a database file if the full path 1454c8ce3972Sdan# to the associated journal file will be longer than sqlite3_vfs.mxPathname. 1455c8ce3972Sdan# 1456c8ce3972Sdantestvfs tv -default 1 1457c8ce3972Sdantv script xOpenCb 1458c8ce3972Sdantv filter xOpen 1459c8ce3972Sdanproc xOpenCb {method filename} { 1460c8ce3972Sdan set ::file_len [string length $filename] 1461c8ce3972Sdan} 1462c8ce3972Sdansqlite3 db test.db 1463c8ce3972Sdandb close 1464c8ce3972Sdantv delete 1465c8ce3972Sdan 1466c8ce3972Sdanfor {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} { 1467c8ce3972Sdan testvfs tv -default 1 -mxpathname $ii 1468c8ce3972Sdan 1469c8ce3972Sdan # The length of the full path to file "test.db-journal" is ($::file_len+8). 1470c8ce3972Sdan # If the configured sqlite3_vfs.mxPathname value greater than or equal to 1471c8ce3972Sdan # this, then the file can be opened. Otherwise, it cannot. 1472c8ce3972Sdan # 1473c8ce3972Sdan if {$ii >= [expr $::file_len+8]} { 1474c8ce3972Sdan set res {0 {}} 1475c8ce3972Sdan } else { 1476c8ce3972Sdan set res {1 {unable to open database file}} 1477c8ce3972Sdan } 1478c8ce3972Sdan 1479c8ce3972Sdan do_test pager1-16.1.$ii { 1480c8ce3972Sdan list [catch { sqlite3 db test.db } msg] $msg 1481c8ce3972Sdan } $res 1482c8ce3972Sdan 1483c8ce3972Sdan catch {db close} 1484c8ce3972Sdan tv delete 1485c8ce3972Sdan} 1486c8ce3972Sdan 1487c8ce3972Sdan#------------------------------------------------------------------------- 1488c8ce3972Sdan# Test "PRAGMA omit_readlock". 1489c8ce3972Sdan# 1490c8ce3972Sdan# pager1-17.$tn.1.*: Test that if a second connection has an open 1491c8ce3972Sdan# read-transaction, it is not usually possible to write 1492c8ce3972Sdan# the database. 1493c8ce3972Sdan# 1494c8ce3972Sdan# pager1-17.$tn.2.*: Test that if the second connection was opened with 1495c8ce3972Sdan# the SQLITE_OPEN_READONLY flag, and 1496c8ce3972Sdan# "PRAGMA omit_readlock = 1" is executed before attaching 1497c8ce3972Sdan# the database and opening a read-transaction on it, it is 1498c8ce3972Sdan# possible to write the db. 1499c8ce3972Sdan# 1500c8ce3972Sdan# pager1-17.$tn.3.*: Test that if the second connection was *not* opened with 1501c8ce3972Sdan# the SQLITE_OPEN_READONLY flag, executing 1502c8ce3972Sdan# "PRAGMA omit_readlock = 1" has no effect. 1503c8ce3972Sdan# 1504c8ce3972Sdando_multiclient_test tn { 1505c8ce3972Sdan do_test pager1-17.$tn.1.1 { 1506c8ce3972Sdan sql1 { 1507c8ce3972Sdan CREATE TABLE t1(a, b); 1508c8ce3972Sdan INSERT INTO t1 VALUES(1, 2); 1509c8ce3972Sdan } 1510c8ce3972Sdan sql2 { 1511c8ce3972Sdan BEGIN; 1512c8ce3972Sdan SELECT * FROM t1; 1513c8ce3972Sdan } 1514c8ce3972Sdan } {1 2} 1515c8ce3972Sdan do_test pager1-17.$tn.1.2 { 1516c8ce3972Sdan csql1 { INSERT INTO t1 VALUES(3, 4) } 1517c8ce3972Sdan } {1 {database is locked}} 1518c8ce3972Sdan do_test pager1-17.$tn.1.3 { 1519c8ce3972Sdan sql2 { COMMIT } 1520c8ce3972Sdan sql1 { INSERT INTO t1 VALUES(3, 4) } 1521c8ce3972Sdan } {} 1522c8ce3972Sdan 1523c8ce3972Sdan do_test pager1-17.$tn.2.1 { 1524c8ce3972Sdan code2 { 1525c8ce3972Sdan db2 close 1526c8ce3972Sdan sqlite3 db2 :memory: -readonly 1 1527c8ce3972Sdan } 1528c8ce3972Sdan sql2 { 1529c8ce3972Sdan PRAGMA omit_readlock = 1; 1530c8ce3972Sdan ATTACH 'test.db' AS two; 1531c8ce3972Sdan BEGIN; 1532c8ce3972Sdan SELECT * FROM t1; 1533c8ce3972Sdan } 1534c8ce3972Sdan } {1 2 3 4} 1535c8ce3972Sdan do_test pager1-17.$tn.2.2 { sql1 "INSERT INTO t1 VALUES(5, 6)" } {} 1536c8ce3972Sdan do_test pager1-17.$tn.2.3 { sql2 "SELECT * FROM t1" } {1 2 3 4} 1537c8ce3972Sdan do_test pager1-17.$tn.2.4 { sql2 "COMMIT ; SELECT * FROM t1" } {1 2 3 4 5 6} 1538c8ce3972Sdan 1539c8ce3972Sdan do_test pager1-17.$tn.3.1 { 1540c8ce3972Sdan code2 { 1541c8ce3972Sdan db2 close 1542c8ce3972Sdan sqlite3 db2 :memory: 1543c8ce3972Sdan } 1544c8ce3972Sdan sql2 { 1545c8ce3972Sdan PRAGMA omit_readlock = 1; 1546c8ce3972Sdan ATTACH 'test.db' AS two; 1547c8ce3972Sdan BEGIN; 1548c8ce3972Sdan SELECT * FROM t1; 1549c8ce3972Sdan } 1550c8ce3972Sdan } {1 2 3 4 5 6} 1551c8ce3972Sdan do_test pager1-17.$tn.3.2 { 1552c8ce3972Sdan csql1 { INSERT INTO t1 VALUES(3, 4) } 1553c8ce3972Sdan } {1 {database is locked}} 1554c8ce3972Sdan do_test pager1-17.$tn.3.3 { sql2 COMMIT } {} 1555c8ce3972Sdan} 1556c8ce3972Sdan 1557c8ce3972Sdan#------------------------------------------------------------------------- 1558c8ce3972Sdan# Test the pagers response to the b-tree layer requesting illegal page 1559c8ce3972Sdan# numbers: 1560c8ce3972Sdan# 1561c8ce3972Sdan# + The locking page, 1562c8ce3972Sdan# + Page 0, 1563c8ce3972Sdan# + A page with a page number greater than (2^31-1). 1564c8ce3972Sdan# 1565c8ce3972Sdando_test pager1-18.1 { 1566c8ce3972Sdan faultsim_delete_and_reopen 1567c8ce3972Sdan db func a_string a_string 1568c8ce3972Sdan execsql { 1569c8ce3972Sdan PRAGMA page_size = 1024; 1570c8ce3972Sdan CREATE TABLE t1(a, b); 1571c8ce3972Sdan INSERT INTO t1 VALUES(a_string(500), a_string(200)); 1572c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1573c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1574c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1575c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1576c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1577c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1578c8ce3972Sdan INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; 1579c8ce3972Sdan } 1580c8ce3972Sdan} {} 1581c8ce3972Sdando_test pager1-18.2 { 1582c8ce3972Sdan set root [db one "SELECT rootpage FROM sqlite_master"] 1583c8ce3972Sdan set lockingpage [expr (0x10000/1024) + 1] 1584c8ce3972Sdan execsql { 1585c8ce3972Sdan PRAGMA writable_schema = 1; 1586c8ce3972Sdan UPDATE sqlite_master SET rootpage = $lockingpage; 1587c8ce3972Sdan } 1588c8ce3972Sdan sqlite3 db2 test.db 1589c8ce3972Sdan catchsql { SELECT count(*) FROM t1 } db2 1590c8ce3972Sdan} {1 {database disk image is malformed}} 1591c8ce3972Sdandb2 close 1592c8ce3972Sdando_test pager1-18.3 { 1593c8ce3972Sdan execsql { 1594c8ce3972Sdan CREATE TABLE t2(x); 1595c8ce3972Sdan INSERT INTO t2 VALUES(a_string(5000)); 1596c8ce3972Sdan } 1597c8ce3972Sdan set pgno [expr ([file size test.db] / 1024)-2] 1598c8ce3972Sdan hexio_write test.db [expr ($pgno-1)*1024] 00000000 1599c8ce3972Sdan sqlite3 db2 test.db 1600c8ce3972Sdan catchsql { SELECT length(x) FROM t2 } db2 1601c8ce3972Sdan} {1 {database disk image is malformed}} 1602c8ce3972Sdandb2 close 1603c8ce3972Sdando_test pager1-18.4 { 1604c8ce3972Sdan hexio_write test.db [expr ($pgno-1)*1024] 90000000 1605c8ce3972Sdan sqlite3 db2 test.db 1606c8ce3972Sdan catchsql { SELECT length(x) FROM t2 } db2 1607c8ce3972Sdan} {1 {database disk image is malformed}} 1608c8ce3972Sdandb2 close 1609c8ce3972Sdando_test pager1-18.5 { 1610c8ce3972Sdan sqlite3 db "" 1611c8ce3972Sdan execsql { 1612c8ce3972Sdan CREATE TABLE t1(a, b); 1613c8ce3972Sdan CREATE TABLE t2(a, b); 1614c8ce3972Sdan PRAGMA writable_schema = 1; 1615c8ce3972Sdan UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1'; 1616c8ce3972Sdan PRAGMA writable_schema = 0; 1617c8ce3972Sdan ALTER TABLE t1 RENAME TO x1; 1618c8ce3972Sdan } 1619c8ce3972Sdan catchsql { SELECT * FROM x1 } 1620*ba3cbf3dSdan} {1 {database disk image is malformed}} 1621c8ce3972Sdandb close 1622c8ce3972Sdan 1623*ba3cbf3dSdando_test pager1-18.6 { 1624*ba3cbf3dSdan faultsim_delete_and_reopen 1625*ba3cbf3dSdan db func a_string a_string 1626*ba3cbf3dSdan execsql { 1627*ba3cbf3dSdan PRAGMA page_size = 1024; 1628*ba3cbf3dSdan CREATE TABLE t1(x); 1629*ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(800)); 1630*ba3cbf3dSdan INSERT INTO t1 VALUES(a_string(800)); 1631*ba3cbf3dSdan } 1632*ba3cbf3dSdan 1633*ba3cbf3dSdan set root [db one "SELECT rootpage FROM sqlite_master"] 1634*ba3cbf3dSdan db close 1635*ba3cbf3dSdan 1636*ba3cbf3dSdan hexio_write test.db [expr ($root-1)*1024 + 8] 00000000 1637*ba3cbf3dSdan sqlite3 db test.db 1638*ba3cbf3dSdan catchsql { SELECT length(x) FROM t1 } 1639*ba3cbf3dSdan} {1 {database disk image is malformed}} 1640*ba3cbf3dSdan 1641*ba3cbf3dSdando_test pager1-19.1 { 1642*ba3cbf3dSdan sqlite3 db "" 1643*ba3cbf3dSdan db func a_string a_string 1644*ba3cbf3dSdan execsql { 1645*ba3cbf3dSdan PRAGMA page_size = 512; 1646*ba3cbf3dSdan PRAGMA auto_vacuum = 1; 1647*ba3cbf3dSdan CREATE TABLE t1(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, 1648*ba3cbf3dSdan ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, 1649*ba3cbf3dSdan ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, 1650*ba3cbf3dSdan da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn, 1651*ba3cbf3dSdan ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, 1652*ba3cbf3dSdan fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, 1653*ba3cbf3dSdan ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn, 1654*ba3cbf3dSdan ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn, 1655*ba3cbf3dSdan ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix, 1656*ba3cbf3dSdan ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn, 1657*ba3cbf3dSdan ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn, 1658*ba3cbf3dSdan la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln, 1659*ba3cbf3dSdan ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn 1660*ba3cbf3dSdan ); 1661*ba3cbf3dSdan CREATE TABLE t2(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, 1662*ba3cbf3dSdan ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, 1663*ba3cbf3dSdan ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, 1664*ba3cbf3dSdan da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn, 1665*ba3cbf3dSdan ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, 1666*ba3cbf3dSdan fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, 1667*ba3cbf3dSdan ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn, 1668*ba3cbf3dSdan ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn, 1669*ba3cbf3dSdan ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix, 1670*ba3cbf3dSdan ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn, 1671*ba3cbf3dSdan ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn, 1672*ba3cbf3dSdan la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln, 1673*ba3cbf3dSdan ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn 1674*ba3cbf3dSdan ); 1675*ba3cbf3dSdan INSERT INTO t1(aa) VALUES( a_string(100000) ); 1676*ba3cbf3dSdan INSERT INTO t2(aa) VALUES( a_string(100000) ); 1677*ba3cbf3dSdan VACUUM; 1678*ba3cbf3dSdan } 1679*ba3cbf3dSdan} {} 1680*ba3cbf3dSdan 1681d353331aSdanfinish_test 1682c8ce3972Sdan 1683