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 17*153eda0aSdansource $testdir/wal_common.tcl 18e91a54e1Sdan 19b0ac3e3aSdan# 20b0ac3e3aSdan# pager1-1.*: Test inter-process locking (clients in multiple processes). 21b0ac3e3aSdan# 22b0ac3e3aSdan# pager1-2.*: Test intra-process locking (multiple clients in this process). 23b0ac3e3aSdan# 24b0ac3e3aSdan# pager1-3.*: Savepoint related tests. 25b0ac3e3aSdan# 261f4cb65aSdan# pager1-4.*: Hot-journal related tests. 271f4cb65aSdan# 28de4996e2Sdan# pager1-5.*: Cases related to multi-file commits. 29de4996e2Sdan# 30146ed78bSdan# pager1-6.*: Cases related to "PRAGMA max_page_count" 31146ed78bSdan# 32*153eda0aSdan# pager1-7.*: Cases specific to "PRAGMA journal_mode=TRUNCATE" 33*153eda0aSdan# 34b0ac3e3aSdan 3553f04f3bSdanset a_string_counter 1 3653f04f3bSdanproc a_string {n} { 3753f04f3bSdan global a_string_counter 3853f04f3bSdan incr a_string_counter 3953f04f3bSdan string range [string repeat "${a_string_counter}." $n] 1 $n 4053f04f3bSdan} 4153f04f3bSdandb func a_string a_string 4253f04f3bSdan 43a4a9095eSdando_multiclient_test tn { 44e91a54e1Sdan 45e91a54e1Sdan # Create and populate a database table using connection [db]. Check 46e91a54e1Sdan # that connections [db2] and [db3] can see the schema and content. 47e91a54e1Sdan # 48e91a54e1Sdan do_test pager1-$tn.1 { 49e91a54e1Sdan sql1 { 50e91a54e1Sdan CREATE TABLE t1(a PRIMARY KEY, b); 51e91a54e1Sdan CREATE INDEX i1 ON t1(b); 52e91a54e1Sdan INSERT INTO t1 VALUES(1, 'one'); 53e91a54e1Sdan INSERT INTO t1 VALUES(2, 'two'); 54e91a54e1Sdan } 55e91a54e1Sdan } {} 56e91a54e1Sdan do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two} 57e91a54e1Sdan do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two} 58e91a54e1Sdan 59e91a54e1Sdan # Open a transaction and add a row using [db]. This puts [db] in 60e91a54e1Sdan # RESERVED state. Check that connections [db2] and [db3] can still 61e91a54e1Sdan # read the database content as it was before the transaction was 62e91a54e1Sdan # opened. [db] should see the inserted row. 63e91a54e1Sdan # 64e91a54e1Sdan do_test pager1-$tn.4 { 65e91a54e1Sdan sql1 { 66e91a54e1Sdan BEGIN; 67e91a54e1Sdan INSERT INTO t1 VALUES(3, 'three'); 68e91a54e1Sdan } 69e91a54e1Sdan } {} 70e91a54e1Sdan do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two} 71e91a54e1Sdan do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} 72e91a54e1Sdan 73e91a54e1Sdan # [db] still has an open write transaction. Check that this prevents 74e91a54e1Sdan # other connections (specifically [db2]) from writing to the database. 75e91a54e1Sdan # 76e91a54e1Sdan # Even if [db2] opens a transaction first, it may not write to the 77e91a54e1Sdan # database. After the attempt to write the db within a transaction, 78e91a54e1Sdan # [db2] is left with an open transaction, but not a read-lock on 79e91a54e1Sdan # the main database. So it does not prevent [db] from committing. 80e91a54e1Sdan # 81e91a54e1Sdan do_test pager1-$tn.8 { 82e91a54e1Sdan csql2 { UPDATE t1 SET a = a + 10 } 83e91a54e1Sdan } {1 {database is locked}} 84e91a54e1Sdan do_test pager1-$tn.9 { 85e91a54e1Sdan csql2 { 86e91a54e1Sdan BEGIN; 87e91a54e1Sdan UPDATE t1 SET a = a + 10; 88e91a54e1Sdan } 89e91a54e1Sdan } {1 {database is locked}} 90e91a54e1Sdan 91e91a54e1Sdan # Have [db] commit its transactions. Check the other connections can 92e91a54e1Sdan # now see the new database content. 93e91a54e1Sdan # 94e91a54e1Sdan do_test pager1-$tn.10 { sql1 { COMMIT } } {} 95e91a54e1Sdan do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} 96e91a54e1Sdan do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 97e91a54e1Sdan do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 98e91a54e1Sdan 99e91a54e1Sdan # Check that, as noted above, [db2] really did keep an open transaction 100e91a54e1Sdan # after the attempt to write the database failed. 101e91a54e1Sdan # 102e91a54e1Sdan do_test pager1-$tn.14 { 103e91a54e1Sdan csql2 { BEGIN } 104e91a54e1Sdan } {1 {cannot start a transaction within a transaction}} 105e91a54e1Sdan do_test pager1-$tn.15 { sql2 { ROLLBACK } } {} 106e91a54e1Sdan 107e91a54e1Sdan # Have [db2] open a transaction and take a read-lock on the database. 108e91a54e1Sdan # Check that this prevents [db] from writing to the database (outside 109e91a54e1Sdan # of any transaction). After this fails, check that [db3] can read 110e91a54e1Sdan # the db (showing that [db] did not take a PENDING lock etc.) 111e91a54e1Sdan # 112e91a54e1Sdan do_test pager1-$tn.15 { 113e91a54e1Sdan sql2 { BEGIN; SELECT * FROM t1; } 114e91a54e1Sdan } {1 one 2 two 3 three} 115e91a54e1Sdan do_test pager1-$tn.16 { 116e91a54e1Sdan csql1 { UPDATE t1 SET a = a + 10 } 117e91a54e1Sdan } {1 {database is locked}} 118e91a54e1Sdan do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 119e91a54e1Sdan 120e91a54e1Sdan # This time, have [db] open a transaction before writing the database. 121e91a54e1Sdan # This works - [db] gets a RESERVED lock which does not conflict with 122e91a54e1Sdan # the SHARED lock [db2] is holding. 123e91a54e1Sdan # 124e91a54e1Sdan do_test pager1-$tn.18 { 125e91a54e1Sdan sql1 { 126e91a54e1Sdan BEGIN; 127e91a54e1Sdan UPDATE t1 SET a = a + 10; 128e91a54e1Sdan } 129e91a54e1Sdan } {} 130e91a54e1Sdan do_test pager1-$tn-19 { 131e91a54e1Sdan sql1 { PRAGMA lock_status } 132e91a54e1Sdan } {main reserved temp closed} 133e91a54e1Sdan do_test pager1-$tn-20 { 134e91a54e1Sdan sql2 { PRAGMA lock_status } 135e91a54e1Sdan } {main shared temp closed} 136e91a54e1Sdan 137e91a54e1Sdan # Check that all connections can still read the database. Only [db] sees 138e91a54e1Sdan # the updated content (as the transaction has not been committed yet). 139e91a54e1Sdan # 140e91a54e1Sdan do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} 141e91a54e1Sdan do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 142e91a54e1Sdan do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} 143e91a54e1Sdan 144e91a54e1Sdan # Because [db2] still has the SHARED lock, [db] is unable to commit the 145e91a54e1Sdan # transaction. If it tries, an error is returned and the connection 146e91a54e1Sdan # upgrades to a PENDING lock. 147e91a54e1Sdan # 148e91a54e1Sdan # Once this happens, [db] can read the database and see the new content, 149e91a54e1Sdan # [db2] (still holding SHARED) can still read the old content, but [db3] 150e91a54e1Sdan # (not holding any lock) is prevented by [db]'s PENDING from reading 151e91a54e1Sdan # the database. 152e91a54e1Sdan # 153e91a54e1Sdan do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}} 154e91a54e1Sdan do_test pager1-$tn-25 { 155e91a54e1Sdan sql1 { PRAGMA lock_status } 156e91a54e1Sdan } {main pending temp closed} 157e91a54e1Sdan do_test pager1-$tn.26 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} 158e91a54e1Sdan do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} 159e91a54e1Sdan do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} 160e91a54e1Sdan 161e91a54e1Sdan # Have [db2] commit its read transaction, releasing the SHARED lock it 162e91a54e1Sdan # is holding. Now, neither [db2] nor [db3] may read the database (as [db] 163e91a54e1Sdan # is still holding a PENDING). 164e91a54e1Sdan # 165e91a54e1Sdan do_test pager1-$tn.29 { sql2 { COMMIT } } {} 166e91a54e1Sdan do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}} 167e91a54e1Sdan do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} 168e91a54e1Sdan 169e91a54e1Sdan # [db] is now able to commit the transaction. Once the transaction is 170e91a54e1Sdan # committed, all three connections can read the new content. 171e91a54e1Sdan # 172e91a54e1Sdan do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {} 173e91a54e1Sdan do_test pager1-$tn.26 { sql1 { COMMIT } } {} 174e91a54e1Sdan do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three} 175e91a54e1Sdan do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three} 176e91a54e1Sdan do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three} 177e91a54e1Sdan} 178e91a54e1Sdan 17953f04f3bSdan#------------------------------------------------------------------------- 18053f04f3bSdan# Savepoint related test cases. 18153f04f3bSdan# 182b0ac3e3aSdando_test pager1-3.1 { 183b0ac3e3aSdan faultsim_delete_and_reopen 184b0ac3e3aSdan execsql { 185b0ac3e3aSdan CREATE TABLE t1(a PRIMARY KEY, b); 186b0ac3e3aSdan CREATE TABLE counter( 187b0ac3e3aSdan i CHECK (i<5), 188b0ac3e3aSdan u CHECK (u<10) 189b0ac3e3aSdan ); 190b0ac3e3aSdan INSERT INTO counter VALUES(0, 0); 191b0ac3e3aSdan CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN 192b0ac3e3aSdan UPDATE counter SET i = i+1; 193b0ac3e3aSdan END; 194b0ac3e3aSdan CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN 195b0ac3e3aSdan UPDATE counter SET u = u+1; 196b0ac3e3aSdan END; 197b0ac3e3aSdan } 198b0ac3e3aSdan execsql { SELECT * FROM counter } 199b0ac3e3aSdan} {0 0} 200b0ac3e3aSdan 201b0ac3e3aSdando_execsql_test pager1-3.2 { 202b0ac3e3aSdan BEGIN; 203b0ac3e3aSdan INSERT INTO t1 VALUES(1, randomblob(1500)); 204b0ac3e3aSdan INSERT INTO t1 VALUES(2, randomblob(1500)); 205b0ac3e3aSdan INSERT INTO t1 VALUES(3, randomblob(1500)); 206b0ac3e3aSdan SELECT * FROM counter; 207b0ac3e3aSdan} {3 0} 208b0ac3e3aSdando_catchsql_test pager1-3.3 { 209b0ac3e3aSdan INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1 210b0ac3e3aSdan} {1 {constraint failed}} 211b0ac3e3aSdando_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0} 212b0ac3e3aSdando_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3} 213b0ac3e3aSdando_execsql_test pager1-3.6 { COMMIT } {} 214b0ac3e3aSdan 21553f04f3bSdan#------------------------------------------------------------------------- 21653f04f3bSdan# Hot journal rollback related test cases. 21753f04f3bSdan# 21853f04f3bSdan# pager1.4.1.*: Test that the pager module deletes very small invalid 21953f04f3bSdan# journal files. 22053f04f3bSdan# 22153f04f3bSdan# pager1.4.2.*: Test that if the master journal pointer at the end of a 22253f04f3bSdan# hot-journal file appears to be corrupt (checksum does not 22353f04f3bSdan# compute) the associated journal is rolled back (and no 22453f04f3bSdan# xAccess() call to check for the presence of any master 22553f04f3bSdan# journal file is made). 22653f04f3bSdan# 227de4996e2Sdan# pager1.4.3.*: Test that the contents of a hot-journal are ignored if the 228de4996e2Sdan# page-size or sector-size in the journal header appear to 229de4996e2Sdan# be invalid (too large, too small or not a power of 2). 230de4996e2Sdan# 23153f04f3bSdando_test pager1.4.1.1 { 23253f04f3bSdan faultsim_delete_and_reopen 23353f04f3bSdan execsql { 23453f04f3bSdan CREATE TABLE x(y, z); 23553f04f3bSdan INSERT INTO x VALUES(1, 2); 23653f04f3bSdan } 23753f04f3bSdan set fd [open test.db-journal w] 23853f04f3bSdan puts -nonewline $fd "helloworld" 23953f04f3bSdan close $fd 24053f04f3bSdan file exists test.db-journal 24153f04f3bSdan} {1} 24253f04f3bSdando_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2} 24353f04f3bSdando_test pager1.4.1.3 { file exists test.db-journal } {0} 24453f04f3bSdan 24553f04f3bSdan# Set up a [testvfs] to snapshot the file-system just before SQLite 24653f04f3bSdan# deletes the master-journal to commit a multi-file transaction. 24753f04f3bSdan# 24853f04f3bSdan# In subsequent test cases, invoking [faultsim_restore_and_reopen] sets 24953f04f3bSdan# up the file system to contain two databases, two hot-journal files and 25053f04f3bSdan# a master-journal. 25153f04f3bSdan# 25253f04f3bSdando_test pager1.4.2.1 { 25353f04f3bSdan testvfs tstvfs -default 1 25453f04f3bSdan tstvfs filter xDelete 25553f04f3bSdan tstvfs script xDeleteCallback 25653f04f3bSdan proc xDeleteCallback {method file args} { 25753f04f3bSdan set file [file tail $file] 25853f04f3bSdan if { [string match *mj* $file] } { faultsim_save } 25953f04f3bSdan } 26053f04f3bSdan faultsim_delete_and_reopen 26153f04f3bSdan db func a_string a_string 26253f04f3bSdan execsql { 26353f04f3bSdan ATTACH 'test.db2' AS aux; 26453f04f3bSdan PRAGMA journal_mode = DELETE; 26553f04f3bSdan PRAGMA main.cache_size = 10; 26653f04f3bSdan PRAGMA aux.cache_size = 10; 26753f04f3bSdan CREATE TABLE t1(a UNIQUE, b UNIQUE); 26853f04f3bSdan CREATE TABLE aux.t2(a UNIQUE, b UNIQUE); 26953f04f3bSdan INSERT INTO t1 VALUES(a_string(200), a_string(300)); 27053f04f3bSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 27153f04f3bSdan INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; 27253f04f3bSdan INSERT INTO t2 SELECT * FROM t1; 27353f04f3bSdan BEGIN; 27453f04f3bSdan INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1; 27553f04f3bSdan INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1; 27653f04f3bSdan INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1; 27753f04f3bSdan INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1; 27853f04f3bSdan REPLACE INTO t2 SELECT * FROM t1; 27953f04f3bSdan COMMIT; 28053f04f3bSdan } 28153f04f3bSdan db close 28253f04f3bSdan tstvfs delete 28353f04f3bSdan} {} 28453f04f3bSdando_test pager1.4.2.2 { 28553f04f3bSdan faultsim_restore_and_reopen 28653f04f3bSdan execsql { 28753f04f3bSdan SELECT count(*) FROM t1; 28853f04f3bSdan PRAGMA integrity_check; 28953f04f3bSdan } 29053f04f3bSdan} {4 ok} 29153f04f3bSdando_test pager1.4.2.3 { 29253f04f3bSdan faultsim_restore_and_reopen 29353f04f3bSdan foreach f [glob test.db-mj*] { file delete -force $f } 29453f04f3bSdan execsql { 29553f04f3bSdan SELECT count(*) FROM t1; 29653f04f3bSdan PRAGMA integrity_check; 29753f04f3bSdan } 29853f04f3bSdan} {64 ok} 29953f04f3bSdando_test pager1.4.2.4 { 30053f04f3bSdan faultsim_restore_and_reopen 30153f04f3bSdan hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456 30253f04f3bSdan execsql { 30353f04f3bSdan SELECT count(*) FROM t1; 30453f04f3bSdan PRAGMA integrity_check; 30553f04f3bSdan } 30653f04f3bSdan} {4 ok} 30753f04f3bSdando_test pager1.4.2.5 { 30853f04f3bSdan faultsim_restore_and_reopen 30953f04f3bSdan hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456 31053f04f3bSdan foreach f [glob test.db-mj*] { file delete -force $f } 31153f04f3bSdan execsql { 31253f04f3bSdan SELECT count(*) FROM t1; 31353f04f3bSdan PRAGMA integrity_check; 31453f04f3bSdan } 31553f04f3bSdan} {4 ok} 31653f04f3bSdan 317de4996e2Sdando_test pager1.4.3.1 { 318de4996e2Sdan testvfs tstvfs -default 1 319de4996e2Sdan tstvfs filter xSync 320de4996e2Sdan tstvfs script xSyncCallback 321de4996e2Sdan proc xSyncCallback {method file args} { 322de4996e2Sdan set file [file tail $file] 323de4996e2Sdan if { 0==[string match *journal $file] } { faultsim_save } 324de4996e2Sdan } 325de4996e2Sdan faultsim_delete_and_reopen 326de4996e2Sdan execsql { 327de4996e2Sdan PRAGMA journal_mode = DELETE; 328de4996e2Sdan CREATE TABLE t1(a, b); 329de4996e2Sdan INSERT INTO t1 VALUES(1, 2); 330de4996e2Sdan INSERT INTO t1 VALUES(3, 4); 331de4996e2Sdan } 332de4996e2Sdan db close 333de4996e2Sdan tstvfs delete 334de4996e2Sdan} {} 335de4996e2Sdan 336de4996e2Sdanforeach {tn ofst value result} { 337de4996e2Sdan 2 20 31 {1 2 3 4} 338de4996e2Sdan 3 20 32 {1 2 3 4} 339de4996e2Sdan 4 20 33 {1 2 3 4} 340de4996e2Sdan 5 20 65536 {1 2 3 4} 341de4996e2Sdan 6 20 131072 {1 2 3 4} 342de4996e2Sdan 343de4996e2Sdan 7 24 511 {1 2 3 4} 344de4996e2Sdan 8 24 513 {1 2 3 4} 345de4996e2Sdan 9 24 65536 {1 2 3 4} 346de4996e2Sdan 347de4996e2Sdan 10 32 65536 {1 2} 348de4996e2Sdan} { 349de4996e2Sdan do_test pager1.4.3.$tn { 350de4996e2Sdan faultsim_restore_and_reopen 351de4996e2Sdan hexio_write test.db-journal $ofst [format %.8x $value] 352de4996e2Sdan execsql { SELECT * FROM t1 } 353de4996e2Sdan } $result 354de4996e2Sdan} 355de4996e2Sdandb close 356de4996e2Sdan 357de4996e2Sdan#------------------------------------------------------------------------- 358146ed78bSdan# The following tests deal with multi-file commits. 359de4996e2Sdan# 360146ed78bSdan# pager1-5.1.*: The case where a multi-file cannot be committed because 361146ed78bSdan# another connection is holding a SHARED lock on one of the 362146ed78bSdan# files. After the SHARED lock is removed, the COMMIT succeeds. 363146ed78bSdan# 364146ed78bSdan# pager1-5.2.*: Multi-file commits with journal_mode=memory. 365146ed78bSdan# 366146ed78bSdan# pager1-5.3.*: Multi-file commits with journal_mode=memory. 367146ed78bSdan# 368146ed78bSdan# pager1-5.4.*: Check that with synchronous=normal, the master-journal file 369146ed78bSdan# name is added to a journal file immediately after the last 370146ed78bSdan# journal record. But with synchronous=full, extra unused space 371146ed78bSdan# is allocated between the last journal record and the 372146ed78bSdan# master-journal file name so that the master-journal file 373146ed78bSdan# name does not lie on the same sector as the last journal file 374146ed78bSdan# record. 375146ed78bSdan# 376146ed78bSdan# pager1-5.5.*: 377146ed78bSdan# 378146ed78bSdando_test pager1-5.1.1 { 379146ed78bSdan faultsim_delete_and_reopen 380146ed78bSdan execsql { 381146ed78bSdan ATTACH 'test.db2' AS aux; 382146ed78bSdan CREATE TABLE t1(a, b); 383146ed78bSdan CREATE TABLE aux.t2(a, b); 384146ed78bSdan INSERT INTO t1 VALUES(17, 'Lenin'); 385146ed78bSdan INSERT INTO t1 VALUES(22, 'Stalin'); 386146ed78bSdan INSERT INTO t1 VALUES(53, 'Khrushchev'); 387146ed78bSdan } 388146ed78bSdan} {} 389146ed78bSdando_test pager1-5.1.2 { 390146ed78bSdan execsql { 391146ed78bSdan BEGIN; 392146ed78bSdan INSERT INTO t1 VALUES(64, 'Brezhnev'); 393146ed78bSdan INSERT INTO t2 SELECT * FROM t1; 394146ed78bSdan } 395146ed78bSdan sqlite3 db2 test.db2 396146ed78bSdan execsql { 397146ed78bSdan BEGIN; 398146ed78bSdan SELECT * FROM t2; 399146ed78bSdan } db2 400146ed78bSdan} {} 401146ed78bSdando_test pager1-5.1.3 { 402146ed78bSdan catchsql COMMIT 403146ed78bSdan} {1 {database is locked}} 404146ed78bSdando_test pager1-5.1.4 { 405146ed78bSdan execsql COMMIT db2 406146ed78bSdan execsql COMMIT 407146ed78bSdan execsql { SELECT * FROM t2 } db2 408146ed78bSdan} {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev} 409146ed78bSdando_test pager1-5.1.5 { 410146ed78bSdan db2 close 411146ed78bSdan} {} 412146ed78bSdan 413146ed78bSdando_test pager1-5.2.1 { 414146ed78bSdan execsql { 415146ed78bSdan PRAGMA journal_mode = memory; 416146ed78bSdan BEGIN; 417146ed78bSdan INSERT INTO t1 VALUES(84, 'Andropov'); 418146ed78bSdan INSERT INTO t2 VALUES(84, 'Andropov'); 419146ed78bSdan COMMIT; 420146ed78bSdan } 421146ed78bSdan} {memory} 422146ed78bSdando_test pager1-5.3.1 { 423146ed78bSdan execsql { 424146ed78bSdan PRAGMA journal_mode = off; 425146ed78bSdan BEGIN; 426146ed78bSdan INSERT INTO t1 VALUES(85, 'Gorbachev'); 427146ed78bSdan INSERT INTO t2 VALUES(85, 'Gorbachev'); 428146ed78bSdan COMMIT; 429146ed78bSdan } 430146ed78bSdan} {off} 431146ed78bSdan 432146ed78bSdando_test pager1-5.4.1 { 433146ed78bSdan db close 434146ed78bSdan testvfs tv 435146ed78bSdan sqlite3 db test.db -vfs tv 436146ed78bSdan execsql { ATTACH 'test.db2' AS aux } 437146ed78bSdan 438146ed78bSdan tv filter xDelete 439146ed78bSdan tv script max_journal_size 440146ed78bSdan tv sectorsize 512 441146ed78bSdan set ::max_journal 0 442146ed78bSdan proc max_journal_size {method args} { 443146ed78bSdan set sz 0 444146ed78bSdan catch { set sz [file size test.db-journal] } 445146ed78bSdan if {$sz > $::max_journal} { 446146ed78bSdan set ::max_journal $sz 447146ed78bSdan } 448146ed78bSdan return SQLITE_OK 449146ed78bSdan } 450146ed78bSdan execsql { 451146ed78bSdan PRAGMA journal_mode = DELETE; 452146ed78bSdan PRAGMA synchronous = NORMAL; 453146ed78bSdan BEGIN; 454146ed78bSdan INSERT INTO t1 VALUES(85, 'Gorbachev'); 455146ed78bSdan INSERT INTO t2 VALUES(85, 'Gorbachev'); 456146ed78bSdan COMMIT; 457146ed78bSdan } 458146ed78bSdan set ::max_journal 459146ed78bSdan} [expr 2615+[string length [pwd]]] 460146ed78bSdando_test pager1-5.4.2 { 461146ed78bSdan set ::max_journal 0 462146ed78bSdan execsql { 463146ed78bSdan PRAGMA synchronous = full; 464146ed78bSdan BEGIN; 465146ed78bSdan DELETE FROM t1 WHERE b = 'Lenin'; 466146ed78bSdan DELETE FROM t2 WHERE b = 'Lenin'; 467146ed78bSdan COMMIT; 468146ed78bSdan } 469146ed78bSdan set ::max_journal 470146ed78bSdan} [expr 3111+[string length [pwd]]] 471146ed78bSdandb close 472146ed78bSdantv delete 473146ed78bSdan 474146ed78bSdando_test pager1-5.5.1 { 475146ed78bSdan sqlite3 db test.db 476146ed78bSdan execsql { 477146ed78bSdan ATTACH 'test.db2' AS aux; 478146ed78bSdan PRAGMA journal_mode = PERSIST; 479146ed78bSdan CREATE TABLE t3(a, b); 480146ed78bSdan INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1; 481146ed78bSdan UPDATE t3 SET b = randomblob(1500); 482146ed78bSdan } 483146ed78bSdan expr [file size test.db-journal] > 15000 484146ed78bSdan} {1} 485146ed78bSdando_test pager1-5.5.2 { 486146ed78bSdan execsql { 487146ed78bSdan PRAGMA synchronous = full; 488146ed78bSdan BEGIN; 489146ed78bSdan DELETE FROM t1 WHERE b = 'Stalin'; 490146ed78bSdan DELETE FROM t2 WHERE b = 'Stalin'; 491146ed78bSdan COMMIT; 492146ed78bSdan } 493146ed78bSdan file size test.db-journal 494146ed78bSdan} {0} 495146ed78bSdan 496146ed78bSdan 497146ed78bSdan#------------------------------------------------------------------------- 498146ed78bSdan# The following tests work with "PRAGMA max_page_count" 499146ed78bSdan# 500146ed78bSdando_test pager1-6.1 { 501146ed78bSdan faultsim_delete_and_reopen 502146ed78bSdan execsql { 503146ed78bSdan PRAGMA max_page_count = 10; 504146ed78bSdan CREATE TABLE t2(a, b); 505146ed78bSdan CREATE TABLE t3(a, b); 506146ed78bSdan CREATE TABLE t4(a, b); 507146ed78bSdan CREATE TABLE t5(a, b); 508146ed78bSdan CREATE TABLE t6(a, b); 509146ed78bSdan CREATE TABLE t7(a, b); 510146ed78bSdan CREATE TABLE t8(a, b); 511146ed78bSdan CREATE TABLE t9(a, b); 512146ed78bSdan CREATE TABLE t10(a, b); 513146ed78bSdan } 514146ed78bSdan} {10} 515146ed78bSdando_test pager1-6.2 { 516146ed78bSdan catchsql { 517146ed78bSdan CREATE TABLE t11(a, b); 518146ed78bSdan } 519146ed78bSdan} {1 {database or disk is full}} 520de4996e2Sdan 521*153eda0aSdan 522*153eda0aSdan#------------------------------------------------------------------------- 523*153eda0aSdan# The following tests work with "PRAGMA journal_mode=TRUNCATE" and 524*153eda0aSdan# "PRAGMA locking_mode=EXCLUSIVE". 525*153eda0aSdan# 526*153eda0aSdan# Each test is specified with 5 variables. As follows: 527*153eda0aSdan# 528*153eda0aSdan# $tn: Test Number. Used as part of the [do_test] test names. 529*153eda0aSdan# $sql: SQL to execute. 530*153eda0aSdan# $res: Expected result of executing $sql. 531*153eda0aSdan# $js: The expected size of the journal file, in bytes, after executing 532*153eda0aSdan# the SQL script. Or -1 if the journal is not expected to exist. 533*153eda0aSdan# $ws: The expected size of the WAL file, in bytes, after executing 534*153eda0aSdan# the SQL script. Or -1 if the WAL is not expected to exist. 535*153eda0aSdan# 536*153eda0aSdanfaultsim_delete_and_reopen 537*153eda0aSdanforeach {tn sql res js ws} [subst { 538*153eda0aSdan 539*153eda0aSdan 1 { 540*153eda0aSdan CREATE TABLE t1(a, b); 541*153eda0aSdan PRAGMA auto_vacuum=OFF; 542*153eda0aSdan PRAGMA synchronous=NORMAL; 543*153eda0aSdan PRAGMA page_size=1024; 544*153eda0aSdan PRAGMA locking_mode=EXCLUSIVE; 545*153eda0aSdan PRAGMA journal_mode=TRUNCATE; 546*153eda0aSdan INSERT INTO t1 VALUES(1, 2); 547*153eda0aSdan } {exclusive truncate} 0 -1 548*153eda0aSdan 549*153eda0aSdan 2 { 550*153eda0aSdan BEGIN IMMEDIATE; 551*153eda0aSdan SELECT * FROM t1; 552*153eda0aSdan COMMIT; 553*153eda0aSdan } {1 2} 0 -1 554*153eda0aSdan 555*153eda0aSdan 3 { 556*153eda0aSdan BEGIN; 557*153eda0aSdan SELECT * FROM t1; 558*153eda0aSdan COMMIT; 559*153eda0aSdan } {1 2} 0 -1 560*153eda0aSdan 561*153eda0aSdan 4 { PRAGMA journal_mode = WAL } wal -1 -1 562*153eda0aSdan 5 { INSERT INTO t1 VALUES(3, 4) } {} -1 [wal_file_size 1 1024] 563*153eda0aSdan 6 { PRAGMA locking_mode = NORMAL } normal -1 [wal_file_size 1 1024] 564*153eda0aSdan 7 { INSERT INTO t1 VALUES(5, 6); } {} -1 [wal_file_size 2 1024] 565*153eda0aSdan 566*153eda0aSdan 8 { PRAGMA journal_mode = TRUNCATE } truncate 0 -1 567*153eda0aSdan 9 { INSERT INTO t1 VALUES(7, 8) } {} 0 -1 568*153eda0aSdan 10 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8} 0 -1 569*153eda0aSdan 570*153eda0aSdan}] { 571*153eda0aSdan do_execsql_test pager1-7.1.$tn.1 $sql $res 572*153eda0aSdan catch { set J -1 ; set J [file size test.db-journal] } 573*153eda0aSdan catch { set W -1 ; set W [file size test.db-wal] } 574*153eda0aSdan do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws] 575*153eda0aSdan} 576*153eda0aSdan 577*153eda0aSdando_test pager1-8.1 { 578*153eda0aSdan faultsim_delete_and_reopen 579*153eda0aSdan db close 580*153eda0aSdan sqlite3 db :memory: 581*153eda0aSdan execsql { 582*153eda0aSdan CREATE TABLE x1(x); 583*153eda0aSdan INSERT INTO x1 VALUES('Charles'); 584*153eda0aSdan INSERT INTO x1 VALUES('James'); 585*153eda0aSdan INSERT INTO x1 VALUES('Mary'); 586*153eda0aSdan SELECT * FROM x1; 587*153eda0aSdan } 588*153eda0aSdan} {Charles James Mary} 589*153eda0aSdando_test pager1-8.2 { 590*153eda0aSdan db close 591*153eda0aSdan sqlite3 db :memory: 592*153eda0aSdan catchsql { SELECT * FROM x1 } 593*153eda0aSdan} {1 {no such table: x1}} 594*153eda0aSdan 595e91a54e1Sdanfinish_test 596e91a54e1Sdan 597