1# 2010 April 19 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# This file implements regression tests for SQLite library. The 12# focus of this file is testing the operation of the library in 13# "PRAGMA journal_mode=WAL" mode. 14# 15 16set testdir [file dirname $argv0] 17source $testdir/tester.tcl 18source $testdir/malloc_common.tcl 19 20# If the library was compiled without WAL support, check that the 21# "PRAGMA journal_mode=WAL" treats "WAL" as an unrecognized mode. 22# 23ifcapable !wal { 24 25 do_test walmode-0.1 { 26 execsql { PRAGMA journal_mode = wal } 27 } {delete} 28 do_test walmode-0.2 { 29 execsql { PRAGMA main.journal_mode = wal } 30 } {delete} 31 do_test walmode-0.3 { 32 execsql { PRAGMA main.journal_mode } 33 } {delete} 34 35 finish_test 36 return 37} 38 39do_test walmode-1.1 { 40 set sqlite_sync_count 0 41 execsql { PRAGMA page_size = 1024 } 42 execsql { PRAGMA journal_mode = wal } 43} {wal} 44do_test walmode-1.2 { 45 file size test.db 46} {1024} 47 48if {[atomic_batch_write test.db]==0} { 49 set expected_sync_count 3 50 if {$::tcl_platform(platform)!="windows"} { 51 ifcapable dirsync { 52 incr expected_sync_count 53 } 54 } 55 do_test walmode-1.3 { 56 set sqlite_sync_count 57 } $expected_sync_count 58} 59 60do_test walmode-1.4 { 61 file exists test.db-wal 62} {0} 63do_test walmode-1.5 { 64 execsql { CREATE TABLE t1(a, b) } 65 file size test.db 66} {1024} 67do_test walmode-1.6 { 68 file exists test.db-wal 69} {1} 70do_test walmode-1.7 { 71 db close 72 file exists test.db-wal 73} {0} 74 75# There is now a database file with the read and write versions set to 2 76# in the file system. This file should default to WAL mode. 77# 78do_test walmode-2.1 { 79 sqlite3 db test.db 80 file exists test.db-wal 81} {0} 82do_test walmode-2.2 { 83 execsql { SELECT * FROM sqlite_master } 84 file exists test.db-wal 85} {1} 86do_test walmode-2.3 { 87 db close 88 file exists test.db-wal 89} {0} 90 91# If the first statement executed is "PRAGMA journal_mode = wal", and 92# the file is already configured for WAL (read and write versions set 93# to 2), then there should be no need to write the database. The 94# statement should cause the client to connect to the log file. 95# 96set sqlite_sync_count 0 97do_test walmode-3.1 { 98 sqlite3 db test.db 99 execsql { PRAGMA journal_mode = wal } 100} {wal} 101do_test walmode-3.2 { 102 list $sqlite_sync_count [file exists test.db-wal] [file size test.db-wal] 103} {0 1 0} 104 105# Test that changing back to journal_mode=persist works. 106# 107do_test walmode-4.1 { 108 execsql { INSERT INTO t1 VALUES(1, 2) } 109 execsql { PRAGMA journal_mode = persist } 110} {persist} 111if {[atomic_batch_write test.db]==0} { 112 do_test walmode-4.2 { 113 list [file exists test.db-journal] [file exists test.db-wal] 114 } {1 0} 115} 116do_test walmode-4.3 { 117 execsql { SELECT * FROM t1 } 118} {1 2} 119do_test walmode-4.4 { 120 db close 121 sqlite3 db test.db 122 execsql { SELECT * FROM t1 } 123} {1 2} 124if {[atomic_batch_write test.db]==0} { 125 do_test walmode-4.5 { 126 list [file exists test.db-journal] [file exists test.db-wal] 127 } {1 0} 128} 129 130# Test that nothing goes wrong if a connection is prevented from changing 131# from WAL to rollback mode because a second connection has the database 132# open. Or from rollback to WAL. 133# 134do_test walmode-4.6 { 135 sqlite3 db2 test.db 136 execsql { PRAGMA main.journal_mode } db2 137} {delete} 138do_test walmode-4.7 { 139 execsql { PRAGMA main.journal_mode = wal } db 140} {wal} 141do_test walmode-4.8 { 142 execsql { SELECT * FROM t1 } db2 143} {1 2} 144do_test walmode-4.9 { 145 catchsql { PRAGMA journal_mode = delete } db 146} {1 {database is locked}} 147do_test walmode-4.10 { 148 execsql { PRAGMA main.journal_mode } db 149} {wal} 150 151do_test walmode-4.11 { 152 db2 close 153 execsql { PRAGMA journal_mode = delete } db 154} {delete} 155do_test walmode-4.12 { 156 execsql { PRAGMA main.journal_mode } db 157} {delete} 158do_test walmode-4.13 { 159 list [file exists test.db-journal] [file exists test.db-wal] 160} {0 0} 161do_test walmode-4.14 { 162 sqlite3 db2 test.db 163 execsql { 164 BEGIN; 165 SELECT * FROM t1; 166 } db2 167} {1 2} 168 169do_test walmode-4.16 { execsql { PRAGMA main.journal_mode } db } {delete} 170do_test walmode-4.17 { execsql { PRAGMA main.journal_mode } db2 } {delete} 171 172do_test walmode-4.17 { 173 catchsql { PRAGMA main.journal_mode = wal } db 174} {1 {database is locked}} 175do_test walmode-4.18 { 176 execsql { PRAGMA main.journal_mode } db 177} {delete} 178catch { db close } 179catch { db2 close } 180 181# Test that it is not possible to change a temporary or in-memory database 182# to WAL mode. WAL mode is for persistent file-backed databases only. 183# 184# walmode-5.1.*: Try to set journal_mode=WAL on [sqlite3 db :memory:] database. 185# walmode-5.2.*: Try to set journal_mode=WAL on [sqlite3 db ""] database. 186# walmode-5.3.*: Try to set temp.journal_mode=WAL. 187# 188do_test walmode-5.1.1 { 189 sqlite3 db :memory: 190 execsql { PRAGMA main.journal_mode } 191} {memory} 192do_test walmode-5.1.2 { 193 execsql { PRAGMA main.journal_mode = wal } 194} {memory} 195do_test walmode-5.1.3 { 196 execsql { 197 BEGIN; 198 CREATE TABLE t1(a, b); 199 INSERT INTO t1 VALUES(1, 2); 200 COMMIT; 201 SELECT * FROM t1; 202 PRAGMA main.journal_mode; 203 } 204} {1 2 memory} 205do_test walmode-5.1.4 { 206 execsql { PRAGMA main.journal_mode = wal } 207} {memory} 208do_test walmode-5.1.5 { 209 execsql { 210 INSERT INTO t1 VALUES(3, 4); 211 SELECT * FROM t1; 212 PRAGMA main.journal_mode; 213 } 214} {1 2 3 4 memory} 215 216if {$TEMP_STORE>=2} { 217 set tempJrnlMode memory 218} else { 219 set tempJrnlMode delete 220} 221do_test walmode-5.2.1 { 222 sqlite3 db "" 223 execsql { PRAGMA main.journal_mode } 224} $tempJrnlMode 225do_test walmode-5.2.2 { 226 execsql { PRAGMA main.journal_mode = wal } 227} $tempJrnlMode 228do_test walmode-5.2.3 { 229 execsql { 230 BEGIN; 231 CREATE TABLE t1(a, b); 232 INSERT INTO t1 VALUES(1, 2); 233 COMMIT; 234 SELECT * FROM t1; 235 PRAGMA main.journal_mode; 236 } 237} [list 1 2 $tempJrnlMode] 238do_test walmode-5.2.4 { 239 execsql { PRAGMA main.journal_mode = wal } 240} $tempJrnlMode 241do_test walmode-5.2.5 { 242 execsql { 243 INSERT INTO t1 VALUES(3, 4); 244 SELECT * FROM t1; 245 PRAGMA main.journal_mode; 246 } 247} [list 1 2 3 4 $tempJrnlMode] 248 249do_test walmode-5.3.1 { 250 sqlite3 db test.db 251 execsql { PRAGMA temp.journal_mode } 252} $tempJrnlMode 253do_test walmode-5.3.2 { 254 execsql { PRAGMA temp.journal_mode = wal } 255} $tempJrnlMode 256do_test walmode-5.3.3 { 257 execsql { 258 BEGIN; 259 CREATE TEMP TABLE t1(a, b); 260 INSERT INTO t1 VALUES(1, 2); 261 COMMIT; 262 SELECT * FROM t1; 263 PRAGMA temp.journal_mode; 264 } 265} [list 1 2 $tempJrnlMode] 266do_test walmode-5.3.4 { 267 execsql { PRAGMA temp.journal_mode = wal } 268} $tempJrnlMode 269do_test walmode-5.3.5 { 270 execsql { 271 INSERT INTO t1 VALUES(3, 4); 272 SELECT * FROM t1; 273 PRAGMA temp.journal_mode; 274 } 275} [list 1 2 3 4 $tempJrnlMode] 276 277 278#------------------------------------------------------------------------- 279# Test changing to WAL mode from journal_mode=off or journal_mode=memory 280# 281foreach {tn mode} { 282 1 off 283 2 memory 284 3 persist 285 4 delete 286 5 truncate 287} { 288 do_test walmode-6.$tn { 289 faultsim_delete_and_reopen 290 execsql " 291 PRAGMA journal_mode = $mode; 292 PRAGMA journal_mode = wal; 293 " 294 } [list $mode wal] 295} 296db close 297 298#------------------------------------------------------------------------- 299# Test the effect of a "PRAGMA journal_mode" command being the first 300# thing executed by a new connection. This means that the schema is not 301# loaded when sqlite3_prepare_v2() is called to compile the statement. 302# 303do_test walmode-7.0 { 304 forcedelete test.db 305 sqlite3 db test.db 306 execsql { 307 PRAGMA journal_mode = WAL; 308 CREATE TABLE t1(a, b); 309 } 310} {wal} 311foreach {tn sql result} { 312 1 "PRAGMA journal_mode" wal 313 2 "PRAGMA main.journal_mode" wal 314 3 "PRAGMA journal_mode = delete" delete 315 4 "PRAGMA journal_mode" delete 316 5 "PRAGMA main.journal_mode" delete 317 6 "PRAGMA journal_mode = wal" wal 318 7 "PRAGMA journal_mode" wal 319 8 "PRAGMA main.journal_mode" wal 320 321 9 "PRAGMA journal_mode" wal 322 10 "PRAGMA main.journal_mode" wal 323 11 "PRAGMA main.journal_mode = delete" delete 324 12 "PRAGMA journal_mode" delete 325 13 "PRAGMA main.journal_mode" delete 326 14 "PRAGMA main.journal_mode = wal" wal 327 15 "PRAGMA journal_mode" wal 328 16 "PRAGMA main.journal_mode" wal 329} { 330 do_test walmode-7.$tn { 331 db close 332 sqlite3 db test.db 333 execsql $sql 334 } $result 335} 336db close 337 338#------------------------------------------------------------------------- 339# Test the effect of a "PRAGMA journal_mode" command on an attached 340# database. 341# 342faultsim_delete_and_reopen 343do_execsql_test walmode-8.1 { 344 CREATE TABLE t1(a, b); 345 PRAGMA journal_mode = WAL; 346 ATTACH 'test.db2' AS two; 347 CREATE TABLE two.t2(a, b); 348} {wal} 349do_execsql_test walmode-8.2 { PRAGMA main.journal_mode } {wal} 350do_execsql_test walmode-8.3 { PRAGMA two.journal_mode } {delete} 351do_execsql_test walmode-8.4 { PRAGMA two.journal_mode = DELETE } {delete} 352 353db close 354sqlite3 db test.db 355do_execsql_test walmode-8.5 { ATTACH 'test.db2' AS two } {} 356do_execsql_test walmode-8.6 { PRAGMA main.journal_mode } {wal} 357do_execsql_test walmode-8.7 { PRAGMA two.journal_mode } {delete} 358do_execsql_test walmode-8.8 { INSERT INTO two.t2 DEFAULT VALUES } {} 359do_execsql_test walmode-8.9 { PRAGMA two.journal_mode } {delete} 360do_execsql_test walmode-8.10 { INSERT INTO t1 DEFAULT VALUES } {} 361do_execsql_test walmode-8.11 { PRAGMA main.journal_mode } {wal} 362do_execsql_test walmode-8.12 { PRAGMA journal_mode } {wal} 363 364# Change to WAL mode on test2.db and make sure (in the tests that follow) 365# that this mode change persists. 366do_test walmode-8.x1 { 367 execsql { 368 PRAGMA two.journal_mode=WAL; 369 PRAGMA two.journal_mode; 370 } 371} {wal wal} 372 373db close 374sqlite3 db test.db 375do_execsql_test walmode-8.13 { PRAGMA journal_mode = WAL } {wal} 376do_execsql_test walmode-8.14 { ATTACH 'test.db2' AS two } {} 377do_execsql_test walmode-8.15 { PRAGMA main.journal_mode } {wal} 378do_execsql_test walmode-8.16 { PRAGMA two.journal_mode } {wal} 379do_execsql_test walmode-8.17 { INSERT INTO two.t2 DEFAULT VALUES } {} 380do_execsql_test walmode-8.18 { PRAGMA two.journal_mode } {wal} 381 382sqlite3 db2 test.db2 383do_test walmode-8.19 { execsql { PRAGMA main.journal_mode } db2 } {wal} 384db2 close 385 386do_execsql_test walmode-8.20 { PRAGMA journal_mode = DELETE } {delete} 387do_execsql_test walmode-8.21 { PRAGMA main.journal_mode } {delete} 388do_execsql_test walmode-8.22 { PRAGMA two.journal_mode } {delete} 389do_execsql_test walmode-8.21 { PRAGMA journal_mode = WAL } {wal} 390do_execsql_test walmode-8.21 { PRAGMA main.journal_mode } {wal} 391do_execsql_test walmode-8.22 { PRAGMA two.journal_mode } {wal} 392 393finish_test 394