xref: /sqlite-3.40.0/test/wal6.test (revision 506a1400)
172fe10fdSshaneh# 2010 December 1
272fe10fdSshaneh#
372fe10fdSshaneh# The author disclaims copyright to this source code.  In place of
472fe10fdSshaneh# a legal notice, here is a blessing:
572fe10fdSshaneh#
672fe10fdSshaneh#    May you do good and not evil.
772fe10fdSshaneh#    May you find forgiveness for yourself and forgive others.
872fe10fdSshaneh#    May you share freely, never taking more than you give.
972fe10fdSshaneh#
1072fe10fdSshaneh#***********************************************************************
1172fe10fdSshaneh# This file implements regression tests for SQLite library.  The
1272fe10fdSshaneh# focus of this file is testing the operation of the library in
1372fe10fdSshaneh# "PRAGMA journal_mode=WAL" mode.
1472fe10fdSshaneh#
1572fe10fdSshaneh
1672fe10fdSshanehset testdir [file dirname $argv0]
17f73819afSdanset testprefix wal6
1872fe10fdSshanehsource $testdir/tester.tcl
1972fe10fdSshanehsource $testdir/lock_common.tcl
2072fe10fdSshanehsource $testdir/wal_common.tcl
2172fe10fdSshanehsource $testdir/malloc_common.tcl
2272fe10fdSshanehifcapable !wal {finish_test ; return }
2372fe10fdSshaneh
2472fe10fdSshaneh#-------------------------------------------------------------------------
2572fe10fdSshaneh# Changing to WAL mode in one connection forces the change in others.
2672fe10fdSshaneh#
2772fe10fdSshanehdb close
2872fe10fdSshanehforcedelete test.db
2972fe10fdSshaneh
3072fe10fdSshanehset all_journal_modes {delete persist truncate memory off}
3172fe10fdSshanehforeach jmode $all_journal_modes {
3272fe10fdSshaneh
3372fe10fdSshaneh  do_test wal6-1.0.$jmode {
3472fe10fdSshaneh    sqlite3 db test.db
3572fe10fdSshaneh    execsql "PRAGMA journal_mode = $jmode;"
3672fe10fdSshaneh  } $jmode
3772fe10fdSshaneh
3872fe10fdSshaneh  do_test wal6-1.1.$jmode {
3972fe10fdSshaneh    execsql {
4072fe10fdSshaneh      CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
4172fe10fdSshaneh      INSERT INTO t1 VALUES(1,2);
4272fe10fdSshaneh      SELECT * FROM t1;
4372fe10fdSshaneh    }
4472fe10fdSshaneh  } {1 2}
4572fe10fdSshaneh
4672fe10fdSshaneh# Under Windows, you'll get an error trying to delete
4752564d70Sdrh# a file this is already opened.  Close the first connection
4872fe10fdSshaneh# so the other tests work.
4972fe10fdSshanehif {$tcl_platform(platform)=="windows"} {
5072fe10fdSshaneh  if {$jmode=="persist" || $jmode=="truncate"} {
5172fe10fdSshaneh    db close
5272fe10fdSshaneh  }
5372fe10fdSshaneh}
5472fe10fdSshaneh
5572fe10fdSshaneh  do_test wal6-1.2.$jmode {
5672fe10fdSshaneh    sqlite3 db2 test.db
5772fe10fdSshaneh    execsql {
5872fe10fdSshaneh    PRAGMA journal_mode=WAL;
5972fe10fdSshaneh    INSERT INTO t1 VALUES(3,4);
6072fe10fdSshaneh    SELECT * FROM t1 ORDER BY a;
6172fe10fdSshaneh    } db2
6272fe10fdSshaneh  } {wal 1 2 3 4}
6372fe10fdSshaneh
6472fe10fdSshanehif {$tcl_platform(platform)=="windows"} {
6572fe10fdSshaneh  if {$jmode=="persist" || $jmode=="truncate"} {
6672fe10fdSshaneh    sqlite3 db test.db
6772fe10fdSshaneh  }
6872fe10fdSshaneh}
6972fe10fdSshaneh
7072fe10fdSshaneh  do_test wal6-1.3.$jmode {
7172fe10fdSshaneh    execsql {
7272fe10fdSshaneh      SELECT * FROM t1 ORDER BY a;
7372fe10fdSshaneh    }
7472fe10fdSshaneh  } {1 2 3 4}
7572fe10fdSshaneh
7672fe10fdSshaneh  db close
7772fe10fdSshaneh  db2 close
7872fe10fdSshaneh  forcedelete test.db
7972fe10fdSshaneh
8072fe10fdSshaneh}
8172fe10fdSshaneh
82f73819afSdan#-------------------------------------------------------------------------
83f73819afSdan# Test that SQLITE_BUSY_SNAPSHOT is returned as expected.
84f73819afSdan#
85f73819afSdanreset_db
86f73819afSdansqlite3 db2 test.db
87f73819afSdan
88f73819afSdando_execsql_test 2.1 {
89f73819afSdan  PRAGMA journal_mode = WAL;
90f73819afSdan  CREATE TABLE t1(a PRIMARY KEY, b TEXT);
91f73819afSdan  INSERT INTO t1 VALUES(1, 'one');
92f73819afSdan  INSERT INTO t1 VALUES(2, 'two');
93f73819afSdan  BEGIN;
94f73819afSdan    SELECT * FROM t1;
95f73819afSdan} {wal 1 one 2 two}
96f73819afSdan
97f73819afSdando_test 2.2 {
98f73819afSdan  execsql {
99f73819afSdan    SELECT * FROM t1;
100f73819afSdan    INSERT INTO t1 VALUES(3, 'three');
101f73819afSdan  } db2
102f73819afSdan} {1 one 2 two}
103f73819afSdan
104f73819afSdando_catchsql_test 2.3 {
105f73819afSdan  INSERT INTO t1 VALUES('x', 'x')
106f73819afSdan} {1 {database is locked}}
107f73819afSdan
108f73819afSdando_test 2.4 {
109f73819afSdan  list [sqlite3_errcode db] [sqlite3_extended_errcode db]
110f73819afSdan} {SQLITE_BUSY SQLITE_BUSY_SNAPSHOT}
111f73819afSdan
112f73819afSdando_execsql_test 2.5 {
113f73819afSdan  SELECT * FROM t1;
114f73819afSdan  COMMIT;
115f73819afSdan  INSERT INTO t1 VALUES('x', 'x')
116f73819afSdan} {1 one 2 two}
117f73819afSdan
118f73819afSdanproc test3 {prefix} {
119f73819afSdan  do_test $prefix.1 {
120f73819afSdan    execsql { SELECT count(*) FROM t1 }
121f73819afSdan  } {0}
122f73819afSdan  do_test $prefix.2 {
123f73819afSdan    execsql { INSERT INTO t1 VALUES('x', 'x') } db2
124f73819afSdan  } {}
125f73819afSdan  do_test $prefix.3 {
126f73819afSdan    execsql { INSERT INTO t1 VALUES('y', 'y') }
127f73819afSdan  } {}
128f73819afSdan  do_test $prefix.4 {
129f73819afSdan    execsql { SELECT count(*) FROM t1 }
130f73819afSdan  } {2}
131f73819afSdan}
132f73819afSdan
133f73819afSdando_execsql_test 2.6.1 { DELETE FROM t1 }
134f73819afSdantest3 2.6.2
135f73819afSdan
136f73819afSdandb func test3 test3
137f73819afSdando_execsql_test 2.6.3 { DELETE FROM t1 }
138f73819afSdandb eval {SELECT test3('2.6.4')}
139f73819afSdan
140f73819afSdando_test 2.x {
141f73819afSdan  db2 close
142f73819afSdan} {}
143f73819afSdan
144e8e570abSdan#-------------------------------------------------------------------------
145e8e570abSdan# Check that if BEGIN IMMEDIATE fails, it does not leave the user with
146e8e570abSdan# an open read-transaction (unless one was already open before the BEGIN
147e8e570abSdan# IMMEDIATE). Even if there are other active VMs.
148e8e570abSdan#
149e8e570abSdan
150e8e570abSdanproc test4 {prefix} {
151e8e570abSdan  do_test $prefix.1 {
152e8e570abSdan    catchsql { BEGIN IMMEDIATE }
153e8e570abSdan  } {1 {database is locked}}
154e8e570abSdan
155e8e570abSdan  do_test $prefix.2 {
156e8e570abSdan    execsql { COMMIT } db2
157e8e570abSdan  } {}
158e8e570abSdan
159e8e570abSdan  do_test $prefix.3 {
160e8e570abSdan    execsql { BEGIN IMMEDIATE }
161e8e570abSdan  } {}
162e8e570abSdan  do_test $prefix.4 {
163e8e570abSdan    execsql { COMMIT }
164e8e570abSdan  } {}
165e8e570abSdan}
166e8e570abSdan
167e8e570abSdanreset_db
168e8e570abSdansqlite3 db2 test.db
169e8e570abSdando_execsql_test 3.1 {
170e8e570abSdan  PRAGMA journal_mode = WAL;
171e8e570abSdan  CREATE TABLE ab(a PRIMARY KEY, b);
172e8e570abSdan} {wal}
173e8e570abSdan
174e8e570abSdando_test 3.2.1 {
175e8e570abSdan  execsql {
176e8e570abSdan    BEGIN;
177e8e570abSdan      INSERT INTO ab VALUES(1, 2);
178e8e570abSdan  } db2
179e8e570abSdan} {}
180e8e570abSdantest4 3.2.2
181e8e570abSdan
182e8e570abSdandb func test4 test4
183e8e570abSdando_test 3.3.1 {
184e8e570abSdan  execsql {
185e8e570abSdan    BEGIN;
186e8e570abSdan      INSERT INTO ab VALUES(3, 4);
187e8e570abSdan  } db2
188e8e570abSdan} {}
189e8e570abSdan
190e8e570abSdandb eval {SELECT test4('3.3.2')}
191e8e570abSdan
192e8e570abSdando_test 3.x {
193e8e570abSdan  db2 close
194e8e570abSdan} {}
195e8e570abSdan
1966df003c7Sdan#-------------------------------------------------------------------------
1976df003c7Sdan# Check that if a wal file has been partially checkpointed, no frames are
1986df003c7Sdan# read from the checkpointed part.
1996df003c7Sdan#
2006df003c7Sdanreset_db
2016df003c7Sdando_execsql_test 4.1 {
2026df003c7Sdan  PRAGMA page_size = 1024;
2036df003c7Sdan  PRAGMA journal_mode = wal;
2046df003c7Sdan  CREATE TABLE t1(a, b);
2056df003c7Sdan  CREATE TABLE t2(a, b);
2066df003c7Sdan  PRAGMA wal_checkpoint = truncate;
2076df003c7Sdan} {wal 0 0 0}
2086df003c7Sdan
2096df003c7Sdando_test 4.2 {
2106df003c7Sdan  execsql { INSERT INTO t1 VALUES(1, 2) }
2116df003c7Sdan  file size test.db-wal
2126df003c7Sdan} [wal_file_size 1 1024]
2136df003c7Sdan
2146df003c7Sdando_test 4.3 {
2156df003c7Sdan  sqlite3 db2 test.db
2166df003c7Sdan  execsql {
2176df003c7Sdan    BEGIN;
2186df003c7Sdan    INSERT INTO t2 VALUES(3, 4);
2196df003c7Sdan  }
2206df003c7Sdan  execsql { PRAGMA wal_checkpoint = passive } db2
2216df003c7Sdan} {0 1 1}
2226df003c7Sdan
2236df003c7Sdando_test 4.3 {
2246df003c7Sdan  execsql { COMMIT }
2256df003c7Sdan  db2 close
2266df003c7Sdan  hexio_write test.db-wal 0 [string repeat 00 2000]
2276df003c7Sdan  sqlite3 db2 test.db
2286df003c7Sdan} {}
2296df003c7Sdan
2306df003c7Sdando_test 4.4.1 {
2316df003c7Sdan  catchsql { SELECT * FROM t1 } db2
2326df003c7Sdan} {0 {1 2}}
2336df003c7Sdando_test 4.4.2 {
2346df003c7Sdan  catchsql { SELECT * FROM t2 } db2
2356df003c7Sdan} {1 {database disk image is malformed}}
2366df003c7Sdan
23701e697b4Sdan#-------------------------------------------------------------------------
23801e697b4Sdan# Confirm that it is possible to get an SQLITE_BUSY_SNAPSHOT error from
23901e697b4Sdan# "BEGIN EXCLUSIVE" if the connection already has an open read-transaction.
24001e697b4Sdan#
241*506a1400Sdrhdb close
242*506a1400Sdrhdb2 close
24301e697b4Sdanreset_db
24401e697b4Sdansqlite3 db2 test.db
24501e697b4Sdando_execsql_test 5.1 {
24601e697b4Sdan  PRAGMA journal_mode = wal;
24701e697b4Sdan  CREATE TABLE t1(x, y);
24801e697b4Sdan  INSERT INTO t1 VALUES(1, 2);
24901e697b4Sdan  INSERT INTO t1 VALUES(3, 4);
25001e697b4Sdan} {wal}
25101e697b4Sdando_test 5.2 {
25201e697b4Sdan  set res [list]
25301e697b4Sdan  db eval {
25401e697b4Sdan    SELECT * FROM t1
25501e697b4Sdan  } {
25601e697b4Sdan    if {$x==1} {
25701e697b4Sdan      db2 eval { INSERT INTO t1 VALUES(5, 6) }
25801e697b4Sdan    }
25901e697b4Sdan    if {$x==3} {
26001e697b4Sdan      set res [catchsql {BEGIN EXCLUSIVE}]
26101e697b4Sdan      lappend res [sqlite3_extended_errcode db]
26201e697b4Sdan    }
26301e697b4Sdan  }
26401e697b4Sdan  set res
26501e697b4Sdan} {1 {database is locked} SQLITE_BUSY_SNAPSHOT}
26601e697b4Sdan
26701e697b4Sdan
2686df003c7Sdan
26972fe10fdSshanehfinish_test
270