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