1e04dc88bSdan# 2010 April 19 2e04dc88bSdan# 3e04dc88bSdan# The author disclaims copyright to this source code. In place of 4e04dc88bSdan# a legal notice, here is a blessing: 5e04dc88bSdan# 6e04dc88bSdan# May you do good and not evil. 7e04dc88bSdan# May you find forgiveness for yourself and forgive others. 8e04dc88bSdan# May you share freely, never taking more than you give. 9e04dc88bSdan# 10e04dc88bSdan#*********************************************************************** 11e04dc88bSdan# This file implements regression tests for SQLite library. The 12e04dc88bSdan# focus of this file is testing the operation of the library in 13e04dc88bSdan# "PRAGMA journal_mode=WAL" mode. 14e04dc88bSdan# 15e04dc88bSdan 16e04dc88bSdanset testdir [file dirname $argv0] 17e04dc88bSdansource $testdir/tester.tcl 183f94b609Sdansource $testdir/malloc_common.tcl 19e04dc88bSdan 205cf53537Sdan# If the library was compiled without WAL support, check that the 215cf53537Sdan# "PRAGMA journal_mode=WAL" treats "WAL" as an unrecognized mode. 225cf53537Sdan# 235cf53537Sdanifcapable !wal { 245cf53537Sdan 255cf53537Sdan do_test walmode-0.1 { 265cf53537Sdan execsql { PRAGMA journal_mode = wal } 275cf53537Sdan } {delete} 285cf53537Sdan do_test walmode-0.2 { 295cf53537Sdan execsql { PRAGMA main.journal_mode = wal } 305cf53537Sdan } {delete} 315cf53537Sdan do_test walmode-0.3 { 325cf53537Sdan execsql { PRAGMA main.journal_mode } 335cf53537Sdan } {delete} 345cf53537Sdan 355cf53537Sdan finish_test 365cf53537Sdan return 375cf53537Sdan} 385cf53537Sdan 39e04dc88bSdando_test walmode-1.1 { 40b9780027Sdan set sqlite_sync_count 0 41b9780027Sdan execsql { PRAGMA page_size = 1024 } 42b9780027Sdan execsql { PRAGMA journal_mode = wal } 43e04dc88bSdan} {wal} 44b9780027Sdando_test walmode-1.2 { 45b9780027Sdan file size test.db 46b9780027Sdan} {1024} 47a10069ddSshaneh 48*69aedc8dSdanif {[atomic_batch_write test.db]==0} { 49a10069ddSshaneh set expected_sync_count 3 50a10069ddSshaneh if {$::tcl_platform(platform)!="windows"} { 51a10069ddSshaneh ifcapable dirsync { 52a10069ddSshaneh incr expected_sync_count 53a10069ddSshaneh } 54a10069ddSshaneh } 55b9780027Sdan do_test walmode-1.3 { 56b9780027Sdan set sqlite_sync_count 57a10069ddSshaneh } $expected_sync_count 58*69aedc8dSdan} 59a10069ddSshaneh 60b9780027Sdando_test walmode-1.4 { 61b9780027Sdan file exists test.db-wal 62b9780027Sdan} {0} 63b9780027Sdando_test walmode-1.5 { 64b9780027Sdan execsql { CREATE TABLE t1(a, b) } 65b9780027Sdan file size test.db 66b9780027Sdan} {1024} 67b9780027Sdando_test walmode-1.6 { 68b9780027Sdan file exists test.db-wal 69b9780027Sdan} {1} 70b9780027Sdando_test walmode-1.7 { 71b9780027Sdan db close 72b9780027Sdan file exists test.db-wal 73b9780027Sdan} {0} 74b9780027Sdan 75b9780027Sdan# There is now a database file with the read and write versions set to 2 76b9780027Sdan# in the file system. This file should default to WAL mode. 77b9780027Sdan# 78b9780027Sdando_test walmode-2.1 { 79b9780027Sdan sqlite3 db test.db 80b9780027Sdan file exists test.db-wal 81b9780027Sdan} {0} 82b9780027Sdando_test walmode-2.2 { 83b9780027Sdan execsql { SELECT * FROM sqlite_master } 84b9780027Sdan file exists test.db-wal 85b9780027Sdan} {1} 86b9780027Sdando_test walmode-2.3 { 87b9780027Sdan db close 88b9780027Sdan file exists test.db-wal 89b9780027Sdan} {0} 90b9780027Sdan 91b9780027Sdan# If the first statement executed is "PRAGMA journal_mode = wal", and 92b9780027Sdan# the file is already configured for WAL (read and write versions set 93b9780027Sdan# to 2), then there should be no need to write the database. The 94b9780027Sdan# statement should cause the client to connect to the log file. 95b9780027Sdan# 96b9780027Sdanset sqlite_sync_count 0 97b9780027Sdando_test walmode-3.1 { 98b9780027Sdan sqlite3 db test.db 99b9780027Sdan execsql { PRAGMA journal_mode = wal } 100b9780027Sdan} {wal} 101b9780027Sdando_test walmode-3.2 { 102b9780027Sdan list $sqlite_sync_count [file exists test.db-wal] [file size test.db-wal] 103b9780027Sdan} {0 1 0} 104b9780027Sdan 105ede6eb8dSdan# Test that changing back to journal_mode=persist works. 106ede6eb8dSdan# 107b9780027Sdando_test walmode-4.1 { 108b9780027Sdan execsql { INSERT INTO t1 VALUES(1, 2) } 109b9780027Sdan execsql { PRAGMA journal_mode = persist } 110b9780027Sdan} {persist} 111*69aedc8dSdanif {[atomic_batch_write test.db]==0} { 112b9780027Sdan do_test walmode-4.2 { 113b9780027Sdan list [file exists test.db-journal] [file exists test.db-wal] 114b9780027Sdan } {1 0} 115*69aedc8dSdan} 116b9780027Sdando_test walmode-4.3 { 117b9780027Sdan execsql { SELECT * FROM t1 } 118b9780027Sdan} {1 2} 119b9780027Sdando_test walmode-4.4 { 120b9780027Sdan db close 121b9780027Sdan sqlite3 db test.db 122b9780027Sdan execsql { SELECT * FROM t1 } 123b9780027Sdan} {1 2} 124*69aedc8dSdanif {[atomic_batch_write test.db]==0} { 125b9780027Sdan do_test walmode-4.5 { 126b9780027Sdan list [file exists test.db-journal] [file exists test.db-wal] 127b9780027Sdan } {1 0} 128*69aedc8dSdan} 129e04dc88bSdan 130ede6eb8dSdan# Test that nothing goes wrong if a connection is prevented from changing 131ede6eb8dSdan# from WAL to rollback mode because a second connection has the database 132ede6eb8dSdan# open. Or from rollback to WAL. 133ede6eb8dSdan# 134d956efebSdando_test walmode-4.6 { 135ede6eb8dSdan sqlite3 db2 test.db 136ede6eb8dSdan execsql { PRAGMA main.journal_mode } db2 137ede6eb8dSdan} {delete} 138d956efebSdando_test walmode-4.7 { 139ede6eb8dSdan execsql { PRAGMA main.journal_mode = wal } db 140ede6eb8dSdan} {wal} 141d956efebSdando_test walmode-4.8 { 142ede6eb8dSdan execsql { SELECT * FROM t1 } db2 143ede6eb8dSdan} {1 2} 144d956efebSdando_test walmode-4.9 { 145ede6eb8dSdan catchsql { PRAGMA journal_mode = delete } db 146ede6eb8dSdan} {1 {database is locked}} 147d956efebSdando_test walmode-4.10 { 148ede6eb8dSdan execsql { PRAGMA main.journal_mode } db 149ede6eb8dSdan} {wal} 150d956efebSdan 151d956efebSdando_test walmode-4.11 { 152ede6eb8dSdan db2 close 153ede6eb8dSdan execsql { PRAGMA journal_mode = delete } db 154ede6eb8dSdan} {delete} 155d956efebSdando_test walmode-4.12 { 156ede6eb8dSdan execsql { PRAGMA main.journal_mode } db 157ede6eb8dSdan} {delete} 158d956efebSdando_test walmode-4.13 { 159ede6eb8dSdan list [file exists test.db-journal] [file exists test.db-wal] 160ede6eb8dSdan} {0 0} 161d956efebSdando_test walmode-4.14 { 162ede6eb8dSdan sqlite3 db2 test.db 163ede6eb8dSdan execsql { 164ede6eb8dSdan BEGIN; 165ede6eb8dSdan SELECT * FROM t1; 166ede6eb8dSdan } db2 167ede6eb8dSdan} {1 2} 168d956efebSdan 169d956efebSdando_test walmode-4.16 { execsql { PRAGMA main.journal_mode } db } {delete} 170d956efebSdando_test walmode-4.17 { execsql { PRAGMA main.journal_mode } db2 } {delete} 171d956efebSdan 172d956efebSdando_test walmode-4.17 { 173ede6eb8dSdan catchsql { PRAGMA main.journal_mode = wal } db 174ede6eb8dSdan} {1 {database is locked}} 175d956efebSdando_test walmode-4.18 { 176ede6eb8dSdan execsql { PRAGMA main.journal_mode } db 177ede6eb8dSdan} {delete} 178ede6eb8dSdancatch { db close } 179ede6eb8dSdancatch { db2 close } 180e180c296Sdan 181e180c296Sdan# Test that it is not possible to change a temporary or in-memory database 182e180c296Sdan# to WAL mode. WAL mode is for persistent file-backed databases only. 183e180c296Sdan# 184e180c296Sdan# walmode-5.1.*: Try to set journal_mode=WAL on [sqlite3 db :memory:] database. 185e180c296Sdan# walmode-5.2.*: Try to set journal_mode=WAL on [sqlite3 db ""] database. 186e180c296Sdan# walmode-5.3.*: Try to set temp.journal_mode=WAL. 187e180c296Sdan# 188e180c296Sdando_test walmode-5.1.1 { 189e180c296Sdan sqlite3 db :memory: 190e180c296Sdan execsql { PRAGMA main.journal_mode } 191e180c296Sdan} {memory} 192e180c296Sdando_test walmode-5.1.2 { 193e180c296Sdan execsql { PRAGMA main.journal_mode = wal } 194e180c296Sdan} {memory} 195e180c296Sdando_test walmode-5.1.3 { 196e180c296Sdan execsql { 197e180c296Sdan BEGIN; 198e180c296Sdan CREATE TABLE t1(a, b); 199e180c296Sdan INSERT INTO t1 VALUES(1, 2); 200e180c296Sdan COMMIT; 201e180c296Sdan SELECT * FROM t1; 202e180c296Sdan PRAGMA main.journal_mode; 203e180c296Sdan } 204e180c296Sdan} {1 2 memory} 205e180c296Sdando_test walmode-5.1.4 { 206e180c296Sdan execsql { PRAGMA main.journal_mode = wal } 207e180c296Sdan} {memory} 208e180c296Sdando_test walmode-5.1.5 { 209e180c296Sdan execsql { 210e180c296Sdan INSERT INTO t1 VALUES(3, 4); 211e180c296Sdan SELECT * FROM t1; 212e180c296Sdan PRAGMA main.journal_mode; 213e180c296Sdan } 214e180c296Sdan} {1 2 3 4 memory} 215e180c296Sdan 2164565682fSdanif {$TEMP_STORE>=2} { 2174565682fSdan set tempJrnlMode memory 2184565682fSdan} else { 2194565682fSdan set tempJrnlMode delete 2204565682fSdan} 221e180c296Sdando_test walmode-5.2.1 { 222e180c296Sdan sqlite3 db "" 223e180c296Sdan execsql { PRAGMA main.journal_mode } 2244565682fSdan} $tempJrnlMode 225e180c296Sdando_test walmode-5.2.2 { 226e180c296Sdan execsql { PRAGMA main.journal_mode = wal } 2274565682fSdan} $tempJrnlMode 228e180c296Sdando_test walmode-5.2.3 { 229e180c296Sdan execsql { 230e180c296Sdan BEGIN; 231e180c296Sdan CREATE TABLE t1(a, b); 232e180c296Sdan INSERT INTO t1 VALUES(1, 2); 233e180c296Sdan COMMIT; 234e180c296Sdan SELECT * FROM t1; 235e180c296Sdan PRAGMA main.journal_mode; 236e180c296Sdan } 2374565682fSdan} [list 1 2 $tempJrnlMode] 238e180c296Sdando_test walmode-5.2.4 { 239e180c296Sdan execsql { PRAGMA main.journal_mode = wal } 2404565682fSdan} $tempJrnlMode 241e180c296Sdando_test walmode-5.2.5 { 242e180c296Sdan execsql { 243e180c296Sdan INSERT INTO t1 VALUES(3, 4); 244e180c296Sdan SELECT * FROM t1; 245e180c296Sdan PRAGMA main.journal_mode; 246e180c296Sdan } 2474565682fSdan} [list 1 2 3 4 $tempJrnlMode] 248e180c296Sdan 249e180c296Sdando_test walmode-5.3.1 { 250e180c296Sdan sqlite3 db test.db 251e180c296Sdan execsql { PRAGMA temp.journal_mode } 252d80b2338Sdrh} $tempJrnlMode 253e180c296Sdando_test walmode-5.3.2 { 254e180c296Sdan execsql { PRAGMA temp.journal_mode = wal } 255d80b2338Sdrh} $tempJrnlMode 256e180c296Sdando_test walmode-5.3.3 { 257e180c296Sdan execsql { 258e180c296Sdan BEGIN; 259e180c296Sdan CREATE TEMP TABLE t1(a, b); 260e180c296Sdan INSERT INTO t1 VALUES(1, 2); 261e180c296Sdan COMMIT; 262e180c296Sdan SELECT * FROM t1; 263e180c296Sdan PRAGMA temp.journal_mode; 264e180c296Sdan } 265d80b2338Sdrh} [list 1 2 $tempJrnlMode] 266e180c296Sdando_test walmode-5.3.4 { 267e180c296Sdan execsql { PRAGMA temp.journal_mode = wal } 268d80b2338Sdrh} $tempJrnlMode 269e180c296Sdando_test walmode-5.3.5 { 270e180c296Sdan execsql { 271e180c296Sdan INSERT INTO t1 VALUES(3, 4); 272e180c296Sdan SELECT * FROM t1; 273e180c296Sdan PRAGMA temp.journal_mode; 274e180c296Sdan } 275d80b2338Sdrh} [list 1 2 3 4 $tempJrnlMode] 276e180c296Sdan 2773f94b609Sdan 2783f94b609Sdan#------------------------------------------------------------------------- 2793f94b609Sdan# Test changing to WAL mode from journal_mode=off or journal_mode=memory 2803f94b609Sdan# 2813f94b609Sdanforeach {tn mode} { 282f6c61471Sdan 1 off 283f6c61471Sdan 2 memory 2843f94b609Sdan 3 persist 2853f94b609Sdan 4 delete 2863f94b609Sdan 5 truncate 2873f94b609Sdan} { 2883f94b609Sdan do_test walmode-6.$tn { 2893f94b609Sdan faultsim_delete_and_reopen 2903f94b609Sdan execsql " 2913f94b609Sdan PRAGMA journal_mode = $mode; 2923f94b609Sdan PRAGMA journal_mode = wal; 2933f94b609Sdan " 2943f94b609Sdan } [list $mode wal] 2953f94b609Sdan} 296f6c61471Sdandb close 297f6c61471Sdan 2988700b1e5Sdan#------------------------------------------------------------------------- 2998700b1e5Sdan# Test the effect of a "PRAGMA journal_mode" command being the first 3008700b1e5Sdan# thing executed by a new connection. This means that the schema is not 3018700b1e5Sdan# loaded when sqlite3_prepare_v2() is called to compile the statement. 3028700b1e5Sdan# 303f6c61471Sdando_test walmode-7.0 { 304fda06befSmistachkin forcedelete test.db 305f6c61471Sdan sqlite3 db test.db 306f6c61471Sdan execsql { 307f6c61471Sdan PRAGMA journal_mode = WAL; 308f6c61471Sdan CREATE TABLE t1(a, b); 309f6c61471Sdan } 310f6c61471Sdan} {wal} 311f6c61471Sdanforeach {tn sql result} { 312c6b2a0ffSdrh 1 "PRAGMA journal_mode" wal 313f6c61471Sdan 2 "PRAGMA main.journal_mode" wal 314f6c61471Sdan 3 "PRAGMA journal_mode = delete" delete 315f6c61471Sdan 4 "PRAGMA journal_mode" delete 316f6c61471Sdan 5 "PRAGMA main.journal_mode" delete 317f6c61471Sdan 6 "PRAGMA journal_mode = wal" wal 318c6b2a0ffSdrh 7 "PRAGMA journal_mode" wal 319f6c61471Sdan 8 "PRAGMA main.journal_mode" wal 320f6c61471Sdan 321c6b2a0ffSdrh 9 "PRAGMA journal_mode" wal 322f6c61471Sdan 10 "PRAGMA main.journal_mode" wal 323f6c61471Sdan 11 "PRAGMA main.journal_mode = delete" delete 324f6c61471Sdan 12 "PRAGMA journal_mode" delete 325f6c61471Sdan 13 "PRAGMA main.journal_mode" delete 326f6c61471Sdan 14 "PRAGMA main.journal_mode = wal" wal 327c6b2a0ffSdrh 15 "PRAGMA journal_mode" wal 328f6c61471Sdan 16 "PRAGMA main.journal_mode" wal 329f6c61471Sdan} { 330f6c61471Sdan do_test walmode-7.$tn { 331f6c61471Sdan db close 332f6c61471Sdan sqlite3 db test.db 333f6c61471Sdan execsql $sql 334f6c61471Sdan } $result 335f6c61471Sdan} 336f6c61471Sdandb close 3373f94b609Sdan 3388700b1e5Sdan#------------------------------------------------------------------------- 3398700b1e5Sdan# Test the effect of a "PRAGMA journal_mode" command on an attached 3408700b1e5Sdan# database. 3418700b1e5Sdan# 3428700b1e5Sdanfaultsim_delete_and_reopen 3438700b1e5Sdando_execsql_test walmode-8.1 { 3448700b1e5Sdan CREATE TABLE t1(a, b); 3458700b1e5Sdan PRAGMA journal_mode = WAL; 3468700b1e5Sdan ATTACH 'test.db2' AS two; 3478700b1e5Sdan CREATE TABLE two.t2(a, b); 3488700b1e5Sdan} {wal} 3498700b1e5Sdando_execsql_test walmode-8.2 { PRAGMA main.journal_mode } {wal} 350c6b2a0ffSdrhdo_execsql_test walmode-8.3 { PRAGMA two.journal_mode } {delete} 3518700b1e5Sdando_execsql_test walmode-8.4 { PRAGMA two.journal_mode = DELETE } {delete} 3528700b1e5Sdan 3538700b1e5Sdandb close 3548700b1e5Sdansqlite3 db test.db 3558700b1e5Sdando_execsql_test walmode-8.5 { ATTACH 'test.db2' AS two } {} 3568700b1e5Sdando_execsql_test walmode-8.6 { PRAGMA main.journal_mode } {wal} 3578700b1e5Sdando_execsql_test walmode-8.7 { PRAGMA two.journal_mode } {delete} 3588700b1e5Sdando_execsql_test walmode-8.8 { INSERT INTO two.t2 DEFAULT VALUES } {} 3598700b1e5Sdando_execsql_test walmode-8.9 { PRAGMA two.journal_mode } {delete} 3608700b1e5Sdando_execsql_test walmode-8.10 { INSERT INTO t1 DEFAULT VALUES } {} 3618700b1e5Sdando_execsql_test walmode-8.11 { PRAGMA main.journal_mode } {wal} 362c6b2a0ffSdrhdo_execsql_test walmode-8.12 { PRAGMA journal_mode } {wal} 363c6b2a0ffSdrh 364c6b2a0ffSdrh# Change to WAL mode on test2.db and make sure (in the tests that follow) 365c6b2a0ffSdrh# that this mode change persists. 366c6b2a0ffSdrhdo_test walmode-8.x1 { 367c6b2a0ffSdrh execsql { 368c6b2a0ffSdrh PRAGMA two.journal_mode=WAL; 369c6b2a0ffSdrh PRAGMA two.journal_mode; 370c6b2a0ffSdrh } 371c6b2a0ffSdrh} {wal wal} 3728700b1e5Sdan 3738700b1e5Sdandb close 3748700b1e5Sdansqlite3 db test.db 3758700b1e5Sdando_execsql_test walmode-8.13 { PRAGMA journal_mode = WAL } {wal} 3768700b1e5Sdando_execsql_test walmode-8.14 { ATTACH 'test.db2' AS two } {} 3778700b1e5Sdando_execsql_test walmode-8.15 { PRAGMA main.journal_mode } {wal} 3788700b1e5Sdando_execsql_test walmode-8.16 { PRAGMA two.journal_mode } {wal} 3798700b1e5Sdando_execsql_test walmode-8.17 { INSERT INTO two.t2 DEFAULT VALUES } {} 3808700b1e5Sdando_execsql_test walmode-8.18 { PRAGMA two.journal_mode } {wal} 3818700b1e5Sdan 3828700b1e5Sdansqlite3 db2 test.db2 3838700b1e5Sdando_test walmode-8.19 { execsql { PRAGMA main.journal_mode } db2 } {wal} 3848700b1e5Sdandb2 close 3858700b1e5Sdan 38673d66fdbSdando_execsql_test walmode-8.20 { PRAGMA journal_mode = DELETE } {delete} 38773d66fdbSdando_execsql_test walmode-8.21 { PRAGMA main.journal_mode } {delete} 38873d66fdbSdando_execsql_test walmode-8.22 { PRAGMA two.journal_mode } {delete} 38973d66fdbSdando_execsql_test walmode-8.21 { PRAGMA journal_mode = WAL } {wal} 39073d66fdbSdando_execsql_test walmode-8.21 { PRAGMA main.journal_mode } {wal} 39173d66fdbSdando_execsql_test walmode-8.22 { PRAGMA two.journal_mode } {wal} 39273d66fdbSdan 393e04dc88bSdanfinish_test 394