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.
16 set testdir [file dirname $argv0]
17 source $testdir/tester.tcl
18 source $testdir/lock_common.tcl
19 source $testdir/malloc_common.tcl
20 source $testdir/wal_common.tcl
23 ifcapable !wal {finish_test ; return }
30 proc xSync {method file args} {
31 if {[file tail $file]=="test.db-wal"} {
37 #-------------------------------------------------------------------------
38 # Test that if IOCAP_SEQUENTIAL is set, the wal-header is not synced to
39 # disk immediately after it is written.
41 sqlite3 db test.db -vfs tvfs
43 PRAGMA auto_vacuum = 0;
44 PRAGMA journal_mode = wal;
45 PRAGMA synchronous = normal;
46 CREATE TABLE t1(a, b, c);
47 INSERT INTO t1 VALUES(1, 2, 3);
48 INSERT INTO t1 VALUES(4, 5, 6);
49 INSERT INTO t1 VALUES(7, 8, 9);
50 PRAGMA wal_checkpoint;
55 execsql { INSERT INTO t1 VALUES(10, 11, 12) }
60 tvfs devchar sequential
61 sqlite3 db test.db -vfs tvfs
63 PRAGMA synchronous = normal;
64 INSERT INTO t1 VALUES(13, 14, 15);
65 INSERT INTO t1 VALUES(16, 17, 18);
66 PRAGMA wal_checkpoint;
71 execsql { INSERT INTO t1 VALUES(10, 11, 12) }
75 #-------------------------------------------------------------------------
76 # Test that "PRAGMA journal_size_limit" works in wal mode.
80 PRAGMA journal_size_limit = 10000;
82 PRAGMA journal_mode = wal;
84 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
86 INSERT INTO t1 SELECT randomblob(750) FROM s;
89 expr [file size test.db-wal]>12000
93 PRAGMA wal_checkpoint;
94 INSERT INTO t1 VALUES(randomblob(750));
100 PRAGMA journal_size_limit = 8000;
101 PRAGMA wal_checkpoint;
102 INSERT INTO t1 VALUES(randomblob(750));
104 file size test.db-wal
107 #-------------------------------------------------------------------------
108 # Test that a checkpoint may be interrupted using sqlite3_interrupt().
109 # And that the error code is SQLITE_NOMEM, not SQLITE_INTERRUPT, if
110 # an OOM error occurs just before the sqlite3_interrupt() call.
114 sqlite3 db test.db -vfs tvfs
117 do_execsql_test 3.0 {
119 PRAGMA journal_mode = wal;
121 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
123 INSERT INTO t1 SELECT randomblob(750) FROM s;
129 proc xWrite {method file args} {
130 if {[file tail $file]=="test.db"} {
139 do_catchsql_test 3.1 {
140 PRAGMA wal_checkpoint
144 proc xWrite {method file args} {
145 if {[file tail $file]=="test.db"} {
148 sqlite3_memdebug_fail 1 -repeat 0
149 catchsql { SELECT 'a big long string!' }
156 do_catchsql_test 3.2 {
157 PRAGMA wal_checkpoint
158 } {1 {out of memory}}
160 #-------------------------------------------------------------------------
165 sqlite3 db test.db -vfs tvfs
168 PRAGMA journal_mode = wal;
170 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
172 INSERT INTO t1 SELECT randomblob(750) FROM s;
179 proc xShmMap {method file args} {
180 return SQLITE_READONLY
182 sqlite3 db test.db -vfs tvfs
183 do_catchsql_test 4.1 {
184 SELECT count(*) FROM t1
185 } {1 {attempt to write a readonly database}}
188 tvfs filter {xShmMap xShmLock}
189 proc xShmMap {method file name args} {
191 xShmMap { return SQLITE_READONLY }
193 if {$args == "{0 1 lock shared}"} {
195 if {$::cnt>0} { return SQLITE_BUSY }
201 do_catchsql_test 4.2 {
202 SELECT count(*) FROM t1
203 } {1 {attempt to write a readonly database}}
205 #-------------------------------------------------------------------------
209 sqlite3 db test.db -vfs tvfs
211 do_execsql_test 5.0 {
212 PRAGMA auto_vacuum = 0;
213 PRAGMA page_size = 1024;
215 PRAGMA journal_mode = wal;
217 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
219 INSERT INTO t1 SELECT randomblob(750) FROM s;
222 do_execsql_test 5.1 {
223 SELECT count(*) FROM t1
227 vfs_set_readmark db main 1 100
228 vfs_set_readmark db main 2 100
229 vfs_set_readmark db main 3 100
230 vfs_set_readmark db main 4 100
233 do_execsql_test 5.3 {
234 SELECT count(*) FROM t1
238 list [vfs_set_readmark db main 1] \
239 [vfs_set_readmark db main 2] \
240 [vfs_set_readmark db main 3] \
241 [vfs_set_readmark db main 4]
247 proc xShmLock {args} {
249 if {$::cnt>0} { return SQLITE_BUSY }
254 vfs_set_readmark db main 1 100
255 execsql { SELECT count(*) FROM t1 }
258 vfs_set_readmark db main 1 100
259 vfs_set_readmark db main 2 100
260 vfs_set_readmark db main 3 100
261 vfs_set_readmark db main 4 100
263 tvfs script xShmMapLock
264 tvfs filter {xShmLock xShmMap}
265 proc xShmMapLock {method args} {
266 if {$method=="xShmMap"} {
267 return "SQLITE_READONLY"
272 sqlite3 db2 test.db -vfs tvfs
275 list [catch { execsql { SELECT count(*) FROM t1 } db2 } msg] $msg
276 } {1 {attempt to write a readonly database}}
279 vfs_set_readmark db main 1 1
282 list [catch { execsql { SELECT count(*) FROM t1 } db2 } msg] $msg
287 #-------------------------------------------------------------------------
288 # Cause an SQLITE_PROTOCOL while attempting to restart the wal file.
293 sqlite3 db test.db -vfs tvfs
294 do_execsql_test 6.0 {
295 PRAGMA auto_vacuum = 0;
296 PRAGMA page_size = 1024;
298 PRAGMA journal_mode = wal;
300 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
302 INSERT INTO t1 SELECT randomblob(750) FROM s;
306 execsql { PRAGMA wal_checkpoint }
313 proc xShmLock {method file handle spec} {
314 if {$::flag && [lrange $spec 2 end]=="lock shared"} {
317 if {$spec=="3 1 unlock shared"} {
323 puts "# WARNING: This next test takes around 12 seconds"
324 do_catchsql_test 6.2 {
325 INSERT INTO t1 VALUES(1);
326 } {1 {locking protocol}}
328 #-------------------------------------------------------------------------
329 # Check that a checkpoint fails if it cannot get the CHECKPOINTER lock
334 sqlite3 db test.db -vfs tvfs
335 do_execsql_test 7.0 {
336 PRAGMA auto_vacuum = 0;
337 PRAGMA page_size = 1024;
339 PRAGMA journal_mode = wal;
341 SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20
343 INSERT INTO t1 SELECT randomblob(750) FROM s;
348 proc xShmLock {method file handle spec} {
349 if {$spec=="1 1 lock exclusive"} {
355 do_execsql_test 7.1 {
356 PRAGMA wal_checkpoint
359 #-------------------------------------------------------------------------
360 # Check that the page cache is correctly flushed if a checkpointer using
361 # a version 2 VFS makes a checkpoint with an out-of-date cache.
364 testvfs tvfs2 -iversion 2
366 sqlite3 db test.db -vfs tvfs2
367 do_execsql_test 8.0 {
368 PRAGMA auto_vacuum = 0;
369 PRAGMA page_size = 1024;
371 PRAGMA journal_mode = wal;
372 WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20 )
373 INSERT INTO t1 SELECT randomblob(75) FROM s;
376 do_execsql_test 8.1 { SELECT count(*) FROM t1 } {20}
379 sqlite3 db2 test.db -vfs tvfs2
381 INSERT INTO t1 VALUES(randomblob(75));
386 do_execsql_test 8.3 {
387 PRAGMA wal_checkpoint;
388 SELECT count(*) FROM t1
393 #-------------------------------------------------------------------------
396 sqlite3 db test.db -vfs tvfs
397 do_execsql_test 9.0 {
398 PRAGMA auto_vacuum = 0;
399 PRAGMA page_size = 1024;
401 PRAGMA journal_mode = wal;
402 WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s LIMIT 20 )
403 INSERT INTO t1 SELECT randomblob(75) FROM s;
406 sqlite3 db2 test.db -vfs tvfs
407 tvfs filter {xShmMap xShmLock}
409 proc xShmMap {method file handle args} {
412 return "SQLITE_READONLY_CANTINIT"
415 if {$args=="{3 1 lock shared}"} {
416 return "SQLITE_IOERR"
423 catchsql { SELECT count(*) FROM t1 } db2
424 } {1 {disk I/O error}}