193006cddSdan# 2016 November 18 293006cddSdan# 393006cddSdan# The author disclaims copyright to this source code. In place of 493006cddSdan# a legal notice, here is a blessing: 593006cddSdan# 693006cddSdan# May you do good and not evil. 793006cddSdan# May you find forgiveness for yourself and forgive others. 893006cddSdan# May you share freely, never taking more than you give. 993006cddSdan# 1093006cddSdan#*********************************************************************** 1193006cddSdan# This file implements regression tests for SQLite library. The focus 1293006cddSdan# of this file is the sqlite3_snapshot_xxx() APIs. 1393006cddSdan# 1493006cddSdan 1593006cddSdanset testdir [file dirname $argv0] 1693006cddSdansource $testdir/tester.tcl 1793006cddSdanifcapable !snapshot {finish_test; return} 1893006cddSdanset testprefix snapshot2 1993006cddSdan 2093006cddSdan# This test does not work with the inmemory_journal permutation. The reason 2193006cddSdan# is that each connection opened as part of this permutation executes 2293006cddSdan# "PRAGMA journal_mode=memory", which fails if the database is in wal mode 2393006cddSdan# and there are one or more existing connections. 2493006cddSdanif {[permutation]=="inmemory_journal"} { 2593006cddSdan finish_test 2693006cddSdan return 2793006cddSdan} 2893006cddSdan 2993006cddSdan#------------------------------------------------------------------------- 3093006cddSdan# Check that it is not possible to obtain a snapshot immediately after 3193006cddSdan# a wal mode database with an empty wal file is opened. But it is after 3293006cddSdan# the file has been written, even by some other connection. 3393006cddSdan# 3493006cddSdando_execsql_test 1.0 { 3593006cddSdan PRAGMA journal_mode = wal; 3693006cddSdan CREATE TABLE t1(a, b, c); 3793006cddSdan INSERT INTO t1 VALUES(1, 2, 3); 3893006cddSdan INSERT INTO t1 VALUES(4, 5, 6); 3993006cddSdan} {wal} 4093006cddSdan 4193006cddSdandb close 4293006cddSdando_test 1.1.1 { list [file exists test.db] [file exists test.db-wal] } {1 0} 4393006cddSdan 4493006cddSdansqlite3 db test.db 4593006cddSdando_execsql_test 1.1.2 { SELECT * FROM t1 } {1 2 3 4 5 6} 4693006cddSdan 4793006cddSdando_test 1.1.3 { 4893006cddSdan execsql BEGIN 4993006cddSdan list [catch { sqlite3_snapshot_get_blob db main } msg] $msg 5093006cddSdan} {1 SQLITE_ERROR} 5193006cddSdanexecsql COMMIT 5293006cddSdan 5393006cddSdando_test 1.1.4 { 5493006cddSdan execsql { INSERT INTO t1 VALUES(7, 8, 9) } 5593006cddSdan execsql BEGIN 5693006cddSdan string length [sqlite3_snapshot_get_blob db main] 5793006cddSdan} 48 5893006cddSdanexecsql COMMIT 5993006cddSdan 6093006cddSdandb close 6193006cddSdando_test 1.2.1 { list [file exists test.db] [file exists test.db-wal] } {1 0} 6293006cddSdan 6393006cddSdansqlite3 db test.db 6493006cddSdando_execsql_test 1.2.2 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8 9} 6593006cddSdan 6693006cddSdando_test 1.2.3 { 6793006cddSdan execsql BEGIN 6893006cddSdan list [catch { sqlite3_snapshot_get_blob db main } msg] $msg 6993006cddSdan} {1 SQLITE_ERROR} 7093006cddSdanexecsql COMMIT 7193006cddSdan 7293006cddSdando_test 1.2.4 { 7393006cddSdan sqlite3 db2 test.db 7493006cddSdan execsql { INSERT INTO t1 VALUES(10, 11, 12) } db2 7593006cddSdan execsql BEGIN 7693006cddSdan string length [sqlite3_snapshot_get_blob db main] 7793006cddSdan} 48 7893006cddSdanexecsql COMMIT 7993006cddSdandb2 close 8093006cddSdan 811158498dSdan#------------------------------------------------------------------------- 825b4009f6Sdan# Simple tests for sqlite3_snapshot_recover(). 831158498dSdan# 841158498dSdanreset_db 851158498dSdando_execsql_test 2.0 { 861158498dSdan CREATE TABLE t1(x); 871158498dSdan PRAGMA journal_mode = wal; 881158498dSdan INSERT INTO t1 VALUES(1); 891158498dSdan INSERT INTO t1 VALUES(2); 901158498dSdan} {wal} 911158498dSdan 921158498dSdando_test 2.1 { 931158498dSdan db trans { set snap [sqlite3_snapshot_get_blob db main] } 941158498dSdan sqlite3_db_config db NO_CKPT_ON_CLOSE 1 951158498dSdan db close 961158498dSdan sqlite3 db test.db 971158498dSdan 981158498dSdan execsql {SELECT * FROM sqlite_master} 991158498dSdan execsql BEGIN 1001158498dSdan sqlite3_snapshot_open_blob db main $snap 1011158498dSdan execsql COMMIT; 1021158498dSdan execsql { INSERT INTO t1 VALUES(3); } 1031158498dSdan} {} 1041158498dSdan 1051158498dSdando_test 2.2 { 1061158498dSdan sqlite3_db_config db NO_CKPT_ON_CLOSE 1 1071158498dSdan db close 1081158498dSdan sqlite3 db test.db 1091158498dSdan 1101158498dSdan execsql {SELECT * FROM sqlite_master} 1111158498dSdan execsql BEGIN 1121158498dSdan list [catch { sqlite3_snapshot_open_blob db main $snap } msg] $msg 113*8d4b7a3fSdan} {1 SQLITE_ERROR_SNAPSHOT} 1141158498dSdan 1151158498dSdando_test 2.3 { 1161158498dSdan execsql COMMIT 1171158498dSdan sqlite3_snapshot_recover db main 1181158498dSdan execsql BEGIN 1191158498dSdan sqlite3_snapshot_open_blob db main $snap 1201158498dSdan execsql { SELECT * FROM t1 } 1211158498dSdan} {1 2} 1221158498dSdan 1231158498dSdando_test 2.4 { 1241158498dSdan execsql COMMIT 1251158498dSdan execsql { SELECT * FROM t1 } 1261158498dSdan} {1 2 3} 1271158498dSdan 1281158498dSdando_test 2.5 { 1291158498dSdan execsql { PRAGMA wal_checkpoint } 1301158498dSdan sqlite3_db_config db NO_CKPT_ON_CLOSE 1 1311158498dSdan db close 1321158498dSdan sqlite3 db test.db 1331158498dSdan 1341158498dSdan sqlite3_snapshot_recover db main 1351158498dSdan execsql BEGIN 1361158498dSdan list [catch { sqlite3_snapshot_open_blob db main $snap } msg] $msg 137*8d4b7a3fSdan} {1 SQLITE_ERROR_SNAPSHOT} 1381158498dSdan 1395b4009f6Sdan#------------------------------------------------------------------------- 1405b4009f6Sdan# Check that calling sqlite3_snapshot_recover() does not confuse the 1415b4009f6Sdan# pager cache. 1425b4009f6Sdanreset_db 1435b4009f6Sdando_execsql_test 3.0 { 1445b4009f6Sdan PRAGMA journal_mode = wal; 1455b4009f6Sdan CREATE TABLE t1(x, y); 1465b4009f6Sdan INSERT INTO t1 VALUES('a', 'b'); 1475b4009f6Sdan INSERT INTO t1 VALUES('c', 'd'); 1485b4009f6Sdan} {wal} 1495b4009f6Sdando_test 3.1 { 1505b4009f6Sdan sqlite3 db2 test.db 1515b4009f6Sdan execsql { INSERT INTO t1 VALUES('e', 'f') } db2 1525b4009f6Sdan db2 close 1535b4009f6Sdan sqlite3_snapshot_recover db main 1545b4009f6Sdan} {} 1555b4009f6Sdando_execsql_test 3.2 { 1565b4009f6Sdan SELECT * FROM t1; 1575b4009f6Sdan} {a b c d e f} 15893006cddSdan 1594d4757fcSdan#------------------------------------------------------------------------- 1604d4757fcSdan# Check that sqlite3_snapshot_recover() returns an error if it is called 1614d4757fcSdan# with an open read-transaction. Or on a database that does not exist. Or 1624d4757fcSdan# on the temp database. Or on a db that is not in wal mode. 1634d4757fcSdan# 1644d4757fcSdando_test 4.1 { 1654d4757fcSdan sqlite3_snapshot_recover db main 1664d4757fcSdan} {} 1674d4757fcSdando_test 4.2 { 1684d4757fcSdan execsql { 1694d4757fcSdan BEGIN; 1704d4757fcSdan SELECT * FROM sqlite_master; 1714d4757fcSdan } 1724d4757fcSdan list [catch { sqlite3_snapshot_recover db main } msg] $msg 1734d4757fcSdan} {1 SQLITE_ERROR} 1744d4757fcSdando_test 4.3 { 1754d4757fcSdan execsql COMMIT 1764d4757fcSdan sqlite3_snapshot_recover db main 1774d4757fcSdan} {} 1784d4757fcSdando_test 4.4 { 1794d4757fcSdan list [catch { sqlite3_snapshot_recover db aux } msg] $msg 1804d4757fcSdan} {1 SQLITE_ERROR} 1814d4757fcSdando_test 4.5 { 1824d4757fcSdan forcedelete test.db2 1834d4757fcSdan execsql { 1844d4757fcSdan ATTACH 'test.db2' AS aux; 1854d4757fcSdan PRAGMA aux.journal_mode = wal; 1864d4757fcSdan CREATE TABLE aux.t2(x, y); 1874d4757fcSdan } 1884d4757fcSdan list [catch { sqlite3_snapshot_recover db aux } msg] $msg 1894d4757fcSdan} {0 {}} 1904d4757fcSdando_test 4.6 { 1914d4757fcSdan list [catch { sqlite3_snapshot_recover db temp } msg] $msg 1924d4757fcSdan} {1 SQLITE_ERROR} 1934d4757fcSdando_test 4.7 { 1944d4757fcSdan execsql { 1954d4757fcSdan PRAGMA aux.journal_mode = delete; 1964d4757fcSdan } 1974d4757fcSdan list [catch { sqlite3_snapshot_recover db aux } msg] $msg 1984d4757fcSdan} {1 SQLITE_ERROR} 1994d4757fcSdan 200b92d585cSdan#------------------------------------------------------------------------- 201b92d585cSdanreset_db 202b92d585cSdansqlite3 db2 test.db 203b92d585cSdando_execsql_test 5.0 { 204b92d585cSdan CREATE TABLE t2(x); 205b92d585cSdan PRAGMA journal_mode = wal; 206b92d585cSdan INSERT INTO t2 VALUES('abc'); 207b92d585cSdan INSERT INTO t2 VALUES('def'); 208b92d585cSdan INSERT INTO t2 VALUES('ghi'); 209b92d585cSdan} {wal} 210b92d585cSdan 211b92d585cSdando_test 5.1 { 212b92d585cSdan execsql { 213b92d585cSdan SELECT * FROM t2; 214b92d585cSdan BEGIN; 215b92d585cSdan } db2 216b92d585cSdan set snap [sqlite3_snapshot_get_blob db2 main] 217b92d585cSdan db2 eval END 218b92d585cSdan} {} 219b92d585cSdan 220b92d585cSdando_test 5.2 { 221b92d585cSdan execsql BEGIN db2 222b92d585cSdan sqlite3_snapshot_open_blob db2 main $snap 223b92d585cSdan db2 eval { SELECT * FROM t2 ; END } 224b92d585cSdan} {abc def ghi} 225b92d585cSdan 226b92d585cSdando_test 5.3 { 227b92d585cSdan execsql { PRAGMA wal_checkpoint = RESTART } 228b92d585cSdan execsql BEGIN db2 229b92d585cSdan sqlite3_snapshot_open_blob db2 main $snap 230b92d585cSdan db2 eval { SELECT * FROM t2 ; END } 231b92d585cSdan} {abc def ghi} 232b92d585cSdan 233b92d585cSdando_test 5.4 { 234b92d585cSdan execsql { INSERT INTO t2 VALUES('jkl') } 235b92d585cSdan execsql BEGIN db2 236b92d585cSdan list [catch { sqlite3_snapshot_open_blob db2 main $snap } msg] $msg 237*8d4b7a3fSdan} {1 SQLITE_ERROR_SNAPSHOT} 238b92d585cSdan 239b92d585cSdan 24093006cddSdanfinish_test 241