xref: /sqlite-3.40.0/test/wal6.test (revision 506a1400)
1# 2010 December 1
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]
17set testprefix wal6
18source $testdir/tester.tcl
19source $testdir/lock_common.tcl
20source $testdir/wal_common.tcl
21source $testdir/malloc_common.tcl
22ifcapable !wal {finish_test ; return }
23
24#-------------------------------------------------------------------------
25# Changing to WAL mode in one connection forces the change in others.
26#
27db close
28forcedelete test.db
29
30set all_journal_modes {delete persist truncate memory off}
31foreach jmode $all_journal_modes {
32
33  do_test wal6-1.0.$jmode {
34    sqlite3 db test.db
35    execsql "PRAGMA journal_mode = $jmode;"
36  } $jmode
37
38  do_test wal6-1.1.$jmode {
39    execsql {
40      CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
41      INSERT INTO t1 VALUES(1,2);
42      SELECT * FROM t1;
43    }
44  } {1 2}
45
46# Under Windows, you'll get an error trying to delete
47# a file this is already opened.  Close the first connection
48# so the other tests work.
49if {$tcl_platform(platform)=="windows"} {
50  if {$jmode=="persist" || $jmode=="truncate"} {
51    db close
52  }
53}
54
55  do_test wal6-1.2.$jmode {
56    sqlite3 db2 test.db
57    execsql {
58    PRAGMA journal_mode=WAL;
59    INSERT INTO t1 VALUES(3,4);
60    SELECT * FROM t1 ORDER BY a;
61    } db2
62  } {wal 1 2 3 4}
63
64if {$tcl_platform(platform)=="windows"} {
65  if {$jmode=="persist" || $jmode=="truncate"} {
66    sqlite3 db test.db
67  }
68}
69
70  do_test wal6-1.3.$jmode {
71    execsql {
72      SELECT * FROM t1 ORDER BY a;
73    }
74  } {1 2 3 4}
75
76  db close
77  db2 close
78  forcedelete test.db
79
80}
81
82#-------------------------------------------------------------------------
83# Test that SQLITE_BUSY_SNAPSHOT is returned as expected.
84#
85reset_db
86sqlite3 db2 test.db
87
88do_execsql_test 2.1 {
89  PRAGMA journal_mode = WAL;
90  CREATE TABLE t1(a PRIMARY KEY, b TEXT);
91  INSERT INTO t1 VALUES(1, 'one');
92  INSERT INTO t1 VALUES(2, 'two');
93  BEGIN;
94    SELECT * FROM t1;
95} {wal 1 one 2 two}
96
97do_test 2.2 {
98  execsql {
99    SELECT * FROM t1;
100    INSERT INTO t1 VALUES(3, 'three');
101  } db2
102} {1 one 2 two}
103
104do_catchsql_test 2.3 {
105  INSERT INTO t1 VALUES('x', 'x')
106} {1 {database is locked}}
107
108do_test 2.4 {
109  list [sqlite3_errcode db] [sqlite3_extended_errcode db]
110} {SQLITE_BUSY SQLITE_BUSY_SNAPSHOT}
111
112do_execsql_test 2.5 {
113  SELECT * FROM t1;
114  COMMIT;
115  INSERT INTO t1 VALUES('x', 'x')
116} {1 one 2 two}
117
118proc test3 {prefix} {
119  do_test $prefix.1 {
120    execsql { SELECT count(*) FROM t1 }
121  } {0}
122  do_test $prefix.2 {
123    execsql { INSERT INTO t1 VALUES('x', 'x') } db2
124  } {}
125  do_test $prefix.3 {
126    execsql { INSERT INTO t1 VALUES('y', 'y') }
127  } {}
128  do_test $prefix.4 {
129    execsql { SELECT count(*) FROM t1 }
130  } {2}
131}
132
133do_execsql_test 2.6.1 { DELETE FROM t1 }
134test3 2.6.2
135
136db func test3 test3
137do_execsql_test 2.6.3 { DELETE FROM t1 }
138db eval {SELECT test3('2.6.4')}
139
140do_test 2.x {
141  db2 close
142} {}
143
144#-------------------------------------------------------------------------
145# Check that if BEGIN IMMEDIATE fails, it does not leave the user with
146# an open read-transaction (unless one was already open before the BEGIN
147# IMMEDIATE). Even if there are other active VMs.
148#
149
150proc test4 {prefix} {
151  do_test $prefix.1 {
152    catchsql { BEGIN IMMEDIATE }
153  } {1 {database is locked}}
154
155  do_test $prefix.2 {
156    execsql { COMMIT } db2
157  } {}
158
159  do_test $prefix.3 {
160    execsql { BEGIN IMMEDIATE }
161  } {}
162  do_test $prefix.4 {
163    execsql { COMMIT }
164  } {}
165}
166
167reset_db
168sqlite3 db2 test.db
169do_execsql_test 3.1 {
170  PRAGMA journal_mode = WAL;
171  CREATE TABLE ab(a PRIMARY KEY, b);
172} {wal}
173
174do_test 3.2.1 {
175  execsql {
176    BEGIN;
177      INSERT INTO ab VALUES(1, 2);
178  } db2
179} {}
180test4 3.2.2
181
182db func test4 test4
183do_test 3.3.1 {
184  execsql {
185    BEGIN;
186      INSERT INTO ab VALUES(3, 4);
187  } db2
188} {}
189
190db eval {SELECT test4('3.3.2')}
191
192do_test 3.x {
193  db2 close
194} {}
195
196#-------------------------------------------------------------------------
197# Check that if a wal file has been partially checkpointed, no frames are
198# read from the checkpointed part.
199#
200reset_db
201do_execsql_test 4.1 {
202  PRAGMA page_size = 1024;
203  PRAGMA journal_mode = wal;
204  CREATE TABLE t1(a, b);
205  CREATE TABLE t2(a, b);
206  PRAGMA wal_checkpoint = truncate;
207} {wal 0 0 0}
208
209do_test 4.2 {
210  execsql { INSERT INTO t1 VALUES(1, 2) }
211  file size test.db-wal
212} [wal_file_size 1 1024]
213
214do_test 4.3 {
215  sqlite3 db2 test.db
216  execsql {
217    BEGIN;
218    INSERT INTO t2 VALUES(3, 4);
219  }
220  execsql { PRAGMA wal_checkpoint = passive } db2
221} {0 1 1}
222
223do_test 4.3 {
224  execsql { COMMIT }
225  db2 close
226  hexio_write test.db-wal 0 [string repeat 00 2000]
227  sqlite3 db2 test.db
228} {}
229
230do_test 4.4.1 {
231  catchsql { SELECT * FROM t1 } db2
232} {0 {1 2}}
233do_test 4.4.2 {
234  catchsql { SELECT * FROM t2 } db2
235} {1 {database disk image is malformed}}
236
237#-------------------------------------------------------------------------
238# Confirm that it is possible to get an SQLITE_BUSY_SNAPSHOT error from
239# "BEGIN EXCLUSIVE" if the connection already has an open read-transaction.
240#
241db close
242db2 close
243reset_db
244sqlite3 db2 test.db
245do_execsql_test 5.1 {
246  PRAGMA journal_mode = wal;
247  CREATE TABLE t1(x, y);
248  INSERT INTO t1 VALUES(1, 2);
249  INSERT INTO t1 VALUES(3, 4);
250} {wal}
251do_test 5.2 {
252  set res [list]
253  db eval {
254    SELECT * FROM t1
255  } {
256    if {$x==1} {
257      db2 eval { INSERT INTO t1 VALUES(5, 6) }
258    }
259    if {$x==3} {
260      set res [catchsql {BEGIN EXCLUSIVE}]
261      lappend res [sqlite3_extended_errcode db]
262    }
263  }
264  set res
265} {1 {database is locked} SQLITE_BUSY_SNAPSHOT}
266
267
268
269finish_test
270