blob: 1667f22f3f0f953af42aae227b6b70c1bdec9c7e [file] [log] [blame]
dand3f8f942010-04-13 11:35:01 +00001# 2010 April 13
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#
dan7c246102010-04-12 19:00:29 +000015
16set testdir [file dirname $argv0]
17source $testdir/tester.tcl
dane264d982010-04-14 18:06:50 +000018source $testdir/lock_common.tcl
dan7c246102010-04-12 19:00:29 +000019
dan5cf53532010-05-01 16:40:20 +000020ifcapable !wal {finish_test ; return }
21
dan7c246102010-04-12 19:00:29 +000022proc reopen_db {} {
danb9bf16b2010-04-14 11:23:30 +000023 catch { db close }
dan31f98fc2010-04-27 05:42:32 +000024 file delete -force test.db test.db-wal test.db-wal-summary
dan7c246102010-04-12 19:00:29 +000025 sqlite3_wal db test.db
dan7c246102010-04-12 19:00:29 +000026}
27
dan67032392010-04-17 15:42:43 +000028set ::blobcnt 0
29proc blob {nByte} {
30 incr ::blobcnt
31 return [string range [string repeat "${::blobcnt}x" $nByte] 1 $nByte]
32}
33
dan7c246102010-04-12 19:00:29 +000034proc sqlite3_wal {args} {
35 eval sqlite3 $args
dane04dc882010-04-20 18:53:15 +000036 [lindex $args 0] eval { PRAGMA page_size = 1024 }
dan7c246102010-04-12 19:00:29 +000037 [lindex $args 0] eval { PRAGMA journal_mode = wal }
dan67032392010-04-17 15:42:43 +000038 [lindex $args 0] eval { PRAGMA synchronous = normal }
39 [lindex $args 0] function blob blob
dan7c246102010-04-12 19:00:29 +000040}
41
dan97a31352010-04-16 13:59:31 +000042proc log_file_size {nFrame pgsz} {
43 expr {12 + ($pgsz+16)*$nFrame}
44}
45
dan3de777f2010-04-17 12:31:37 +000046proc log_deleted {logfile} {
47 return [expr [file exists $logfile]==0]
48}
49
dan7c246102010-04-12 19:00:29 +000050#
51# These are 'warm-body' tests used while developing the WAL code. They
52# serve to prove that a few really simple cases work:
53#
54# wal-1.*: Read and write the database.
55# wal-2.*: Test MVCC with one reader, one writer.
56# wal-3.*: Test transaction rollback.
57# wal-4.*: Test savepoint/statement rollback.
58# wal-5.*: Test the temp database.
59# wal-6.*: Test creating databases with different page sizes.
60#
61
62do_test wal-0.1 {
dan67032392010-04-17 15:42:43 +000063 execsql { PRAGMA synchronous = normal }
dan7c246102010-04-12 19:00:29 +000064 execsql { PRAGMA journal_mode = wal }
65} {wal}
dane04dc882010-04-20 18:53:15 +000066do_test wal-0.2 {
67 file size test.db
68} {1024}
dan7c246102010-04-12 19:00:29 +000069
70do_test wal-1.0 {
71 execsql {
72 BEGIN;
73 CREATE TABLE t1(a, b);
74 }
dane04dc882010-04-20 18:53:15 +000075 list [file exists test.db-journal] \
76 [file exists test.db-wal] \
77 [file size test.db]
78} {0 1 1024}
dan7c246102010-04-12 19:00:29 +000079do_test wal-1.1 {
80 execsql COMMIT
81 list [file exists test.db-journal] [file exists test.db-wal]
82} {0 1}
83do_test wal-1.2 {
84 # There are now two pages in the log.
85 file size test.db-wal
dan97a31352010-04-16 13:59:31 +000086} [log_file_size 2 1024]
dan7c246102010-04-12 19:00:29 +000087
88do_test wal-1.3 {
89 execsql { SELECT * FROM sqlite_master }
90} {table t1 t1 2 {CREATE TABLE t1(a, b)}}
91
92do_test wal-1.4 {
93 execsql { INSERT INTO t1 VALUES(1, 2) }
94 execsql { INSERT INTO t1 VALUES(3, 4) }
95 execsql { INSERT INTO t1 VALUES(5, 6) }
96 execsql { INSERT INTO t1 VALUES(7, 8) }
97 execsql { INSERT INTO t1 VALUES(9, 10) }
98} {}
99
100do_test wal-1.5 {
101 execsql { SELECT * FROM t1 }
102} {1 2 3 4 5 6 7 8 9 10}
103
104do_test wal-2.1 {
105 sqlite3_wal db2 ./test.db
106 execsql { BEGIN; SELECT * FROM t1 } db2
107} {1 2 3 4 5 6 7 8 9 10}
108
109do_test wal-2.2 {
110 execsql { INSERT INTO t1 VALUES(11, 12) }
111 execsql { SELECT * FROM t1 }
112} {1 2 3 4 5 6 7 8 9 10 11 12}
113
114do_test wal-2.3 {
115 execsql { SELECT * FROM t1 } db2
116} {1 2 3 4 5 6 7 8 9 10}
117
118do_test wal-2.4 {
119 execsql { INSERT INTO t1 VALUES(13, 14) }
120 execsql { SELECT * FROM t1 }
121} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
122
123do_test wal-2.5 {
124 execsql { SELECT * FROM t1 } db2
125} {1 2 3 4 5 6 7 8 9 10}
126
127do_test wal-2.6 {
128 execsql { COMMIT; SELECT * FROM t1 } db2
129} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
130
131do_test wal-3.1 {
132 execsql { BEGIN; DELETE FROM t1 }
133 execsql { SELECT * FROM t1 }
134} {}
135do_test wal-3.2 {
136 execsql { SELECT * FROM t1 } db2
137} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
138do_test wal-3.3 {
139 execsql { ROLLBACK }
140 execsql { SELECT * FROM t1 }
141} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
142db2 close
143
dan74d6cd82010-04-24 18:44:05 +0000144#-------------------------------------------------------------------------
145# The following tests, wal-4.*, test that savepoints work with WAL
146# databases.
147#
dan7c246102010-04-12 19:00:29 +0000148do_test wal-4.1 {
149 execsql {
150 DELETE FROM t1;
151 BEGIN;
152 INSERT INTO t1 VALUES('a', 'b');
153 SAVEPOINT sp;
154 INSERT INTO t1 VALUES('c', 'd');
155 SELECT * FROM t1;
156 }
157} {a b c d}
158do_test wal-4.2 {
159 execsql {
160 ROLLBACK TO sp;
161 SELECT * FROM t1;
162 }
163} {a b}
164do_test wal-4.3 {
165 execsql {
166 COMMIT;
167 SELECT * FROM t1;
168 }
169} {a b}
170
dan4cd78b42010-04-26 16:57:10 +0000171do_test wal-4.4.1 {
dan74d6cd82010-04-24 18:44:05 +0000172 db close
173 sqlite3 db test.db
174 db func blob blob
175 list [execsql { SELECT * FROM t1 }] [file size test.db-wal]
176} {{a b} 0}
dan4cd78b42010-04-26 16:57:10 +0000177do_test wal-4.4.2 {
dan74d6cd82010-04-24 18:44:05 +0000178 execsql { PRAGMA cache_size = 10 }
179 execsql {
180 CREATE TABLE t2(a, b);
181 INSERT INTO t2 VALUES(blob(400), blob(400));
182 SAVEPOINT tr;
183 INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 2 */
184 INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 4 */
185 INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 8 */
186 INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 16 */
187 INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 32 */
188 INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 2 */
189 INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 4 */
190 INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 8 */
191 INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 16 */
192 INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 32 */
193 SELECT count(*) FROM t2;
194 }
195} {32}
dan4cd78b42010-04-26 16:57:10 +0000196do_test wal-4.4.3 {
dan74d6cd82010-04-24 18:44:05 +0000197 execsql { ROLLBACK TO tr }
198} {}
dan4cd78b42010-04-26 16:57:10 +0000199do_test wal-4.4.4 {
dan74d6cd82010-04-24 18:44:05 +0000200 set logsize [file size test.db-wal]
201 execsql {
202 INSERT INTO t1 VALUES('x', 'y');
203 RELEASE tr;
204 }
205 expr { $logsize == [file size test.db-wal] }
206} {1}
dan4cd78b42010-04-26 16:57:10 +0000207do_test wal-4.4.5 {
dan74d6cd82010-04-24 18:44:05 +0000208 execsql { SELECT count(*) FROM t2 }
209} {1}
dan4cd78b42010-04-26 16:57:10 +0000210do_test wal-4.4.6 {
dan74d6cd82010-04-24 18:44:05 +0000211 file copy -force test.db test2.db
212 file copy -force test.db-wal test2.db-wal
213 sqlite3 db2 test2.db
214 execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
215} {1 2}
dan4cd78b42010-04-26 16:57:10 +0000216do_test wal-4.4.7 {
dan74d6cd82010-04-24 18:44:05 +0000217 execsql { PRAGMA integrity_check } db2
218} {ok}
219db2 close
220
dan4cd78b42010-04-26 16:57:10 +0000221do_test wal-4.5.1 {
222 reopen_db
223 db func blob blob
224 execsql {
225 PRAGMA journal_mode = WAL;
226 CREATE TABLE t1(a, b);
227 INSERT INTO t1 VALUES('a', 'b');
228 }
229 sqlite3 db test.db
230 db func blob blob
231 list [execsql { SELECT * FROM t1 }] [file size test.db-wal]
232} {{a b} 0}
233do_test wal-4.5.2 {
234 execsql { PRAGMA cache_size = 10 }
235 execsql {
236 CREATE TABLE t2(a, b);
237 BEGIN;
238 INSERT INTO t2 VALUES(blob(400), blob(400));
239 SAVEPOINT tr;
240 INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 2 */
241 INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 4 */
242 INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 8 */
243 INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 16 */
244 INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 32 */
245 INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 2 */
246 INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 4 */
247 INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 8 */
248 INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 16 */
249 INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 32 */
250 SELECT count(*) FROM t2;
251 }
252} {32}
253do_test wal-4.5.3 {
dan4cd78b42010-04-26 16:57:10 +0000254 execsql { ROLLBACK TO tr }
255} {}
256do_test wal-4.5.4 {
257 set logsize [file size test.db-wal]
dan4cd78b42010-04-26 16:57:10 +0000258 execsql {
259 INSERT INTO t1 VALUES('x', 'y');
260 RELEASE tr;
261 COMMIT;
262 }
263 expr { $logsize == [file size test.db-wal] }
264} {1}
265do_test wal-4.5.5 {
266 execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 }
267} {1 2}
268do_test wal-4.5.6 {
269 file copy -force test.db test2.db
270 file copy -force test.db-wal test2.db-wal
271 sqlite3 db2 test2.db
dan4cd78b42010-04-26 16:57:10 +0000272 execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
273} {1 2}
274do_test wal-4.5.7 {
275 execsql { PRAGMA integrity_check } db2
276} {ok}
277db2 close
278
279
dan74d6cd82010-04-24 18:44:05 +0000280reopen_db
dan7c246102010-04-12 19:00:29 +0000281do_test wal-5.1 {
282 execsql {
283 CREATE TEMP TABLE t2(a, b);
284 INSERT INTO t2 VALUES(1, 2);
285 }
286} {}
287do_test wal-5.2 {
288 execsql {
289 BEGIN;
290 INSERT INTO t2 VALUES(3, 4);
291 SELECT * FROM t2;
292 }
293} {1 2 3 4}
294do_test wal-5.3 {
295 execsql {
296 ROLLBACK;
297 SELECT * FROM t2;
298 }
299} {1 2}
300do_test wal-5.4 {
301 execsql {
302 CREATE TEMP TABLE t3(x UNIQUE);
303 BEGIN;
304 INSERT INTO t2 VALUES(3, 4);
305 INSERT INTO t3 VALUES('abc');
306 }
307 catchsql { INSERT INTO t3 VALUES('abc') }
308} {1 {column x is not unique}}
309do_test wal-5.5 {
310 execsql {
311 COMMIT;
312 SELECT * FROM t2;
313 }
314} {1 2 3 4}
315db close
316
dan7c246102010-04-12 19:00:29 +0000317foreach sector {512 4096} {
318 sqlite3_simulate_device -sectorsize $sector
319 foreach pgsz {512 1024 2048 4096} {
320 file delete -force test.db test.db-wal
321 do_test wal-6.$sector.$pgsz.1 {
dane04dc882010-04-20 18:53:15 +0000322 sqlite3 db test.db -vfs devsym
dan7c246102010-04-12 19:00:29 +0000323 execsql "
dane04dc882010-04-20 18:53:15 +0000324 PRAGMA page_size = $pgsz;
325 PRAGMA journal_mode = wal;
dan7c246102010-04-12 19:00:29 +0000326 "
327 execsql "
328 CREATE TABLE t1(a, b);
329 INSERT INTO t1 VALUES(1, 2);
330 "
331 db close
332 file size test.db
333 } [expr $pgsz*2]
334
335 do_test wal-6.$sector.$pgsz.2 {
dan3de777f2010-04-17 12:31:37 +0000336 log_deleted test.db-wal
337 } {1}
dan7c246102010-04-12 19:00:29 +0000338 }
339}
340
341do_test wal-7.1 {
342 file delete -force test.db test.db-wal
343 sqlite3_wal db test.db
344 execsql {
345 PRAGMA page_size = 1024;
346 CREATE TABLE t1(a, b);
347 INSERT INTO t1 VALUES(1, 2);
348 }
dan7c246102010-04-12 19:00:29 +0000349 list [file size test.db] [file size test.db-wal]
dane04dc882010-04-20 18:53:15 +0000350} [list 1024 [log_file_size 3 1024]]
dan7c246102010-04-12 19:00:29 +0000351do_test wal-7.2 {
dan5a299f92010-05-03 11:05:08 +0000352 execsql { PRAGMA wal_checkpoint }
dan7c246102010-04-12 19:00:29 +0000353 list [file size test.db] [file size test.db-wal]
dan97a31352010-04-16 13:59:31 +0000354} [list 2048 [log_file_size 3 1024]]
dan7c246102010-04-12 19:00:29 +0000355
dan7c246102010-04-12 19:00:29 +0000356# Execute some transactions in auto-vacuum mode to test database file
357# truncation.
358#
danb9bf16b2010-04-14 11:23:30 +0000359do_test wal-8.1 {
dan7c246102010-04-12 19:00:29 +0000360 reopen_db
dane04dc882010-04-20 18:53:15 +0000361 catch { db close }
362 file delete -force test.db test.db-wal
363
364 sqlite3 db test.db
365 db function blob blob
dan7c246102010-04-12 19:00:29 +0000366 execsql {
367 PRAGMA auto_vacuum = 1;
dane04dc882010-04-20 18:53:15 +0000368 PRAGMA journal_mode = wal;
dan7c246102010-04-12 19:00:29 +0000369 PRAGMA auto_vacuum;
370 }
dane04dc882010-04-20 18:53:15 +0000371} {wal 1}
danb9bf16b2010-04-14 11:23:30 +0000372do_test wal-8.2 {
dan7c246102010-04-12 19:00:29 +0000373 execsql {
374 PRAGMA page_size = 1024;
375 CREATE TABLE t1(x);
dan67032392010-04-17 15:42:43 +0000376 INSERT INTO t1 VALUES(blob(900));
377 INSERT INTO t1 VALUES(blob(900));
378 INSERT INTO t1 SELECT blob(900) FROM t1; /* 4 */
379 INSERT INTO t1 SELECT blob(900) FROM t1; /* 8 */
380 INSERT INTO t1 SELECT blob(900) FROM t1; /* 16 */
381 INSERT INTO t1 SELECT blob(900) FROM t1; /* 32 */
382 INSERT INTO t1 SELECT blob(900) FROM t1; /* 64 */
dan5a299f92010-05-03 11:05:08 +0000383 PRAGMA wal_checkpoint;
dan7c246102010-04-12 19:00:29 +0000384 }
385 file size test.db
dan80a15262010-04-13 11:45:31 +0000386} [expr 68*1024]
danb9bf16b2010-04-14 11:23:30 +0000387do_test wal-8.3 {
dan7c246102010-04-12 19:00:29 +0000388 execsql {
389 DELETE FROM t1 WHERE rowid<54;
dan5a299f92010-05-03 11:05:08 +0000390 PRAGMA wal_checkpoint;
dan7c246102010-04-12 19:00:29 +0000391 }
392 file size test.db
393} [expr 14*1024]
394
395# Run some "warm-body" tests to ensure that log-summary files with more
396# than 256 entries (log summaries that contain index blocks) work Ok.
397#
danb9bf16b2010-04-14 11:23:30 +0000398do_test wal-9.1 {
dan7c246102010-04-12 19:00:29 +0000399 reopen_db
400 execsql {
dan7c246102010-04-12 19:00:29 +0000401 CREATE TABLE t1(x PRIMARY KEY);
dan67032392010-04-17 15:42:43 +0000402 INSERT INTO t1 VALUES(blob(900));
403 INSERT INTO t1 VALUES(blob(900));
404 INSERT INTO t1 SELECT blob(900) FROM t1; /* 4 */
405 INSERT INTO t1 SELECT blob(900) FROM t1; /* 8 */
406 INSERT INTO t1 SELECT blob(900) FROM t1; /* 16 */
407 INSERT INTO t1 SELECT blob(900) FROM t1; /* 32 */
408 INSERT INTO t1 SELECT blob(900) FROM t1; /* 64 */
409 INSERT INTO t1 SELECT blob(900) FROM t1; /* 128 */
410 INSERT INTO t1 SELECT blob(900) FROM t1; /* 256 */
dan7c246102010-04-12 19:00:29 +0000411 }
412 file size test.db
dane04dc882010-04-20 18:53:15 +0000413} 1024
danb9bf16b2010-04-14 11:23:30 +0000414do_test wal-9.2 {
dan7c246102010-04-12 19:00:29 +0000415 sqlite3_wal db2 test.db
416 execsql {PRAGMA integrity_check } db2
417} {ok}
418
danb9bf16b2010-04-14 11:23:30 +0000419do_test wal-9.3 {
dan7c246102010-04-12 19:00:29 +0000420 file delete -force test2.db test2.db-wal
421 file copy test.db test2.db
422 file copy test.db-wal test2.db-wal
423 sqlite3_wal db3 test2.db
424 execsql {PRAGMA integrity_check } db3
425} {ok}
426db3 close
427
danb9bf16b2010-04-14 11:23:30 +0000428do_test wal-9.4 {
dan5a299f92010-05-03 11:05:08 +0000429 execsql { PRAGMA wal_checkpoint }
dan7c246102010-04-12 19:00:29 +0000430 db2 close
431 sqlite3_wal db2 test.db
432 execsql {PRAGMA integrity_check } db2
433} {ok}
434
dan80a15262010-04-13 11:45:31 +0000435foreach handle {db db2 db3} { catch { $handle close } }
436unset handle
437
danb9bf16b2010-04-14 11:23:30 +0000438#-------------------------------------------------------------------------
439# The following block of tests - wal-10.* - test that the WAL locking
dane264d982010-04-14 18:06:50 +0000440# scheme works in simple cases. This block of tests is run twice. Once
441# using multiple connections in the address space of the current process,
442# and once with all connections except one running in external processes.
danb9bf16b2010-04-14 11:23:30 +0000443#
dane264d982010-04-14 18:06:50 +0000444foreach code [list {
445 set ::code2_chan [launch_testfixture]
446 set ::code3_chan [launch_testfixture]
447 proc code2 {tcl} { testfixture $::code2_chan $tcl }
448 proc code3 {tcl} { testfixture $::code3_chan $tcl }
449 set tn 1
450} {
451 proc code2 {tcl} { uplevel #0 $tcl }
452 proc code3 {tcl} { uplevel #0 $tcl }
453 set tn 2
454}] {
danb9bf16b2010-04-14 11:23:30 +0000455
dane264d982010-04-14 18:06:50 +0000456 eval $code
457 reopen_db
458
459 # Open connections [db2] and [db3]. Depending on which iteration this
460 # is, the connections may be created in this interpreter, or in
461 # interpreters running in other OS processes. As such, the [db2] and [db3]
462 # commands should only be accessed within [code2] and [code3] blocks,
463 # respectively.
464 #
465 code2 { sqlite3 db2 test.db ; db2 eval { PRAGMA journal_mode = WAL } }
466 code3 { sqlite3 db3 test.db ; db3 eval { PRAGMA journal_mode = WAL } }
467
468 # Shorthand commands. Execute SQL using database connection [db2] or
469 # [db3]. Return the results.
470 #
471 proc sql2 {sql} { code2 [list db2 eval $sql] }
472 proc sql3 {sql} { code3 [list db3 eval $sql] }
473
474 # Initialize the database schema and contents.
475 #
476 do_test wal-10.$tn.1 {
477 execsql {
478 CREATE TABLE t1(a, b);
479 INSERT INTO t1 VALUES(1, 2);
danb9bf16b2010-04-14 11:23:30 +0000480 SELECT * FROM t1;
dane264d982010-04-14 18:06:50 +0000481 }
482 } {1 2}
danb9bf16b2010-04-14 11:23:30 +0000483
dane264d982010-04-14 18:06:50 +0000484 # Open a transaction and write to the database using [db]. Check that [db2]
485 # is still able to read the snapshot before the transaction was opened.
486 #
487 do_test wal-10.$tn.2 {
488 execsql { BEGIN; INSERT INTO t1 VALUES(3, 4); }
489 sql2 {SELECT * FROM t1}
490 } {1 2}
491
492 # Have [db] commit the transaction. Check that [db2] is now seeing the
493 # new, updated snapshot.
494 #
495 do_test wal-10.$tn.3 {
496 execsql { COMMIT }
497 sql2 {SELECT * FROM t1}
498 } {1 2 3 4}
499
500 # Have [db2] open a read transaction. Then write to the db via [db]. Check
501 # that [db2] is still seeing the original snapshot. Then read with [db3].
502 # [db3] should see the newly committed data.
503 #
504 do_test wal-10.$tn.4 {
505 sql2 { BEGIN ; SELECT * FROM t1}
506 } {1 2 3 4}
507 do_test wal-10.$tn.5 {
508 execsql { INSERT INTO t1 VALUES(5, 6); }
509 sql2 {SELECT * FROM t1}
510 } {1 2 3 4}
511 do_test wal-10.$tn.6 {
512 sql3 {SELECT * FROM t1}
513 } {1 2 3 4 5 6}
514 do_test wal-10.$tn.7 {
515 sql2 COMMIT
516 } {}
517
518 # Have [db2] open a write transaction. Then attempt to write to the
519 # database via [db]. This should fail (writer lock cannot be obtained).
520 #
521 # Then open a read-transaction with [db]. Commit the [db2] transaction
522 # to disk. Verify that [db] still cannot write to the database (because
523 # it is reading an old snapshot).
524 #
525 # Close the current [db] transaction. Open a new one. [db] can now write
526 # to the database (as it is not locked and [db] is reading the latest
527 # snapshot).
528 #
529 do_test wal-10.$tn.7 {
530 sql2 { BEGIN; INSERT INTO t1 VALUES(7, 8) ; }
531 catchsql { INSERT INTO t1 VALUES(9, 10) }
532 } {1 {database is locked}}
533 do_test wal-10.$tn.8 {
534 execsql { BEGIN ; SELECT * FROM t1 }
535 } {1 2 3 4 5 6}
536 do_test wal-10.$tn.9 {
537 sql2 COMMIT
538 catchsql { INSERT INTO t1 VALUES(9, 10) }
539 } {1 {database is locked}}
540 do_test wal-10.$tn.10 {
541 execsql { COMMIT; BEGIN; INSERT INTO t1 VALUES(9, 10); COMMIT; }
542 execsql { SELECT * FROM t1 }
543 } {1 2 3 4 5 6 7 8 9 10}
544
545 # Open a read transaction with [db2]. Check that this prevents [db] from
546 # checkpointing the database. But not from writing to it.
547 #
548 do_test wal-10.$tn.11 {
549 sql2 { BEGIN; SELECT * FROM t1 }
550 } {1 2 3 4 5 6 7 8 9 10}
551 do_test wal-10.$tn.12 {
dan5a299f92010-05-03 11:05:08 +0000552 catchsql { PRAGMA wal_checkpoint }
dane264d982010-04-14 18:06:50 +0000553 } {1 {database is locked}}
554 do_test wal-10.$tn.13 {
555 execsql { INSERT INTO t1 VALUES(11, 12) }
556 sql2 {SELECT * FROM t1}
557 } {1 2 3 4 5 6 7 8 9 10}
558
559 # Connection [db2] is holding a lock on a snapshot, preventing [db] from
560 # checkpointing the database. Add a busy-handler to [db]. If [db2] completes
561 # its transaction from within the busy-handler, [db] is able to complete
562 # the checkpoint operation.
563 #
564 proc busyhandler x {
565 if {$x==4} { sql2 COMMIT }
566 if {$x<5} { return 0 }
567 return 1
danb9bf16b2010-04-14 11:23:30 +0000568 }
dane264d982010-04-14 18:06:50 +0000569 db busy busyhandler
570 do_test wal-10.$tn.14 {
dan5a299f92010-05-03 11:05:08 +0000571 execsql { PRAGMA wal_checkpoint }
dane264d982010-04-14 18:06:50 +0000572 } {}
danb9bf16b2010-04-14 11:23:30 +0000573
dane264d982010-04-14 18:06:50 +0000574 # Similar to the test above. Except this time, a new read transaction is
575 # started (db3) while the checkpointer is waiting for an old one (db2) to
576 # finish. The checkpointer can finish, but any subsequent write operations
577 # must wait until after db3 has closed the read transaction, as db3 is a
578 # "region D" writer.
579 #
580 db busy {}
581 do_test wal-10.$tn.15 {
582 sql2 { BEGIN; SELECT * FROM t1; }
583 } {1 2 3 4 5 6 7 8 9 10 11 12}
584 do_test wal-10.$tn.16 {
dan5a299f92010-05-03 11:05:08 +0000585 catchsql { PRAGMA wal_checkpoint }
dane264d982010-04-14 18:06:50 +0000586 } {1 {database is locked}}
587 proc busyhandler x {
588 if {$x==3} { sql3 { BEGIN; SELECT * FROM t1 } }
589 if {$x==4} { sql2 COMMIT }
590 if {$x<5} { return 0 }
591 return 1
592 }
593 db busy busyhandler
dan49320f82010-04-14 18:50:08 +0000594 do_test wal-10.$tn.17 {
dan5a299f92010-05-03 11:05:08 +0000595 execsql { PRAGMA wal_checkpoint }
dane264d982010-04-14 18:06:50 +0000596 } {}
dan49320f82010-04-14 18:50:08 +0000597 do_test wal-10.$tn.18 {
dane264d982010-04-14 18:06:50 +0000598 sql3 { SELECT * FROM t1 }
599 } {1 2 3 4 5 6 7 8 9 10 11 12}
dan49320f82010-04-14 18:50:08 +0000600 do_test wal-10.$tn.19 {
dane264d982010-04-14 18:06:50 +0000601 catchsql { INSERT INTO t1 VALUES(13, 14) }
602 } {1 {database is locked}}
dan49320f82010-04-14 18:50:08 +0000603 do_test wal-10.$tn.20 {
dane264d982010-04-14 18:06:50 +0000604 execsql { SELECT * FROM t1 }
605 } {1 2 3 4 5 6 7 8 9 10 11 12}
dan49320f82010-04-14 18:50:08 +0000606 do_test wal-10.$tn.21 {
dane264d982010-04-14 18:06:50 +0000607 sql3 COMMIT
608 } {}
dan49320f82010-04-14 18:50:08 +0000609 do_test wal-10.$tn.22 {
dane264d982010-04-14 18:06:50 +0000610 execsql { INSERT INTO t1 VALUES(13, 14) }
611 execsql { SELECT * FROM t1 }
612 } {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
danb9bf16b2010-04-14 11:23:30 +0000613
dan49320f82010-04-14 18:50:08 +0000614 # Set [db3] up as a "region D" reader again. Then upgrade it to a writer
615 # and back down to a reader. Then, check that a checkpoint is not possible
616 # (as [db3] still has a snapshot locked).
617 #
618 do_test wal-10.$tn.23 {
dan5a299f92010-05-03 11:05:08 +0000619 execsql { PRAGMA wal_checkpoint }
dan49320f82010-04-14 18:50:08 +0000620 } {}
621 do_test wal-10.$tn.24 {
622 sql2 { BEGIN; SELECT * FROM t1; }
623 } {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
624 do_test wal-10.$tn.25 {
dan5a299f92010-05-03 11:05:08 +0000625 execsql { PRAGMA wal_checkpoint }
dan49320f82010-04-14 18:50:08 +0000626 } {}
627 do_test wal-10.$tn.26 {
628 catchsql { INSERT INTO t1 VALUES(15, 16) }
629 } {1 {database is locked}}
630 do_test wal-10.$tn.27 {
631 sql3 { INSERT INTO t1 VALUES(15, 16) }
632 } {}
633 do_test wal-10.$tn.28 {
634 code3 {
635 set ::STMT [sqlite3_prepare db3 "SELECT * FROM t1" -1 TAIL]
636 sqlite3_step $::STMT
637 }
638 sql3 COMMIT
639 execsql { SELECT * FROM t1 }
640 } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
641 db busy {}
642 do_test wal-10.$tn.29 {
643 execsql { INSERT INTO t1 VALUES(17, 18) }
dan5a299f92010-05-03 11:05:08 +0000644 catchsql { PRAGMA wal_checkpoint }
dan49320f82010-04-14 18:50:08 +0000645 } {1 {database is locked}}
646 do_test wal-10.$tn.30 {
647 code3 { sqlite3_finalize $::STMT }
dan5a299f92010-05-03 11:05:08 +0000648 execsql { PRAGMA wal_checkpoint }
dan49320f82010-04-14 18:50:08 +0000649 } {}
650
651 # At one point, if a reader failed to upgrade to a writer because it
652 # was reading an old snapshot, the write-locks were not being released.
653 # Test that this bug has been fixed.
654 #
655 do_test wal-10.$tn.31 {
656 execsql { BEGIN ; SELECT * FROM t1 }
657 sql2 { INSERT INTO t1 VALUES(19, 20) }
658 catchsql { INSERT INTO t1 VALUES(21, 22) }
659 } {1 {database is locked}}
660 do_test wal-10.$tn.32 {
661 # This statement would fail when the bug was present.
662 sql2 { INSERT INTO t1 VALUES(21, 22) }
663 } {}
664 do_test wal-10.$tn.33 {
665 execsql { SELECT * FROM t1 ; COMMIT }
666 } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18}
667 do_test wal-10.$tn.34 {
668 execsql { SELECT * FROM t1 }
669 } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22}
670
dan8b348af2010-04-27 18:43:16 +0000671 # Test that if a checkpointer cannot obtain the required locks, it
672 # releases all locks before returning a busy error.
673 #
674 do_test wal-10.$tn.35 {
675 execsql {
676 DELETE FROM t1;
677 INSERT INTO t1 VALUES('a', 'b');
678 INSERT INTO t1 VALUES('c', 'd');
679 }
680 sql2 {
681 BEGIN;
682 SELECT * FROM t1;
683 }
684 } {a b c d}
685 proc busyhandler x { return 1 }
686 db busy busyhandler
687 do_test wal-10.$tn.36 {
dan5a299f92010-05-03 11:05:08 +0000688 catchsql { PRAGMA wal_checkpoint }
dan8b348af2010-04-27 18:43:16 +0000689 } {1 {database is locked}}
690 do_test wal-10.$tn.36 {
691 sql3 { INSERT INTO t1 VALUES('e', 'f') }
692 sql2 { SELECT * FROM t1 }
693 } {a b c d}
694 do_test wal-10.$tn.37 {
695 sql2 COMMIT
dan5a299f92010-05-03 11:05:08 +0000696 execsql { PRAGMA wal_checkpoint }
dan8b348af2010-04-27 18:43:16 +0000697 } {}
698
dane264d982010-04-14 18:06:50 +0000699 catch { db close }
700 catch { code2 { db2 close } }
701 catch { code3 { db3 close } }
702 catch { close $::code2_chan }
703 catch { close $::code3_chan }
704}
705
dan4cc6fb62010-04-15 16:45:34 +0000706#-------------------------------------------------------------------------
707# This block of tests, wal-11.*, test that nothing goes terribly wrong
708# if frames must be written to the log file before a transaction is
709# committed (in order to free up memory).
710#
711do_test wal-11.1 {
712 reopen_db
713 execsql {
714 PRAGMA cache_size = 10;
715 PRAGMA page_size = 1024;
716 CREATE TABLE t1(x PRIMARY KEY);
717 }
718 list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
dane04dc882010-04-20 18:53:15 +0000719} {1 3}
dan4cc6fb62010-04-15 16:45:34 +0000720do_test wal-11.2 {
dan5a299f92010-05-03 11:05:08 +0000721 execsql { PRAGMA wal_checkpoint }
dan97a31352010-04-16 13:59:31 +0000722 list [expr [file size test.db]/1024] [file size test.db-wal]
723} [list 3 [log_file_size 3 1024]]
dan4cc6fb62010-04-15 16:45:34 +0000724do_test wal-11.3 {
dan67032392010-04-17 15:42:43 +0000725 execsql { INSERT INTO t1 VALUES( blob(900) ) }
dan97a31352010-04-16 13:59:31 +0000726 list [expr [file size test.db]/1024] [file size test.db-wal]
727} [list 3 [log_file_size 4 1024]]
dan4cc6fb62010-04-15 16:45:34 +0000728
729do_test wal-11.4 {
730 execsql {
731 BEGIN;
dan67032392010-04-17 15:42:43 +0000732 INSERT INTO t1 SELECT blob(900) FROM t1; -- 2
733 INSERT INTO t1 SELECT blob(900) FROM t1; -- 4
734 INSERT INTO t1 SELECT blob(900) FROM t1; -- 8
735 INSERT INTO t1 SELECT blob(900) FROM t1; -- 16
dan4cc6fb62010-04-15 16:45:34 +0000736 }
dan97a31352010-04-16 13:59:31 +0000737 list [expr [file size test.db]/1024] [file size test.db-wal]
dan67032392010-04-17 15:42:43 +0000738} [list 3 [log_file_size 32 1024]]
dan4cc6fb62010-04-15 16:45:34 +0000739do_test wal-11.5 {
740 execsql {
741 SELECT count(*) FROM t1;
742 PRAGMA integrity_check;
743 }
744} {16 ok}
745do_test wal-11.6 {
746 execsql COMMIT
dan97a31352010-04-16 13:59:31 +0000747 list [expr [file size test.db]/1024] [file size test.db-wal]
dan67032392010-04-17 15:42:43 +0000748} [list 3 [log_file_size 41 1024]]
dan4cc6fb62010-04-15 16:45:34 +0000749do_test wal-11.7 {
750 execsql {
751 SELECT count(*) FROM t1;
752 PRAGMA integrity_check;
753 }
754} {16 ok}
755do_test wal-11.8 {
dan5a299f92010-05-03 11:05:08 +0000756 execsql { PRAGMA wal_checkpoint }
dan97a31352010-04-16 13:59:31 +0000757 list [expr [file size test.db]/1024] [file size test.db-wal]
dan67032392010-04-17 15:42:43 +0000758} [list 37 [log_file_size 41 1024]]
dan4cc6fb62010-04-15 16:45:34 +0000759do_test wal-11.9 {
760 db close
dan3de777f2010-04-17 12:31:37 +0000761 list [expr [file size test.db]/1024] [log_deleted test.db-wal]
762} {37 1}
dan67032392010-04-17 15:42:43 +0000763sqlite3_wal db test.db
dan4cc6fb62010-04-15 16:45:34 +0000764do_test wal-11.10 {
765 execsql {
766 PRAGMA cache_size = 10;
767 BEGIN;
dan67032392010-04-17 15:42:43 +0000768 INSERT INTO t1 SELECT blob(900) FROM t1; -- 32
dan4cc6fb62010-04-15 16:45:34 +0000769 SELECT count(*) FROM t1;
770 }
dan97a31352010-04-16 13:59:31 +0000771 list [expr [file size test.db]/1024] [file size test.db-wal]
dan4cd78b42010-04-26 16:57:10 +0000772} [list 37 [log_file_size 37 1024]]
dan4cc6fb62010-04-15 16:45:34 +0000773do_test wal-11.11 {
774 execsql {
775 SELECT count(*) FROM t1;
776 ROLLBACK;
777 SELECT count(*) FROM t1;
778 }
779} {32 16}
780do_test wal-11.12 {
dan97a31352010-04-16 13:59:31 +0000781 list [expr [file size test.db]/1024] [file size test.db-wal]
dan4cd78b42010-04-26 16:57:10 +0000782} [list 37 [log_file_size 37 1024]]
dan4cc6fb62010-04-15 16:45:34 +0000783do_test wal-11.13 {
784 execsql {
dan67032392010-04-17 15:42:43 +0000785 INSERT INTO t1 VALUES( blob(900) );
dan4cc6fb62010-04-15 16:45:34 +0000786 SELECT count(*) FROM t1;
787 PRAGMA integrity_check;
788 }
789} {17 ok}
790do_test wal-11.14 {
dan97a31352010-04-16 13:59:31 +0000791 list [expr [file size test.db]/1024] [file size test.db-wal]
dan4cd78b42010-04-26 16:57:10 +0000792} [list 37 [log_file_size 37 1024]]
dan4cc6fb62010-04-15 16:45:34 +0000793
794
dan4a4b01d2010-04-16 11:30:18 +0000795#-------------------------------------------------------------------------
dan97a31352010-04-16 13:59:31 +0000796# This block of tests, wal-12.*, tests the fix for a problem that
797# could occur if a log that is a prefix of an older log is written
798# into a reused log file.
dan4a4b01d2010-04-16 11:30:18 +0000799#
800reopen_db
801do_test wal-12.1 {
802 execsql {
803 PRAGMA page_size = 1024;
804 CREATE TABLE t1(x, y);
805 CREATE TABLE t2(x, y);
806 INSERT INTO t1 VALUES('A', 1);
807 }
dan97a31352010-04-16 13:59:31 +0000808 list [expr [file size test.db]/1024] [file size test.db-wal]
dane04dc882010-04-20 18:53:15 +0000809} [list 1 [log_file_size 5 1024]]
dan4a4b01d2010-04-16 11:30:18 +0000810do_test wal-12.2 {
811 db close
dane04dc882010-04-20 18:53:15 +0000812 sqlite3 db test.db
dan4a4b01d2010-04-16 11:30:18 +0000813 execsql {
dane04dc882010-04-20 18:53:15 +0000814 PRAGMA synchronous = normal;
dan4a4b01d2010-04-16 11:30:18 +0000815 UPDATE t1 SET y = 0 WHERE x = 'A';
816 }
817 list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
818} {3 1}
819do_test wal-12.3 {
820 execsql { INSERT INTO t2 VALUES('B', 1) }
821 list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
822} {3 2}
dan4a4b01d2010-04-16 11:30:18 +0000823do_test wal-12.4 {
824 file copy -force test.db test2.db
825 file copy -force test.db-wal test2.db-wal
826 sqlite3_wal db2 test2.db
dan4a4b01d2010-04-16 11:30:18 +0000827 execsql { SELECT * FROM t2 } db2
828} {B 1}
829db2 close
dan4a4b01d2010-04-16 11:30:18 +0000830do_test wal-12.5 {
831 execsql {
dan5a299f92010-05-03 11:05:08 +0000832 PRAGMA wal_checkpoint;
dan4a4b01d2010-04-16 11:30:18 +0000833 UPDATE t2 SET y = 2 WHERE x = 'B';
dan5a299f92010-05-03 11:05:08 +0000834 PRAGMA wal_checkpoint;
dan4a4b01d2010-04-16 11:30:18 +0000835 UPDATE t1 SET y = 1 WHERE x = 'A';
dan5a299f92010-05-03 11:05:08 +0000836 PRAGMA wal_checkpoint;
dan4a4b01d2010-04-16 11:30:18 +0000837 UPDATE t1 SET y = 0 WHERE x = 'A';
838 SELECT * FROM t2;
839 }
840} {B 2}
dance4f05f2010-04-22 19:14:13 +0000841do_test wal-12.6 {
dan4a4b01d2010-04-16 11:30:18 +0000842 file copy -force test.db test2.db
843 file copy -force test.db-wal test2.db-wal
844 sqlite3_wal db2 test2.db
845 execsql { SELECT * FROM t2 } db2
846} {B 2}
847db2 close
dance4f05f2010-04-22 19:14:13 +0000848db close
849
850#-------------------------------------------------------------------------
851# Test large log summaries.
852#
dan31f98fc2010-04-27 05:42:32 +0000853do_test wal-13.1.1 {
dance4f05f2010-04-22 19:14:13 +0000854 list [file exists test.db] [file exists test.db-wal]
855} {1 0}
dan31f98fc2010-04-27 05:42:32 +0000856do_test wal-13.1.2 {
dance4f05f2010-04-22 19:14:13 +0000857 set fd [open test.db-wal w]
858 seek $fd [expr 200*1024*1024]
859 puts $fd ""
860 close $fd
861 sqlite3 db test.db
862 execsql { SELECT * FROM t2 }
863} {B 2}
dan31f98fc2010-04-27 05:42:32 +0000864do_test wal-13.1.3 {
dance4f05f2010-04-22 19:14:13 +0000865 db close
866 file exists test.db-wal
867} {0}
dan31f98fc2010-04-27 05:42:32 +0000868do_test wal-13.1.4 {
dance4f05f2010-04-22 19:14:13 +0000869 sqlite3 db test.db
870 execsql { SELECT count(*) FROM t2 }
871} {1}
dan31f98fc2010-04-27 05:42:32 +0000872do_test wal-13.1.5 {
873 for {set i 0} {$i < 6} {incr i} {
dance4f05f2010-04-22 19:14:13 +0000874 execsql { INSERT INTO t2 SELECT randomblob(400), randomblob(400) FROM t2 }
875 }
876 execsql { SELECT count(*) FROM t2 }
dan31f98fc2010-04-27 05:42:32 +0000877} [expr int(pow(2, 6))]
878do_test wal-13.1.6 {
879 file size test.db-wal
880} [log_file_size 80 1024]
dance4f05f2010-04-22 19:14:13 +0000881
dan31f98fc2010-04-27 05:42:32 +0000882foreach code [list {
883 set tn 2
884 proc buddy {tcl} { uplevel #0 $tcl }
885} {
886 set tn 3
887 set ::buddy [launch_testfixture]
888 proc buddy {tcl} { testfixture $::buddy $tcl }
889}] {
890
891 eval $code
892 reopen_db
893
894 do_test wal-13.$tn.0 {
895 buddy { sqlite3 db2 test.db }
896 execsql {
897 PRAGMA journal_mode = WAL;
898 CREATE TABLE t1(x);
899 INSERT INTO t1 SELECT randomblob(400);
900 }
901 execsql { SELECT count(*) FROM t1 }
902 } {1}
903
904 for {set ii 1} {$ii<16} {incr ii} {
905 do_test wal-13.$tn.$ii.a {
906 buddy { db2 eval { INSERT INTO t1 SELECT randomblob(400) FROM t1 } }
907 buddy { db2 eval { SELECT count(*) FROM t1 } }
908 } [expr (1<<$ii)]
909 do_test wal-13.$tn.$ii.b {
910 db eval { SELECT count(*) FROM t1 }
911 } [expr (1<<$ii)]
912 do_test wal-13.$tn.$ii.c {
913 db eval { SELECT count(*) FROM t1 }
914 } [expr (1<<$ii)]
drh1b48aa42010-04-30 17:28:35 +0000915 do_test wal-13.$tn.$ii.d {
916 db eval { PRAGMA integrity_check }
917 } {ok}
dan31f98fc2010-04-27 05:42:32 +0000918 }
919
920 catch { db2 close }
921 catch { close $::buddy }
922 db close
923}
dan4a4b01d2010-04-16 11:30:18 +0000924
dan31c03902010-04-29 14:51:33 +0000925#-------------------------------------------------------------------------
926# Check a fun corruption case has been fixed.
927#
928# The problem was that after performing a checkpoint using a connection
929# that had an out-of-date pager-cache, the next time the connection was
930# used it did not realize the cache was out-of-date and proceeded to
931# operate with an inconsistent cache. Leading to corruption.
932#
933
934catch { db close }
935catch { db2 close }
936catch { db3 close }
937file delete -force test.db test.db-wal
938sqlite3 db test.db
939sqlite3 db2 test.db
940
941do_test wal-14 {
942 execsql {
943 PRAGMA journal_mode = WAL;
944 CREATE TABLE t1(a PRIMARY KEY, b);
945 INSERT INTO t1 VALUES(randomblob(10), randomblob(100));
946 INSERT INTO t1 SELECT randomblob(10), randomblob(100) FROM t1;
947 INSERT INTO t1 SELECT randomblob(10), randomblob(100) FROM t1;
948 INSERT INTO t1 SELECT randomblob(10), randomblob(100) FROM t1;
949 }
950
951 db2 eval {
952 INSERT INTO t1 SELECT randomblob(10), randomblob(100);
953 INSERT INTO t1 SELECT randomblob(10), randomblob(100);
954 INSERT INTO t1 SELECT randomblob(10), randomblob(100);
955 INSERT INTO t1 SELECT randomblob(10), randomblob(100);
956 }
957
dan5a299f92010-05-03 11:05:08 +0000958 # After executing the "PRAGMA wal_checkpoint", connection [db] was being
dan31c03902010-04-29 14:51:33 +0000959 # left with an inconsistent cache. Running the CREATE INDEX statement
960 # in this state led to database corruption.
961 catchsql {
dan5a299f92010-05-03 11:05:08 +0000962 PRAGMA wal_checkpoint;
dan31c03902010-04-29 14:51:33 +0000963 CREATE INDEX i1 on t1(b);
964 }
965
966 db2 eval { PRAGMA integrity_check }
967} {ok}
968
dan185cca62010-04-29 14:58:53 +0000969catch { db close }
970catch { db2 close }
dan87c1fe12010-05-03 12:14:15 +0000971
972#-------------------------------------------------------------------------
973# The following block of tests - wal-15.* - focus on testing the
974# implementation of the sqlite3_wal_checkpoint() interface.
975#
976file delete -force test.db test.db-wal
977sqlite3 db test.db
978do_test wal-15.1 {
979 execsql {
980 PRAGMA page_size = 1024;
981 PRAGMA journal_mode = WAL;
982 }
983 execsql {
984 CREATE TABLE t1(a, b);
985 INSERT INTO t1 VALUES(1, 2);
986 }
987} {}
988
989# Test that an error is returned if the database name is not recognized
990#
991do_test wal-15.2.1 {
992 sqlite3_wal_checkpoint db aux
993} {SQLITE_ERROR}
994do_test wal-15.2.2 {
995 sqlite3_errcode db
996} {SQLITE_ERROR}
997do_test wal-15.2.3 {
998 sqlite3_errmsg db
999} {unknown database: aux}
1000
1001# Test that an error is returned if an attempt is made to checkpoint
1002# if a transaction is open on the database.
1003#
1004do_test wal-15.3.1 {
1005 execsql {
1006 BEGIN;
1007 INSERT INTO t1 VALUES(3, 4);
1008 }
1009 sqlite3_wal_checkpoint db main
1010} {SQLITE_LOCKED}
1011do_test wal-15.3.2 {
1012 sqlite3_errcode db
1013} {SQLITE_LOCKED}
1014do_test wal-15.3.3 {
1015 sqlite3_errmsg db
1016} {database table is locked}
1017
1018# Also test that an error is returned if the db cannot be checkpointed
1019# because of locks held by another connection.
1020#
1021sqlite3 db2 test.db
1022do_test wal-15.4.1 {
1023 execsql {
1024 BEGIN;
1025 SELECT * FROM t1;
1026 } db2
1027} {1 2}
1028do_test wal-15.4.2 {
1029 execsql { COMMIT }
1030 sqlite3_wal_checkpoint db
1031} {SQLITE_BUSY}
1032do_test wal-15.4.3 {
1033 sqlite3_errmsg db
1034} {database is locked}
1035
1036# After [db2] drops its lock, [db] may checkpoint the db.
1037#
1038do_test wal-15.4.4 {
1039 execsql { COMMIT } db2
1040 sqlite3_wal_checkpoint db
1041} {SQLITE_OK}
1042do_test wal-15.4.5 {
1043 sqlite3_errmsg db
1044} {not an error}
1045do_test wal-15.4.6 {
1046 file size test.db
1047} [expr 1024*2]
1048
1049catch { db2 close }
1050catch { db close }
danaf0cfd32010-05-03 15:58:50 +00001051
1052#-------------------------------------------------------------------------
1053# The following block of tests - wal-16.* - test that if a NULL pointer or
1054# an empty string is passed as the second argument of the wal_checkpoint()
1055# API, an attempt is made to checkpoint all attached databases.
1056#
1057foreach {tn ckpt_cmd ckpt_res ckpt_main ckpt_aux} {
1058 1 {sqlite3_wal_checkpoint db} SQLITE_OK 1 1
1059 2 {sqlite3_wal_checkpoint db ""} SQLITE_OK 1 1
1060 3 {db eval "PRAGMA wal_checkpoint"} {} 1 1
1061
1062 4 {sqlite3_wal_checkpoint db main} SQLITE_OK 1 0
1063 5 {sqlite3_wal_checkpoint db aux} SQLITE_OK 0 1
1064 6 {sqlite3_wal_checkpoint db temp} SQLITE_OK 0 0
1065 7 {db eval "PRAGMA main.wal_checkpoint"} {} 1 0
1066 8 {db eval "PRAGMA aux.wal_checkpoint"} {} 0 1
1067 9 {db eval "PRAGMA temp.wal_checkpoint"} {} 0 0
1068} {
1069 do_test wal-16.$tn.1 {
1070 file delete -force test2.db test2.db-wal test2.db-journal
1071 file delete -force test.db test.db-wal test.db-journal
1072
1073 sqlite3 db test.db
1074 execsql {
1075 ATTACH 'test2.db' AS aux;
1076 PRAGMA main.journal_mode = WAL;
1077 PRAGMA aux.journal_mode = WAL;
1078 PRAGMA synchronous = NORMAL;
1079 }
1080 } {wal wal}
1081
1082 do_test wal-16.$tn.2 {
1083 execsql {
1084 CREATE TABLE main.t1(a, b, PRIMARY KEY(a, b));
1085 CREATE TABLE aux.t2(a, b, PRIMARY KEY(a, b));
1086
1087 INSERT INTO t2 VALUES(1, randomblob(1000));
1088 INSERT INTO t2 VALUES(2, randomblob(1000));
1089 INSERT INTO t1 SELECT * FROM t2;
1090 }
1091
1092 list [file size test.db] [file size test.db-wal]
1093 } [list [expr 1*1024] [log_file_size 10 1024]]
1094 do_test wal-16.$tn.3 {
1095 list [file size test2.db] [file size test2.db-wal]
1096 } [list [expr 1*1024] [log_file_size 16 1024]]
1097
1098 do_test wal-16.$tn.4 [list eval $ckpt_cmd] $ckpt_res
1099
1100 do_test wal-16.$tn.5 {
1101 list [file size test.db] [file size test.db-wal]
1102 } [list [expr ($ckpt_main ? 7 : 1)*1024] [log_file_size 10 1024]]
1103
1104 do_test wal-16.$tn.6 {
1105 list [file size test2.db] [file size test2.db-wal]
1106 } [list [expr ($ckpt_aux ? 7 : 1)*1024] [log_file_size 16 1024]]
1107
1108 catch { db close }
1109}
1110
1111catch { db2 close }
1112catch { db close }
dan7c246102010-04-12 19:00:29 +00001113finish_test
dan87c1fe12010-05-03 12:14:15 +00001114
1115