3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
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.
17 set testdir [file dirname $argv0]
18 source $testdir/tester.tcl
19 source $testdir/lock_common.tcl
20 source $testdir/malloc_common.tcl
21 source $testdir/wal_common.tcl
24 ifcapable !wal {finish_test ; return }
31 proc xSync {method file args} {
32 if {[file tail $file]=="test.db-wal"} {
38 #-------------------------------------------------------------------------
39 # Test that if IOCAP_SEQUENTIAL is set, the wal-header is not synced to
40 # disk immediately after it is written.
42 sqlite3 db test.db -vfs tvfs
44 PRAGMA auto_vacuum = 0;
45 PRAGMA journal_mode = wal;
46 PRAGMA synchronous = normal;
47 CREATE TABLE t1(a, b, c);
48 INSERT INTO t1 VALUES(1, 2, 3);
49 INSERT INTO t1 VALUES(4, 5, 6);
50 INSERT INTO t1 VALUES(7, 8, 9);
51 PRAGMA wal_checkpoint;
56 execsql { INSERT INTO t1 VALUES(10, 11, 12) }
61 tvfs devchar sequential
62 sqlite3 db test.db -vfs tvfs
64 PRAGMA synchronous = normal;
65 INSERT INTO t1 VALUES(13, 14, 15);
66 INSERT INTO t1 VALUES(16, 17, 18);
67 PRAGMA wal_checkpoint;
72 execsql { INSERT INTO t1 VALUES(10, 11, 12) }
76 #-------------------------------------------------------------------------
77 # Test that "PRAGMA journal_size_limit" works in wal mode.
81 PRAGMA journal_size_limit = 10000;
83 PRAGMA journal_mode = wal;
85 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
87 INSERT INTO t1 SELECT randomblob(750) FROM s;
90 expr [file size test.db-wal]>12000
94 PRAGMA wal_checkpoint;
95 INSERT INTO t1 VALUES(randomblob(750));
101 PRAGMA journal_size_limit = 8000;
102 PRAGMA wal_checkpoint;
103 INSERT INTO t1 VALUES(randomblob(750));
105 file size test.db-wal
108 #-------------------------------------------------------------------------
109 # Test that a checkpoint may be interrupted using sqlite3_interrupt().
110 # And that the error code is SQLITE_NOMEM, not SQLITE_INTERRUPT, if
111 # an OOM error occurs just before the sqlite3_interrupt() call.
115 sqlite3 db test.db -vfs tvfs
118 do_execsql_test 3.0 {
120 PRAGMA journal_mode = wal;
122 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
124 INSERT INTO t1 SELECT randomblob(750) FROM s;
130 proc xWrite {method file args} {
131 if {[file tail $file]=="test.db"} {
140 do_catchsql_test 3.1 {
141 PRAGMA wal_checkpoint
145 proc xWrite {method file args} {
146 if {[file tail $file]=="test.db"} {
149 sqlite3_memdebug_fail 1 -repeat 0
150 # For this test to pass, the following statement must call malloc() at
151 # least once. Even if the lookaside is enabled.
152 set ::xwrite_stmt_res [catchsql { SELECT hex(randomblob(4000)) }]
159 set ::xwrite_stmt_res ""
160 do_catchsql_test 3.2 {
161 PRAGMA wal_checkpoint
162 } {1 {out of memory}}
164 set ::xwrite_stmt_res
165 } {1 {out of memory}}
166 unset ::xwrite_stmt_res
168 #-------------------------------------------------------------------------
173 sqlite3 db test.db -vfs tvfs
176 PRAGMA journal_mode = wal;
178 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
180 INSERT INTO t1 SELECT randomblob(750) FROM s;
187 proc xShmMap {method file args} {
188 return SQLITE_READONLY
190 sqlite3 db test.db -vfs tvfs
191 do_catchsql_test 4.1 {
192 SELECT count(*) FROM t1
193 } {1 {attempt to write a readonly database}}
196 tvfs filter {xShmMap xShmLock}
197 proc xShmMap {method file name args} {
199 xShmMap { return SQLITE_READONLY }
201 if {$args == "{0 1 lock shared}"} {
203 if {$::cnt>0} { return SQLITE_BUSY }
209 do_catchsql_test 4.2 {
210 SELECT count(*) FROM t1
211 } {1 {attempt to write a readonly database}}
213 #-------------------------------------------------------------------------
217 sqlite3 db test.db -vfs tvfs
219 do_execsql_test 5.0 {
220 PRAGMA auto_vacuum = 0;
221 PRAGMA page_size = 1024;
223 PRAGMA journal_mode = wal;
225 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
227 INSERT INTO t1 SELECT randomblob(750) FROM s;
230 do_execsql_test 5.1 {
231 SELECT count(*) FROM t1
235 vfs_set_readmark db main 1 100
236 vfs_set_readmark db main 2 100
237 vfs_set_readmark db main 3 100
238 vfs_set_readmark db main 4 100
241 do_execsql_test 5.3 {
242 SELECT count(*) FROM t1
246 list [vfs_set_readmark db main 1] \
247 [vfs_set_readmark db main 2] \
248 [vfs_set_readmark db main 3] \
249 [vfs_set_readmark db main 4]
255 proc xShmLock {args} {
257 if {$::cnt>0} { return SQLITE_BUSY }
262 vfs_set_readmark db main 1 100
263 execsql { SELECT count(*) FROM t1 }
266 vfs_set_readmark db main 1 100
267 vfs_set_readmark db main 2 100
268 vfs_set_readmark db main 3 100
269 vfs_set_readmark db main 4 100
271 tvfs script xShmMapLock
272 tvfs filter {xShmLock xShmMap}
273 proc xShmMapLock {method args} {
274 if {$method=="xShmMap"} {
275 return "SQLITE_READONLY"
280 sqlite3 db2 test.db -vfs tvfs
283 list [catch { execsql { SELECT count(*) FROM t1 } db2 } msg] $msg
284 } {1 {attempt to write a readonly database}}
287 vfs_set_readmark db main 1 1
290 list [catch { execsql { SELECT count(*) FROM t1 } db2 } msg] $msg
295 #-------------------------------------------------------------------------
296 # Cause an SQLITE_PROTOCOL while attempting to restart the wal file.
301 sqlite3 db test.db -vfs tvfs
302 do_execsql_test 6.0 {
303 PRAGMA auto_vacuum = 0;
304 PRAGMA page_size = 1024;
306 PRAGMA journal_mode = wal;
308 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
310 INSERT INTO t1 SELECT randomblob(750) FROM s;
314 execsql { PRAGMA wal_checkpoint }
321 proc xShmLock {method file handle spec} {
322 if {$::flag && [lrange $spec 2 end]=="lock shared"} {
325 if {$spec=="3 1 unlock shared"} {
331 puts "# WARNING: This next test takes around 12 seconds"
332 do_catchsql_test 6.2 {
333 INSERT INTO t1 VALUES(1);
334 } {1 {locking protocol}}
336 #-------------------------------------------------------------------------
337 # Check that a checkpoint fails if it cannot get the CHECKPOINTER lock
342 sqlite3 db test.db -vfs tvfs
343 do_execsql_test 7.0 {
344 PRAGMA auto_vacuum = 0;
345 PRAGMA page_size = 1024;
347 PRAGMA journal_mode = wal;
349 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
351 INSERT INTO t1 SELECT randomblob(750) FROM s;
356 proc xShmLock {method file handle spec} {
357 if {$spec=="1 1 lock exclusive"} {
363 do_execsql_test 7.1 {
364 PRAGMA wal_checkpoint
367 #-------------------------------------------------------------------------
368 # Check that the page cache is correctly flushed if a checkpointer using
369 # a version 2 VFS makes a checkpoint with an out-of-date cache.
372 testvfs tvfs2 -iversion 2
374 sqlite3 db test.db -vfs tvfs2
375 do_execsql_test 8.0 {
376 PRAGMA auto_vacuum = 0;
377 PRAGMA page_size = 1024;
379 PRAGMA journal_mode = wal;
380 WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20 )
381 INSERT INTO t1 SELECT randomblob(75) FROM s;
384 do_execsql_test 8.1 { SELECT count(*) FROM t1 } {20}
387 sqlite3 db2 test.db -vfs tvfs2
389 INSERT INTO t1 VALUES(randomblob(75));
394 do_execsql_test 8.3 {
395 PRAGMA wal_checkpoint;
396 SELECT count(*) FROM t1
401 #-------------------------------------------------------------------------
404 sqlite3 db test.db -vfs tvfs
405 do_execsql_test 9.0 {
406 PRAGMA auto_vacuum = 0;
407 PRAGMA page_size = 1024;
409 PRAGMA journal_mode = wal;
410 WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20 )
411 INSERT INTO t1 SELECT randomblob(75) FROM s;
414 sqlite3 db2 test.db -vfs tvfs
415 tvfs filter {xShmMap xShmLock}
417 proc xShmMap {method file handle args} {
420 return "SQLITE_READONLY_CANTINIT"
423 if {$args=="{3 1 lock shared}"} {
424 return "SQLITE_IOERR"
431 catchsql { SELECT count(*) FROM t1 } db2
432 } {1 {disk I/O error}}