xref: /sqlite-3.40.0/test/snapshot.test (revision 3bf83ccd)
1# 2015 December 7
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 SELECT statement.
13#
14# $Id: select1.test,v 1.70 2009/05/28 01:00:56 drh Exp $
15
16set testdir [file dirname $argv0]
17source $testdir/tester.tcl
18set testprefix snapshot
19
20#-------------------------------------------------------------------------
21# Check some error conditions in snapshot_get(). It is an error if:
22#
23#  1) snapshot_get() is called on a non-WAL database.
24#  2) there is no open read transaction on the database, or
25#  3) there is an open write transaction on the database.
26#
27do_execsql_test 1.0 {
28  CREATE TABLE t1(a, b);
29  INSERT INTO t1 VALUES(1, 2);
30  INSERT INTO t1 VALUES(3, 4);
31}
32
33do_test 1.1.1 {
34  execsql { BEGIN; SELECT * FROM t1; }
35  list [catch { sqlite3_snapshot_get db main } msg] $msg
36} {1 SQLITE_ERROR}
37do_execsql_test 1.1.2 COMMIT
38
39do_test 1.2.1 {
40  execsql {
41    PRAGMA journal_mode = wal;
42    INSERT INTO t1 VALUES(5, 6);
43  }
44  list [catch { sqlite3_snapshot_get db main } msg] $msg
45} {1 SQLITE_ERROR}
46
47do_test 1.3.1 {
48  execsql {
49    BEGIN;
50      INSERT INTO t1 VALUES(7, 8);
51  }
52  list [catch { sqlite3_snapshot_get db main } msg] $msg
53} {1 SQLITE_ERROR}
54do_execsql_test 1.3.2 COMMIT
55
56#-------------------------------------------------------------------------
57# Check that a simple case works. Reuse the database created by the
58# block of tests above.
59#
60do_execsql_test 2.1.0 {
61  BEGIN;
62    SELECT * FROM t1;
63} {1 2 3 4 5 6 7 8}
64
65do_test 2.1.1 {
66  set snapshot [sqlite3_snapshot_get db main]
67  execsql {
68    COMMIT;
69    INSERT INTO t1 VALUES(9, 10);
70    SELECT * FROM t1;
71  }
72} {1 2 3 4 5 6 7 8 9 10}
73
74do_test 2.1.2 {
75  execsql BEGIN
76  sqlite3_snapshot_open db main $snapshot
77  execsql {
78    SELECT * FROM t1;
79  }
80} {1 2 3 4 5 6 7 8}
81
82do_test 2.1.3 {
83  sqlite3_snapshot_free $snapshot
84  execsql COMMIT
85} {}
86
87do_test 2.2.0 {
88  sqlite3 db2 test.db
89  execsql {
90    BEGIN;
91      SELECT * FROM t1;
92  } db2
93} {1 2 3 4 5 6 7 8 9 10}
94
95do_test 2.2.1 {
96  set snapshot [sqlite3_snapshot_get db2 main]
97  execsql {
98    INSERT INTO t1 VALUES(11, 12);
99    SELECT * FROM t1;
100  }
101} {1 2 3 4 5 6 7 8 9 10 11 12}
102
103do_test 2.2.2 {
104  execsql BEGIN
105  sqlite3_snapshot_open db main $snapshot
106  execsql {
107    SELECT * FROM t1;
108  }
109} {1 2 3 4 5 6 7 8 9 10}
110
111do_test 2.2.3 {
112  sqlite3_snapshot_free $snapshot
113  execsql COMMIT
114  execsql COMMIT db2
115  db2 close
116} {}
117
118#-------------------------------------------------------------------------
119# Check some errors in sqlite3_snapshot_open(). It is an error if:
120#
121#   1) the db is in auto-commit mode,
122#   2) the db has an open (read or write) transaction,
123#   3) the db is not a wal database,
124#
125# Reuse the database created by earlier tests.
126#
127do_execsql_test 3.0.0 {
128  CREATE TABLE t2(x, y);
129  INSERT INTO t2 VALUES('a', 'b');
130  INSERT INTO t2 VALUES('c', 'd');
131  BEGIN;
132    SELECT * FROM t2;
133} {a b c d}
134do_test 3.0.1 {
135  set snapshot [sqlite3_snapshot_get db main]
136  execsql { COMMIT }
137  execsql { INSERT INTO t2 VALUES('e', 'f'); }
138} {}
139
140do_test 3.1 {
141  list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
142} {1 SQLITE_ERROR}
143
144do_test 3.2.1 {
145  execsql {
146    BEGIN;
147      SELECT * FROM t2;
148  }
149} {a b c d e f}
150do_test 3.2.2 {
151  list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
152} {1 SQLITE_ERROR}
153
154do_test 3.2.3 {
155  execsql {
156    COMMIT;
157    BEGIN;
158      INSERT INTO t2 VALUES('g', 'h');
159  }
160  list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
161} {1 SQLITE_ERROR}
162do_execsql_test 3.2.4 COMMIT
163
164do_test 3.3.1 {
165  execsql { PRAGMA journal_mode = DELETE }
166  execsql { BEGIN }
167  list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
168} {1 SQLITE_ERROR}
169
170do_test 3.3.2 {
171  sqlite3_snapshot_free $snapshot
172  execsql COMMIT
173} {}
174
175#-------------------------------------------------------------------------
176# Check that SQLITE_BUSY_SNAPSHOT is returned if the specified snapshot
177# no longer exists because the wal file has been checkpointed.
178#
179#   1. Reading a snapshot from the middle of a wal file is not possible
180#      after the wal file has been checkpointed.
181#
182#   2. That a snapshot from the end of a wal file can not be read once
183#      the wal file has been wrapped.
184#
185do_execsql_test 4.1.0 {
186  PRAGMA journal_mode = wal;
187  CREATE TABLE t3(i, j);
188  INSERT INTO t3 VALUES('o', 't');
189  INSERT INTO t3 VALUES('t', 'f');
190  BEGIN;
191    SELECT * FROM t3;
192} {wal o t t f}
193
194do_test 4.1.1 {
195  set snapshot [sqlite3_snapshot_get db main]
196  execsql COMMIT
197} {}
198do_test 4.1.2 {
199  execsql {
200    INSERT INTO t3 VALUES('f', 's');
201    BEGIN;
202  }
203  sqlite3_snapshot_open db main $snapshot
204  execsql { SELECT * FROM t3 }
205} {o t t f}
206
207do_test 4.1.3 {
208  execsql {
209    COMMIT;
210    PRAGMA wal_checkpoint;
211    BEGIN;
212  }
213  list [catch {sqlite3_snapshot_open db main $snapshot} msg] $msg
214} {1 SQLITE_BUSY_SNAPSHOT}
215do_test 4.1.4 {
216  sqlite3_snapshot_free $snapshot
217  execsql COMMIT
218} {}
219
220do_test 4.2.1 {
221  execsql {
222    INSERT INTO t3 VALUES('s', 'e');
223    INSERT INTO t3 VALUES('n', 't');
224    BEGIN;
225      SELECT * FROM t3;
226  }
227} {o t t f f s s e n t}
228do_test 4.2.2 {
229  set snapshot [sqlite3_snapshot_get db main]
230  execsql {
231    COMMIT;
232    PRAGMA wal_checkpoint;
233    BEGIN;
234  }
235  sqlite3_snapshot_open db main $snapshot
236  execsql { SELECT * FROM t3 }
237} {o t t f f s s e n t}
238do_test 4.2.3 {
239  execsql {
240    COMMIT;
241    INSERT INTO t3 VALUES('e', 't');
242    BEGIN;
243  }
244  list [catch {sqlite3_snapshot_open db main $snapshot} msg] $msg
245} {1 SQLITE_BUSY_SNAPSHOT}
246do_test 4.2.4 {
247  sqlite3_snapshot_free $snapshot
248} {}
249
250finish_test
251
252