1f77b610eSdan# 2011 May 06 2f77b610eSdan# 3f77b610eSdan# The author disclaims copyright to this source code. In place of 4f77b610eSdan# a legal notice, here is a blessing: 5f77b610eSdan# 6f77b610eSdan# May you do good and not evil. 7f77b610eSdan# May you find forgiveness for yourself and forgive others. 8f77b610eSdan# May you share freely, never taking more than you give. 9f77b610eSdan# 10f77b610eSdan#*********************************************************************** 11f77b610eSdan# 12f77b610eSdan 13f77b610eSdanset testdir [file dirname $argv0] 14f77b610eSdansource $testdir/tester.tcl 15f77b610eSdanset testprefix e_wal 16f77b610eSdan 17f77b610eSdandb close 18*79201620Sdanforcedelete test.db-shm 19f77b610eSdantestvfs oldvfs -iversion 1 20f77b610eSdan 21f77b610eSdan 22f77b610eSdan# EVIDENCE-OF: R-58297-14483 WAL databases can be created, read, and 23f77b610eSdan# written even if shared memory is unavailable as long as the 24f77b610eSdan# locking_mode is set to EXCLUSIVE before the first attempted access. 25f77b610eSdan# 26f77b610eSdan# EVIDENCE-OF: R-00449-33772 This feature allows WAL databases to be 27f77b610eSdan# created, read, and written by legacy VFSes that lack the "version 2" 28f77b610eSdan# shared-memory methods xShmMap, xShmLock, xShmBarrier, and xShmUnmap on 29f77b610eSdan# the sqlite3_io_methods object. 30f77b610eSdan# 31f77b610eSdan# 1.1: "create" tests. 32f77b610eSdan# 1.2: "read" tests. 33f77b610eSdan# 1.3: "write" tests. 34f77b610eSdan# 35f77b610eSdan# All three done with VFS "oldvfs", which has iVersion==1 and so does 36f77b610eSdan# not support shared memory. 37f77b610eSdan# 38f77b610eSdansqlite3 db test.db -vfs oldvfs 39f77b610eSdando_execsql_test 1.1.1 { 40f77b610eSdan PRAGMA journal_mode = WAL; 41f77b610eSdan} {delete} 42f77b610eSdando_execsql_test 1.1.2 { 43f77b610eSdan PRAGMA locking_mode = EXCLUSIVE; 44f77b610eSdan PRAGMA journal_mode = WAL; 45f77b610eSdan} {exclusive wal} 46f77b610eSdando_execsql_test 1.1.3 { 47f77b610eSdan CREATE TABLE t1(x, y); 48f77b610eSdan INSERT INTO t1 VALUES(1, 2); 49f77b610eSdan} {} 50f77b610eSdando_test 1.1.4 { 51f77b610eSdan list [file exists test.db-shm] [file exists test.db-wal] 52f77b610eSdan} {0 1} 53f77b610eSdan 54f77b610eSdando_test 1.2.1 { 55f77b610eSdan db close 56f77b610eSdan sqlite3 db test.db -vfs oldvfs 57f77b610eSdan catchsql { SELECT * FROM t1 } 58f77b610eSdan} {1 {unable to open database file}} 59f77b610eSdando_test 1.2.2 { 60f77b610eSdan execsql { PRAGMA locking_mode = EXCLUSIVE } 61f77b610eSdan execsql { SELECT * FROM t1 } 62f77b610eSdan} {1 2} 63f77b610eSdando_test 1.2.3 { 64f77b610eSdan list [file exists test.db-shm] [file exists test.db-wal] 65f77b610eSdan} {0 1} 66f77b610eSdan 67f77b610eSdando_test 1.3.1 { 68f77b610eSdan db close 69f77b610eSdan sqlite3 db test.db -vfs oldvfs 70f77b610eSdan catchsql { INSERT INTO t1 VALUES(3, 4) } 71f77b610eSdan} {1 {unable to open database file}} 72f77b610eSdando_test 1.3.2 { 73f77b610eSdan execsql { PRAGMA locking_mode = EXCLUSIVE } 74f77b610eSdan execsql { INSERT INTO t1 VALUES(3, 4) } 75f77b610eSdan execsql { SELECT * FROM t1 } 76f77b610eSdan} {1 2 3 4} 77f77b610eSdando_test 1.3.3 { 78f77b610eSdan list [file exists test.db-shm] [file exists test.db-wal] 79f77b610eSdan} {0 1} 80f77b610eSdan 81f77b610eSdan# EVIDENCE-OF: R-31969-57825 If EXCLUSIVE locking mode is set prior to 82f77b610eSdan# the first WAL-mode database access, then SQLite never attempts to call 83f77b610eSdan# any of the shared-memory methods and hence no shared-memory wal-index 84f77b610eSdan# is ever created. 85f77b610eSdan# 86f77b610eSdandb close 87f77b610eSdansqlite3 db test.db 88f77b610eSdando_execsql_test 2.1.1 { 89f77b610eSdan PRAGMA locking_mode = EXCLUSIVE; 90f77b610eSdan SELECT * FROM t1; 91f77b610eSdan} {exclusive 1 2 3 4} 92f77b610eSdando_test 2.1.2 { 93f77b610eSdan list [file exists test.db-shm] [file exists test.db-wal] 94f77b610eSdan} {0 1} 95f77b610eSdan 96f77b610eSdan# EVIDENCE-OF: R-36328-16367 In that case, the database connection 97f77b610eSdan# remains in EXCLUSIVE mode as long as the journal mode is WAL; attempts 98f77b610eSdan# to change the locking mode using "PRAGMA locking_mode=NORMAL;" are 99f77b610eSdan# no-ops. 100f77b610eSdan# 101f77b610eSdando_execsql_test 2.2.1 { 102f77b610eSdan PRAGMA locking_mode = NORMAL; 103f77b610eSdan SELECT * FROM t1; 104f77b610eSdan} {exclusive 1 2 3 4} 105f77b610eSdando_test 2.2.2 { 106f77b610eSdan sqlite3 db2 test.db 107f77b610eSdan catchsql {SELECT * FROM t1} db2 108f77b610eSdan} {1 {database is locked}} 109f77b610eSdandb2 close 110f77b610eSdan 111f77b610eSdan# EVIDENCE-OF: R-63522-46088 The only way to change out of EXCLUSIVE 112f77b610eSdan# locking mode is to first change out of WAL journal mode. 113f77b610eSdan# 114f77b610eSdando_execsql_test 2.3.1 { 115f77b610eSdan PRAGMA journal_mode = DELETE; 116f77b610eSdan SELECT * FROM t1; 117f77b610eSdan} {delete 1 2 3 4} 118f77b610eSdando_test 2.3.2 { 119f77b610eSdan sqlite3 db2 test.db 120f77b610eSdan catchsql {SELECT * FROM t1} db2 121f77b610eSdan} {1 {database is locked}} 122f77b610eSdando_execsql_test 2.3.3 { 123f77b610eSdan PRAGMA locking_mode = NORMAL; 124f77b610eSdan SELECT * FROM t1; 125f77b610eSdan} {normal 1 2 3 4} 126f77b610eSdando_test 2.3.4 { 127f77b610eSdan sqlite3 db2 test.db 128f77b610eSdan catchsql {SELECT * FROM t1} db2 129f77b610eSdan} {0 {1 2 3 4}} 130f77b610eSdandb2 close 131f77b610eSdandb close 132f77b610eSdan 133f77b610eSdan 134f77b610eSdan# EVIDENCE-OF: R-57239-11845 If NORMAL locking mode is in effect for the 135f77b610eSdan# first WAL-mode database access, then the shared-memory wal-index is 136f77b610eSdan# created. 137f77b610eSdan# 138f77b610eSdando_test 3.0 { 139f77b610eSdan sqlite3 db test.db 140f77b610eSdan execsql { PRAGMA journal_mode = WAL } 141f77b610eSdan db close 142f77b610eSdan} {} 143f77b610eSdando_test 3.1 { 144f77b610eSdan sqlite3 db test.db 145f77b610eSdan execsql { SELECT * FROM t1 } 146f77b610eSdan list [file exists test.db-shm] [file exists test.db-wal] 147f77b610eSdan} {1 1} 148f77b610eSdan 149f77b610eSdan# EVIDENCE-OF: R-13779-07711 As long as exactly one connection is using 150f77b610eSdan# a shared-memory wal-index, the locking mode can be changed freely 151f77b610eSdan# between NORMAL and EXCLUSIVE. 152f77b610eSdan# 153f77b610eSdando_execsql_test 3.2.1 { 154f77b610eSdan PRAGMA locking_mode = EXCLUSIVE; 155f77b610eSdan PRAGMA locking_mode = NORMAL; 156f77b610eSdan PRAGMA locking_mode = EXCLUSIVE; 157f77b610eSdan INSERT INTO t1 VALUES(5, 6); 158f77b610eSdan} {exclusive normal exclusive} 159f77b610eSdando_test 3.2.2 { 160f77b610eSdan sqlite3 db2 test.db 161f77b610eSdan catchsql { SELECT * FROM t1 } db2 162f77b610eSdan} {1 {database is locked}} 163f77b610eSdan 164f77b610eSdan# EVIDENCE-OF: R-10993-11647 It is only when the shared-memory wal-index 165f77b610eSdan# is omitted, when the locking mode is EXCLUSIVE prior to the first 166f77b610eSdan# WAL-mode database access, that the locking mode is stuck in EXCLUSIVE. 167f77b610eSdan# 168f77b610eSdando_execsql_test 3.2.3 { 169f77b610eSdan PRAGMA locking_mode = NORMAL; 170f77b610eSdan SELECT * FROM t1; 171f77b610eSdan} {normal 1 2 3 4 5 6} 172f77b610eSdando_test 3.2.4 { 173f77b610eSdan catchsql { SELECT * FROM t1 } db2 174f77b610eSdan} {0 {1 2 3 4 5 6}} 175f77b610eSdan 176f77b610eSdando_catchsql_test 3.2.5 { 177f77b610eSdan PRAGMA locking_mode = EXCLUSIVE; 178f77b610eSdan INSERT INTO t1 VALUES(7, 8); 179f77b610eSdan} {1 {database is locked}} 180f77b610eSdan 181f77b610eSdandb2 close 182f77b610eSdan 183f77b610eSdan# EVIDENCE-OF: R-46197-42811 This means that the underlying VFS must 184f77b610eSdan# support the "version 2" shared-memory. 185f77b610eSdan# 186f77b610eSdan# EVIDENCE-OF: R-55316-21772 If the VFS does not support shared-memory 187f77b610eSdan# methods, then the attempt to open a database that is already in WAL 188f77b610eSdan# mode, or the attempt convert a database into WAL mode, will fail. 189f77b610eSdan# 190f77b610eSdandb close 191f77b610eSdando_test 3.4.1 { 192f77b610eSdan sqlite3 db test.db -vfs oldvfs 193f77b610eSdan catchsql { SELECT * FROM t1 } 194f77b610eSdan} {1 {unable to open database file}} 195f77b610eSdandb close 196f77b610eSdando_test 3.4.2 { 197f77b610eSdan forcedelete test.db2 198f77b610eSdan sqlite3 db test.db2 -vfs oldvfs 199f77b610eSdan catchsql { PRAGMA journal_mode = WAL } 200f77b610eSdan} {0 delete} 201f77b610eSdandb close 202f77b610eSdan 203f77b610eSdan 204531b55eaSdrh# EVIDENCE-OF: R-45540-25505 To prevent older versions of SQLite (prior 205531b55eaSdrh# to version 3.7.0, 2010-07-22) from trying to recover a WAL-mode 206531b55eaSdrh# database (and making matters worse) the database file format version 207531b55eaSdrh# numbers (bytes 18 and 19 in the database header) are increased from 1 208531b55eaSdrh# to 2 in WAL mode. 209f77b610eSdan# 210f77b610eSdanreset_db 211f77b610eSdando_execsql_test 4.1.1 { CREATE TABLE t1(x, y) } 212f77b610eSdando_test 4.1.2 { hexio_read test.db 18 2 } {0101} 213f77b610eSdando_execsql_test 4.1.3 { PRAGMA journal_mode = wAL } {wal} 214f77b610eSdando_test 4.1.4 { hexio_read test.db 18 2 } {0202} 215f77b610eSdan 216f77b610eSdan 217f77b610eSdan# EVIDENCE-OF: R-02535-05811 One can explicitly change out of WAL mode 218f77b610eSdan# using a pragma such as this: PRAGMA journal_mode=DELETE; 219f77b610eSdan# 220f77b610eSdando_execsql_test 4.2.1 { INSERT INTO t1 VALUES(1, 1); } {} 221f77b610eSdando_test 4.2.2 { file exists test.db-wal } {1} 222f77b610eSdando_execsql_test 4.2.3 { PRAGMA journal_mode = delete } {delete} 223f77b610eSdando_test 4.2.4 { file exists test.db-wal } {0} 224f77b610eSdan 225f77b610eSdan# EVIDENCE-OF: R-60175-02388 Deliberately changing out of WAL mode 226f77b610eSdan# changes the database file format version numbers back to 1 so that 227f77b610eSdan# older versions of SQLite can once again access the database file. 228f77b610eSdan# 229f77b610eSdando_test 4.3 { hexio_read test.db 18 2 } {0101} 230f77b610eSdan 231f77b610eSdanfinish_test 232