1ff677b20Sdan# 2017 February 04 2ff677b20Sdan# 3ff677b20Sdan# The author disclaims copyright to this source code. In place of 4ff677b20Sdan# a legal notice, here is a blessing: 5ff677b20Sdan# 6ff677b20Sdan# May you do good and not evil. 7ff677b20Sdan# May you find forgiveness for yourself and forgive others. 8ff677b20Sdan# May you share freely, never taking more than you give. 9ff677b20Sdan# 10ff677b20Sdan#*********************************************************************** 11ff677b20Sdan# 12ff677b20Sdan# Tests for the sessions module. Specifically, that a changeset can 13ff677b20Sdan# be applied after ALTER TABLE ADD COLUMN has been used to add 14ff677b20Sdan# columns to tables. 15ff677b20Sdan# 16ff677b20Sdan 17ff677b20Sdanif {![info exists testdir]} { 18ff677b20Sdan set testdir [file join [file dirname [info script]] .. .. test] 19ff677b20Sdan} 20ff677b20Sdansource [file join [file dirname [info script]] session_common.tcl] 21ff677b20Sdansource $testdir/tester.tcl 22ff677b20Sdanifcapable !session {finish_test; return} 23ff677b20Sdanset testprefix sessionat 24ff677b20Sdan 25*37f3ac8fSdan# If SQLITE_OMIT_ALTERTABLE is defined, omit this file. 26*37f3ac8fSdanifcapable !altertable { 27*37f3ac8fSdan finish_test 28*37f3ac8fSdan return 29*37f3ac8fSdan} 30*37f3ac8fSdan 31ff677b20Sdandb close 32ff677b20Sdansqlite3_shutdown 33ff677b20Sdantest_sqlite3_log log 34ff677b20Sdanproc log {code msg} { lappend ::log $code $msg } 35ff677b20Sdan 36ff677b20Sdanproc reset_test {} { 37ff677b20Sdan catch { db close } 38ff677b20Sdan catch { db2 close } 39ff677b20Sdan forcedelete test.db test.db2 40ff677b20Sdan sqlite3 db test.db 41ff677b20Sdan sqlite3 db2 test.db2 42ff677b20Sdan} 43ff677b20Sdan 44ff677b20Sdan 45ff677b20Sdan# Run all tests in this file twice. Once with "WITHOUT ROWID", and once 46ff677b20Sdan# with regular rowid tables. 47ff677b20Sdan# 48ff677b20Sdan# ?.1.*: Test that PK inconsistencies are detected if one or more of the PK 49ff677b20Sdan# columns are not present in the changeset. 50ff677b20Sdan# 51ff677b20Sdan# ?.2.*: Test that it is not possible to apply a changeset with N columns 52ff677b20Sdan# to a db with fewer than N columns. 53ff677b20Sdan# 54ff677b20Sdan# ?.3.*: Test some INSERT, UPDATE and DELETE operations that do not 55ff677b20Sdan# require conflict handling. 56ff677b20Sdan# 57ff677b20Sdan# ?.4.*: Test some INSERT, UPDATE and DELETE operations that do require 58ff677b20Sdan# conflict handling. 59ff677b20Sdan# 60ff677b20Sdan# ?.5.*: Test that attempting to concat two changesets with different 61ff677b20Sdan# numbers of columns for the same table is an error. 62ff677b20Sdan# 63ff677b20Sdanforeach {tn trailing} { 64ff677b20Sdan sessionat-ipk "" 65ff677b20Sdan sessionat-wor " WITHOUT ROWID " 66ff677b20Sdan} { 67ff677b20Sdaneval [string map [list %WR% $trailing] { 68ff677b20Sdan reset_test 69ff677b20Sdan 70ff677b20Sdan #----------------------------------------------------------------------- 71ff677b20Sdan do_execsql_test $tn.1.0 { 72ff677b20Sdan CREATE TABLE t1(a, b, PRIMARY KEY(a)) %WR%; 73ff677b20Sdan } 74ff677b20Sdan do_execsql_test -db db2 $tn.1.1 { 75ff677b20Sdan CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)) %WR%; 76ff677b20Sdan } 77ff677b20Sdan do_test $tn.1.2 { 78ff677b20Sdan set ::log {} 79ff677b20Sdan do_then_apply_sql { INSERT INTO t1 VALUES('one', 'two') } 80ff677b20Sdan set ::log 81ff677b20Sdan } [list \ 82ff677b20Sdan SQLITE_SCHEMA {sqlite3changeset_apply(): primary key mismatch for table t1} 83ff677b20Sdan ] 84ff677b20Sdan do_execsql_test $tn.1.3 { SELECT * FROM t1 } {one two} 85ff677b20Sdan do_execsql_test -db db2 $tn.1.4 { SELECT * FROM t1 } {} 86ff677b20Sdan 87ff677b20Sdan #----------------------------------------------------------------------- 88ff677b20Sdan do_execsql_test $tn.2.0 { 89ff677b20Sdan CREATE TABLE t2(x, y, z, PRIMARY KEY(x)) %WR%; 90ff677b20Sdan } 91ff677b20Sdan do_execsql_test -db db2 $tn.2.1 { 92ff677b20Sdan CREATE TABLE t2(x, y, PRIMARY KEY(x)) %WR%; 93ff677b20Sdan } 94ff677b20Sdan do_test $tn.2.2 { 95ff677b20Sdan db cache flush 96ff677b20Sdan set ::log {} 97ff677b20Sdan do_then_apply_sql { INSERT INTO t2 VALUES(1, 2, 3) } 98ff677b20Sdan set ::log 99ff677b20Sdan } [list SQLITE_SCHEMA \ 100ff677b20Sdan {sqlite3changeset_apply(): table t2 has 2 columns, expected 3 or more} 101ff677b20Sdan ] 102ff677b20Sdan do_execsql_test $tn.2.3 { SELECT * FROM t2 } {1 2 3} 103ff677b20Sdan do_execsql_test -db db2 $tn.2.4 { SELECT * FROM t2 } {} 104ff677b20Sdan 105ff677b20Sdan #----------------------------------------------------------------------- 106ff677b20Sdan do_execsql_test $tn.3.0 { 107ff677b20Sdan CREATE TABLE t3(a, b, PRIMARY KEY(b)) %WR%; 108ff677b20Sdan } 109ff677b20Sdan do_execsql_test -db db2 $tn.3.1 { 110ff677b20Sdan CREATE TABLE t3(a, b, c DEFAULT 'D', PRIMARY KEY(b)) %WR%; 111ff677b20Sdan } 112ff677b20Sdan do_test $tn.3.2 { 113ff677b20Sdan do_then_apply_sql { 114ff677b20Sdan INSERT INTO t3 VALUES(1, 2); 115ff677b20Sdan INSERT INTO t3 VALUES(3, 4); 116ff677b20Sdan INSERT INTO t3 VALUES(5, 6); 117ff677b20Sdan }; 118ff677b20Sdan db2 eval {SELECT * FROM t3} 119ff677b20Sdan } {1 2 D 3 4 D 5 6 D} 120ff677b20Sdan do_test $tn.3.3 { 121ff677b20Sdan do_then_apply_sql { 122ff677b20Sdan UPDATE t3 SET a=45 WHERE b=4; 123ff677b20Sdan DELETE FROM t3 WHERE a=5; 124ff677b20Sdan }; 125ff677b20Sdan db2 eval {SELECT * FROM t3} 126ff677b20Sdan } {1 2 D 45 4 D} 127ff677b20Sdan 128ff677b20Sdan #----------------------------------------------------------------------- 129ff677b20Sdan # 4.1: INSERT statements 130ff677b20Sdan # 4.2: DELETE statements 131ff677b20Sdan # 4.3: UPDATE statements 132ff677b20Sdan # 133ff677b20Sdan do_execsql_test $tn.4.1.0 { 134ff677b20Sdan CREATE TABLE t4(x INTEGER PRIMARY KEY, y) %WR%; 135ff677b20Sdan } 136ff677b20Sdan do_execsql_test -db db2 $tn.4.1.1 { 137ff677b20Sdan CREATE TABLE t4(x INTEGER PRIMARY KEY, y, z) %WR%; 138ff677b20Sdan INSERT INTO t4 VALUES(1, 2, 3); 139ff677b20Sdan INSERT INTO t4 VALUES(4, 5, 6); 140ff677b20Sdan } 141ff677b20Sdan do_conflict_test $tn.4.1.2 -tables t4 -sql { 142ff677b20Sdan INSERT INTO t4 VALUES(10, 20); 143ff677b20Sdan INSERT INTO t4 VALUES(4, 11); 144ff677b20Sdan } -conflicts { 145ff677b20Sdan {INSERT t4 CONFLICT {i 4 i 11} {i 4 i 5}} 146ff677b20Sdan } 147ff677b20Sdan do_execsql_test -db db2 $tn.4.1.3 { 148ff677b20Sdan SELECT * FROM t4 ORDER BY x 149ff677b20Sdan } {1 2 3 4 5 6 10 20 {}} 150ff677b20Sdan do_conflict_test $tn.4.1.4 -policy REPLACE -tables t4 -sql { 151ff677b20Sdan INSERT INTO t4 VALUES(1, 11); 152ff677b20Sdan } -conflicts { 153ff677b20Sdan {INSERT t4 CONFLICT {i 1 i 11} {i 1 i 2}} 154ff677b20Sdan } 155ff677b20Sdan do_execsql_test -db db2 $tn.4.1.5 { 156ff677b20Sdan SELECT * FROM t4 ORDER BY x 157ff677b20Sdan } {1 11 {} 4 5 6 10 20 {}} 158ff677b20Sdan 159ff677b20Sdan do_execsql_test $tn.4.2.0 { 160ff677b20Sdan DELETE FROM t4; 161ff677b20Sdan INSERT INTO t4 VALUES(1, 'A'); 162ff677b20Sdan INSERT INTO t4 VALUES(2, 'B'); 163ff677b20Sdan INSERT INTO t4 VALUES(3, 'C'); 164ff677b20Sdan INSERT INTO t4 VALUES(4, 'D'); 165ff677b20Sdan } 166ff677b20Sdan do_execsql_test -db db2 $tn.4.2.1 { 167ff677b20Sdan DELETE FROM t4; 168ff677b20Sdan INSERT INTO t4 VALUES(1, 'A', 'a'); 169ff677b20Sdan INSERT INTO t4 VALUES(3, 'C', 'c'); 170ff677b20Sdan INSERT INTO t4 VALUES(4, 'E', 'd'); 171ff677b20Sdan } 172ff677b20Sdan do_conflict_test $tn.4.2.2 -tables t4 -sql { 173ff677b20Sdan DELETE FROM t4 WHERE x=2; 174ff677b20Sdan DELETE FROM t4 WHERE x=4; 175ff677b20Sdan } -conflicts { 176ff677b20Sdan {DELETE t4 NOTFOUND {i 2 t B}} 177ff677b20Sdan {DELETE t4 DATA {i 4 t D} {i 4 t E}} 178ff677b20Sdan } 179ff677b20Sdan 180ff677b20Sdan do_execsql_test $tn.4.3.0 { 181ff677b20Sdan CREATE TABLE t5(a, b, c PRIMARY KEY) %WR%; 182ff677b20Sdan INSERT INTO t5 VALUES(1,1,1), (2,2,2), (3,3,3), (4,4,4); 183ff677b20Sdan } 184ff677b20Sdan do_execsql_test -db db2 $tn.4.3.1 { 185ff677b20Sdan CREATE TABLE t5(a, b, c PRIMARY KEY, d CHECK(b!=10)) %WR%; 186ff677b20Sdan INSERT INTO t5 VALUES (2,2,2,2), (3,8,3,3), (4,4,4,4); 187ff677b20Sdan } 188ff677b20Sdan do_conflict_test $tn.4.3.2 -tables t5 -sql { 189ff677b20Sdan UPDATE t5 SET a=4 WHERE c=1; 190ff677b20Sdan UPDATE t5 SET b=9 WHERE c=3; 191ff677b20Sdan UPDATE t5 SET b=10 WHERE c=2; 192ff677b20Sdan } -conflicts { 193ff677b20Sdan {UPDATE t5 NOTFOUND {i 1 {} {} i 1} {i 4 {} {} {} {}}} 194ff677b20Sdan {UPDATE t5 DATA {{} {} i 3 i 3} {{} {} i 9 {} {}} {i 3 i 8 i 3}} 195ff677b20Sdan {UPDATE t5 CONSTRAINT {{} {} i 2 i 2} {{} {} i 10 {} {}}} 196ff677b20Sdan } 197ff677b20Sdan 198ff677b20Sdan #----------------------------------------------------------------------- 199ff677b20Sdan do_execsql_test $tn.5.0 { 200ff677b20Sdan CREATE TABLE t6(a, b, c, PRIMARY KEY(a, b)) %WR%; 201ff677b20Sdan } 202ff677b20Sdan do_execsql_test -db db2 $tn.5.1 { 203ff677b20Sdan CREATE TABLE t6(a, b, c, d, e, PRIMARY KEY(a, b)) %WR%; 204ff677b20Sdan } 205ff677b20Sdan do_test $tn.5.2 { 206ff677b20Sdan set c1 [sql_exec_changeset db { 207ff677b20Sdan INSERT INTO t6 VALUES(1, 1, 1); 208ff677b20Sdan INSERT INTO t6 VALUES(2, 2, 2); 209ff677b20Sdan }] 210ff677b20Sdan set c2 [sql_exec_changeset db2 { 211ff677b20Sdan INSERT INTO t6 VALUES(3, 3, 3, 3, 3); 212ff677b20Sdan INSERT INTO t6 VALUES(4, 4, 4, 4, 4); 213ff677b20Sdan }] 214ff677b20Sdan list [catch { sqlite3changeset_concat $c1 $c2} msg] $msg 215ff677b20Sdan } {1 SQLITE_SCHEMA} 216ff677b20Sdan 217f417f28bSdan #----------------------------------------------------------------------- 218f417f28bSdan db2 close 219f417f28bSdan sqlite3 db2 test.db 220f417f28bSdan do_execsql_test $tn.6.0 { 221f417f28bSdan CREATE TABLE t7(a INTEGER PRIMARY KEY, b) %WR%; 222f417f28bSdan INSERT INTO t7 VALUES(1, 1); 223f417f28bSdan INSERT INTO t7 VALUES(2, 2); 224f417f28bSdan INSERT INTO t7 VALUES(3, 3); 225f417f28bSdan } 226f417f28bSdan 227f417f28bSdan do_test $tn.6.1 { 228f417f28bSdan set c1 [sql_exec_changeset db { 229f417f28bSdan INSERT INTO t7 VALUES(4, 4); 230f417f28bSdan DELETE FROM t7 WHERE a=1; 231f417f28bSdan UPDATE t7 SET b=222 WHERE a=2; 232f417f28bSdan }] 233f417f28bSdan set cinv [sqlite3changeset_invert $c1] 234f417f28bSdan execsql { SELECT * FROM t7 } 235f417f28bSdan } {2 222 3 3 4 4} 236f417f28bSdan 237f417f28bSdan do_execsql_test -db db2 $tn.6.2 { 238f417f28bSdan ALTER TABLE t7 ADD COLUMN c DEFAULT 'ccc' 239f417f28bSdan } 240f417f28bSdan 241f417f28bSdan proc xConfict {args} { return "OMIT" } 242f417f28bSdan do_test $tn.6.3 { 243f417f28bSdan sqlite3changeset_apply db $cinv xConflict 244f417f28bSdan execsql { SELECT * FROM t7 } 245f417f28bSdan } {1 1 ccc 2 2 ccc 3 3 ccc} 246ff677b20Sdan}] 247ff677b20Sdan} 248ff677b20Sdan 24961c758b5Sdancatch { db close } 25061c758b5Sdancatch { db2 close } 25161c758b5Sdansqlite3_shutdown 25261c758b5Sdantest_sqlite3_log 253ff677b20Sdan 254ff677b20Sdanfinish_test 255