xref: /sqlite-3.40.0/test/walmode.test (revision 69aedc8d)
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