000001 # 2011 May 06 000002 # 000003 # The author disclaims copyright to this source code. In place of 000004 # a legal notice, here is a blessing: 000005 # 000006 # May you do good and not evil. 000007 # May you find forgiveness for yourself and forgive others. 000008 # May you share freely, never taking more than you give. 000009 # 000010 #*********************************************************************** 000011 # 000012 000013 set testdir [file dirname $argv0] 000014 source $testdir/tester.tcl 000015 set testprefix e_wal 000016 000017 db close 000018 testvfs oldvfs -iversion 1 000019 000020 000021 # EVIDENCE-OF: R-58297-14483 WAL databases can be created, read, and 000022 # written even if shared memory is unavailable as long as the 000023 # locking_mode is set to EXCLUSIVE before the first attempted access. 000024 # 000025 # EVIDENCE-OF: R-00449-33772 This feature allows WAL databases to be 000026 # created, read, and written by legacy VFSes that lack the "version 2" 000027 # shared-memory methods xShmMap, xShmLock, xShmBarrier, and xShmUnmap on 000028 # the sqlite3_io_methods object. 000029 # 000030 # 1.1: "create" tests. 000031 # 1.2: "read" tests. 000032 # 1.3: "write" tests. 000033 # 000034 # All three done with VFS "oldvfs", which has iVersion==1 and so does 000035 # not support shared memory. 000036 # 000037 sqlite3 db test.db -vfs oldvfs 000038 do_execsql_test 1.1.1 { 000039 PRAGMA journal_mode = WAL; 000040 } {delete} 000041 do_execsql_test 1.1.2 { 000042 PRAGMA locking_mode = EXCLUSIVE; 000043 PRAGMA journal_mode = WAL; 000044 } {exclusive wal} 000045 do_execsql_test 1.1.3 { 000046 CREATE TABLE t1(x, y); 000047 INSERT INTO t1 VALUES(1, 2); 000048 } {} 000049 do_test 1.1.4 { 000050 list [file exists test.db-shm] [file exists test.db-wal] 000051 } {0 1} 000052 000053 do_test 1.2.1 { 000054 db close 000055 sqlite3 db test.db -vfs oldvfs 000056 catchsql { SELECT * FROM t1 } 000057 } {1 {unable to open database file}} 000058 do_test 1.2.2 { 000059 execsql { PRAGMA locking_mode = EXCLUSIVE } 000060 execsql { SELECT * FROM t1 } 000061 } {1 2} 000062 do_test 1.2.3 { 000063 list [file exists test.db-shm] [file exists test.db-wal] 000064 } {0 1} 000065 000066 do_test 1.3.1 { 000067 db close 000068 sqlite3 db test.db -vfs oldvfs 000069 catchsql { INSERT INTO t1 VALUES(3, 4) } 000070 } {1 {unable to open database file}} 000071 do_test 1.3.2 { 000072 execsql { PRAGMA locking_mode = EXCLUSIVE } 000073 execsql { INSERT INTO t1 VALUES(3, 4) } 000074 execsql { SELECT * FROM t1 } 000075 } {1 2 3 4} 000076 do_test 1.3.3 { 000077 list [file exists test.db-shm] [file exists test.db-wal] 000078 } {0 1} 000079 000080 # EVIDENCE-OF: R-31969-57825 If EXCLUSIVE locking mode is set prior to 000081 # the first WAL-mode database access, then SQLite never attempts to call 000082 # any of the shared-memory methods and hence no shared-memory wal-index 000083 # is ever created. 000084 # 000085 db close 000086 sqlite3 db test.db 000087 do_execsql_test 2.1.1 { 000088 PRAGMA locking_mode = EXCLUSIVE; 000089 SELECT * FROM t1; 000090 } {exclusive 1 2 3 4} 000091 do_test 2.1.2 { 000092 list [file exists test.db-shm] [file exists test.db-wal] 000093 } {0 1} 000094 000095 # EVIDENCE-OF: R-36328-16367 In that case, the database connection 000096 # remains in EXCLUSIVE mode as long as the journal mode is WAL; attempts 000097 # to change the locking mode using "PRAGMA locking_mode=NORMAL;" are 000098 # no-ops. 000099 # 000100 do_execsql_test 2.2.1 { 000101 PRAGMA locking_mode = NORMAL; 000102 SELECT * FROM t1; 000103 } {exclusive 1 2 3 4} 000104 do_test 2.2.2 { 000105 sqlite3 db2 test.db 000106 catchsql {SELECT * FROM t1} db2 000107 } {1 {database is locked}} 000108 db2 close 000109 000110 # EVIDENCE-OF: R-63522-46088 The only way to change out of EXCLUSIVE 000111 # locking mode is to first change out of WAL journal mode. 000112 # 000113 do_execsql_test 2.3.1 { 000114 PRAGMA journal_mode = DELETE; 000115 SELECT * FROM t1; 000116 } {delete 1 2 3 4} 000117 do_test 2.3.2 { 000118 sqlite3 db2 test.db 000119 catchsql {SELECT * FROM t1} db2 000120 } {1 {database is locked}} 000121 do_execsql_test 2.3.3 { 000122 PRAGMA locking_mode = NORMAL; 000123 SELECT * FROM t1; 000124 } {normal 1 2 3 4} 000125 do_test 2.3.4 { 000126 sqlite3 db2 test.db 000127 catchsql {SELECT * FROM t1} db2 000128 } {0 {1 2 3 4}} 000129 db2 close 000130 db close 000131 000132 000133 # EVIDENCE-OF: R-57239-11845 If NORMAL locking mode is in effect for the 000134 # first WAL-mode database access, then the shared-memory wal-index is 000135 # created. 000136 # 000137 do_test 3.0 { 000138 sqlite3 db test.db 000139 execsql { PRAGMA journal_mode = WAL } 000140 db close 000141 } {} 000142 do_test 3.1 { 000143 sqlite3 db test.db 000144 execsql { SELECT * FROM t1 } 000145 list [file exists test.db-shm] [file exists test.db-wal] 000146 } {1 1} 000147 000148 # EVIDENCE-OF: R-13779-07711 As long as exactly one connection is using 000149 # a shared-memory wal-index, the locking mode can be changed freely 000150 # between NORMAL and EXCLUSIVE. 000151 # 000152 do_execsql_test 3.2.1 { 000153 PRAGMA locking_mode = EXCLUSIVE; 000154 PRAGMA locking_mode = NORMAL; 000155 PRAGMA locking_mode = EXCLUSIVE; 000156 INSERT INTO t1 VALUES(5, 6); 000157 } {exclusive normal exclusive} 000158 do_test 3.2.2 { 000159 sqlite3 db2 test.db 000160 catchsql { SELECT * FROM t1 } db2 000161 } {1 {database is locked}} 000162 000163 # EVIDENCE-OF: R-10993-11647 It is only when the shared-memory wal-index 000164 # is omitted, when the locking mode is EXCLUSIVE prior to the first 000165 # WAL-mode database access, that the locking mode is stuck in EXCLUSIVE. 000166 # 000167 do_execsql_test 3.2.3 { 000168 PRAGMA locking_mode = NORMAL; 000169 SELECT * FROM t1; 000170 } {normal 1 2 3 4 5 6} 000171 do_test 3.2.4 { 000172 catchsql { SELECT * FROM t1 } db2 000173 } {0 {1 2 3 4 5 6}} 000174 000175 do_catchsql_test 3.2.5 { 000176 PRAGMA locking_mode = EXCLUSIVE; 000177 INSERT INTO t1 VALUES(7, 8); 000178 } {1 {database is locked}} 000179 000180 db2 close 000181 000182 # EVIDENCE-OF: R-46197-42811 This means that the underlying VFS must 000183 # support the "version 2" shared-memory. 000184 # 000185 # EVIDENCE-OF: R-55316-21772 If the VFS does not support shared-memory 000186 # methods, then the attempt to open a database that is already in WAL 000187 # mode, or the attempt convert a database into WAL mode, will fail. 000188 # 000189 db close 000190 do_test 3.4.1 { 000191 sqlite3 db test.db -vfs oldvfs 000192 catchsql { SELECT * FROM t1 } 000193 } {1 {unable to open database file}} 000194 db close 000195 do_test 3.4.2 { 000196 forcedelete test.db2 000197 sqlite3 db test.db2 -vfs oldvfs 000198 catchsql { PRAGMA journal_mode = WAL } 000199 } {0 delete} 000200 db close 000201 000202 000203 # EVIDENCE-OF: R-45540-25505 To prevent older versions of SQLite (prior 000204 # to version 3.7.0, 2010-07-22) from trying to recover a WAL-mode 000205 # database (and making matters worse) the database file format version 000206 # numbers (bytes 18 and 19 in the database header) are increased from 1 000207 # to 2 in WAL mode. 000208 # 000209 reset_db 000210 do_execsql_test 4.1.1 { CREATE TABLE t1(x, y) } 000211 do_test 4.1.2 { hexio_read test.db 18 2 } {0101} 000212 do_execsql_test 4.1.3 { PRAGMA journal_mode = wAL } {wal} 000213 do_test 4.1.4 { hexio_read test.db 18 2 } {0202} 000214 000215 000216 # EVIDENCE-OF: R-02535-05811 One can explicitly change out of WAL mode 000217 # using a pragma such as this: PRAGMA journal_mode=DELETE; 000218 # 000219 do_execsql_test 4.2.1 { INSERT INTO t1 VALUES(1, 1); } {} 000220 do_test 4.2.2 { file exists test.db-wal } {1} 000221 do_execsql_test 4.2.3 { PRAGMA journal_mode = delete } {delete} 000222 do_test 4.2.4 { file exists test.db-wal } {0} 000223 000224 # EVIDENCE-OF: R-60175-02388 Deliberately changing out of WAL mode 000225 # changes the database file format version numbers back to 1 so that 000226 # older versions of SQLite can once again access the database file. 000227 # 000228 do_test 4.3 { hexio_read test.db 18 2 } {0101} 000229 000230 finish_test