1# 2016 November 18 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 focus 12# of this file is the sqlite3_snapshot_xxx() APIs. 13# 14 15set testdir [file dirname $argv0] 16source $testdir/tester.tcl 17ifcapable !snapshot {finish_test; return} 18set testprefix snapshot2 19 20# This test does not work with the inmemory_journal permutation. The reason 21# is that each connection opened as part of this permutation executes 22# "PRAGMA journal_mode=memory", which fails if the database is in wal mode 23# and there are one or more existing connections. 24if {[permutation]=="inmemory_journal"} { 25 finish_test 26 return 27} 28 29#------------------------------------------------------------------------- 30# Check that it is not possible to obtain a snapshot immediately after 31# a wal mode database with an empty wal file is opened. But it is after 32# the file has been written, even by some other connection. 33# 34do_execsql_test 1.0 { 35 PRAGMA journal_mode = wal; 36 CREATE TABLE t1(a, b, c); 37 INSERT INTO t1 VALUES(1, 2, 3); 38 INSERT INTO t1 VALUES(4, 5, 6); 39} {wal} 40 41db close 42do_test 1.1.1 { list [file exists test.db] [file exists test.db-wal] } {1 0} 43 44sqlite3 db test.db 45do_execsql_test 1.1.2 { SELECT * FROM t1 } {1 2 3 4 5 6} 46 47do_test 1.1.3 { 48 execsql BEGIN 49 list [catch { sqlite3_snapshot_get_blob db main } msg] $msg 50} {1 SQLITE_ERROR} 51execsql COMMIT 52 53do_test 1.1.4 { 54 execsql { INSERT INTO t1 VALUES(7, 8, 9) } 55 execsql BEGIN 56 string length [sqlite3_snapshot_get_blob db main] 57} 48 58execsql COMMIT 59 60db close 61do_test 1.2.1 { list [file exists test.db] [file exists test.db-wal] } {1 0} 62 63sqlite3 db test.db 64do_execsql_test 1.2.2 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8 9} 65 66do_test 1.2.3 { 67 execsql BEGIN 68 list [catch { sqlite3_snapshot_get_blob db main } msg] $msg 69} {1 SQLITE_ERROR} 70execsql COMMIT 71 72do_test 1.2.4 { 73 sqlite3 db2 test.db 74 execsql { INSERT INTO t1 VALUES(10, 11, 12) } db2 75 execsql BEGIN 76 string length [sqlite3_snapshot_get_blob db main] 77} 48 78execsql COMMIT 79db2 close 80 81#------------------------------------------------------------------------- 82# Simple tests for sqlite3_snapshot_recover(). 83# 84reset_db 85do_execsql_test 2.0 { 86 CREATE TABLE t1(x); 87 PRAGMA journal_mode = wal; 88 INSERT INTO t1 VALUES(1); 89 INSERT INTO t1 VALUES(2); 90} {wal} 91 92do_test 2.1 { 93 db trans { set snap [sqlite3_snapshot_get_blob db main] } 94 sqlite3_db_config db NO_CKPT_ON_CLOSE 1 95 db close 96 sqlite3 db test.db 97 98 execsql {SELECT * FROM sqlite_master} 99 execsql BEGIN 100 sqlite3_snapshot_open_blob db main $snap 101 execsql COMMIT; 102 execsql { INSERT INTO t1 VALUES(3); } 103} {} 104 105do_test 2.2 { 106 sqlite3_db_config db NO_CKPT_ON_CLOSE 1 107 db close 108 sqlite3 db test.db 109 110 execsql {SELECT * FROM sqlite_master} 111 execsql BEGIN 112 list [catch { sqlite3_snapshot_open_blob db main $snap } msg] $msg 113} {1 SQLITE_ERROR_SNAPSHOT} 114 115do_test 2.3 { 116 execsql COMMIT 117 sqlite3_snapshot_recover db main 118 execsql BEGIN 119 sqlite3_snapshot_open_blob db main $snap 120 execsql { SELECT * FROM t1 } 121} {1 2} 122 123do_test 2.4 { 124 execsql COMMIT 125 execsql { SELECT * FROM t1 } 126} {1 2 3} 127 128do_test 2.5 { 129 execsql { PRAGMA wal_checkpoint } 130 sqlite3_db_config db NO_CKPT_ON_CLOSE 1 131 db close 132 sqlite3 db test.db 133 134 sqlite3_snapshot_recover db main 135 execsql BEGIN 136 list [catch { sqlite3_snapshot_open_blob db main $snap } msg] $msg 137} {1 SQLITE_ERROR_SNAPSHOT} 138 139#------------------------------------------------------------------------- 140# Check that calling sqlite3_snapshot_recover() does not confuse the 141# pager cache. 142reset_db 143do_execsql_test 3.0 { 144 PRAGMA journal_mode = wal; 145 CREATE TABLE t1(x, y); 146 INSERT INTO t1 VALUES('a', 'b'); 147 INSERT INTO t1 VALUES('c', 'd'); 148} {wal} 149do_test 3.1 { 150 sqlite3 db2 test.db 151 execsql { INSERT INTO t1 VALUES('e', 'f') } db2 152 db2 close 153 sqlite3_snapshot_recover db main 154} {} 155do_execsql_test 3.2 { 156 SELECT * FROM t1; 157} {a b c d e f} 158 159#------------------------------------------------------------------------- 160# Check that sqlite3_snapshot_recover() returns an error if it is called 161# with an open read-transaction. Or on a database that does not exist. Or 162# on the temp database. Or on a db that is not in wal mode. 163# 164do_test 4.1 { 165 sqlite3_snapshot_recover db main 166} {} 167do_test 4.2 { 168 execsql { 169 BEGIN; 170 SELECT * FROM sqlite_master; 171 } 172 list [catch { sqlite3_snapshot_recover db main } msg] $msg 173} {1 SQLITE_ERROR} 174do_test 4.3 { 175 execsql COMMIT 176 sqlite3_snapshot_recover db main 177} {} 178do_test 4.4 { 179 list [catch { sqlite3_snapshot_recover db aux } msg] $msg 180} {1 SQLITE_ERROR} 181do_test 4.5 { 182 forcedelete test.db2 183 execsql { 184 ATTACH 'test.db2' AS aux; 185 PRAGMA aux.journal_mode = wal; 186 CREATE TABLE aux.t2(x, y); 187 } 188 list [catch { sqlite3_snapshot_recover db aux } msg] $msg 189} {0 {}} 190do_test 4.6 { 191 list [catch { sqlite3_snapshot_recover db temp } msg] $msg 192} {1 SQLITE_ERROR} 193do_test 4.7 { 194 execsql { 195 PRAGMA aux.journal_mode = delete; 196 } 197 list [catch { sqlite3_snapshot_recover db aux } msg] $msg 198} {1 SQLITE_ERROR} 199 200#------------------------------------------------------------------------- 201reset_db 202sqlite3 db2 test.db 203do_execsql_test 5.0 { 204 CREATE TABLE t2(x); 205 PRAGMA journal_mode = wal; 206 INSERT INTO t2 VALUES('abc'); 207 INSERT INTO t2 VALUES('def'); 208 INSERT INTO t2 VALUES('ghi'); 209} {wal} 210 211do_test 5.1 { 212 execsql { 213 SELECT * FROM t2; 214 BEGIN; 215 } db2 216 set snap [sqlite3_snapshot_get_blob db2 main] 217 db2 eval END 218} {} 219 220do_test 5.2 { 221 execsql BEGIN db2 222 sqlite3_snapshot_open_blob db2 main $snap 223 db2 eval { SELECT * FROM t2 ; END } 224} {abc def ghi} 225 226do_test 5.3 { 227 execsql { PRAGMA wal_checkpoint = RESTART } 228 execsql BEGIN db2 229 sqlite3_snapshot_open_blob db2 main $snap 230 db2 eval { SELECT * FROM t2 ; END } 231} {abc def ghi} 232 233do_test 5.4 { 234 execsql { INSERT INTO t2 VALUES('jkl') } 235 execsql BEGIN db2 236 list [catch { sqlite3_snapshot_open_blob db2 main $snap } msg] $msg 237} {1 SQLITE_ERROR_SNAPSHOT} 238 239 240finish_test 241