2017-02-04 20:33:30 +03:00
|
|
|
# 2017 February 04
|
|
|
|
#
|
|
|
|
# The author disclaims copyright to this source code. In place of
|
|
|
|
# a legal notice, here is a blessing:
|
|
|
|
#
|
|
|
|
# May you do good and not evil.
|
|
|
|
# May you find forgiveness for yourself and forgive others.
|
|
|
|
# May you share freely, never taking more than you give.
|
|
|
|
#
|
|
|
|
#***********************************************************************
|
|
|
|
#
|
|
|
|
# Tests for the sessions module. Specifically, that a changeset can
|
|
|
|
# be applied after ALTER TABLE ADD COLUMN has been used to add
|
|
|
|
# columns to tables.
|
|
|
|
#
|
|
|
|
|
|
|
|
if {![info exists testdir]} {
|
|
|
|
set testdir [file join [file dirname [info script]] .. .. test]
|
|
|
|
}
|
|
|
|
source [file join [file dirname [info script]] session_common.tcl]
|
|
|
|
source $testdir/tester.tcl
|
|
|
|
ifcapable !session {finish_test; return}
|
|
|
|
set testprefix sessionat
|
|
|
|
|
2021-10-01 23:39:50 +03:00
|
|
|
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
|
|
|
|
ifcapable !altertable {
|
|
|
|
finish_test
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-02-04 20:33:30 +03:00
|
|
|
db close
|
|
|
|
sqlite3_shutdown
|
|
|
|
test_sqlite3_log log
|
|
|
|
proc log {code msg} { lappend ::log $code $msg }
|
|
|
|
|
|
|
|
proc reset_test {} {
|
|
|
|
catch { db close }
|
|
|
|
catch { db2 close }
|
|
|
|
forcedelete test.db test.db2
|
|
|
|
sqlite3 db test.db
|
|
|
|
sqlite3 db2 test.db2
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Run all tests in this file twice. Once with "WITHOUT ROWID", and once
|
|
|
|
# with regular rowid tables.
|
|
|
|
#
|
|
|
|
# ?.1.*: Test that PK inconsistencies are detected if one or more of the PK
|
|
|
|
# columns are not present in the changeset.
|
|
|
|
#
|
|
|
|
# ?.2.*: Test that it is not possible to apply a changeset with N columns
|
|
|
|
# to a db with fewer than N columns.
|
|
|
|
#
|
|
|
|
# ?.3.*: Test some INSERT, UPDATE and DELETE operations that do not
|
|
|
|
# require conflict handling.
|
|
|
|
#
|
|
|
|
# ?.4.*: Test some INSERT, UPDATE and DELETE operations that do require
|
|
|
|
# conflict handling.
|
|
|
|
#
|
|
|
|
# ?.5.*: Test that attempting to concat two changesets with different
|
|
|
|
# numbers of columns for the same table is an error.
|
|
|
|
#
|
|
|
|
foreach {tn trailing} {
|
|
|
|
sessionat-ipk ""
|
|
|
|
sessionat-wor " WITHOUT ROWID "
|
|
|
|
} {
|
|
|
|
eval [string map [list %WR% $trailing] {
|
|
|
|
reset_test
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------
|
|
|
|
do_execsql_test $tn.1.0 {
|
|
|
|
CREATE TABLE t1(a, b, PRIMARY KEY(a)) %WR%;
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.1.1 {
|
|
|
|
CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)) %WR%;
|
|
|
|
}
|
|
|
|
do_test $tn.1.2 {
|
|
|
|
set ::log {}
|
|
|
|
do_then_apply_sql { INSERT INTO t1 VALUES('one', 'two') }
|
|
|
|
set ::log
|
|
|
|
} [list \
|
|
|
|
SQLITE_SCHEMA {sqlite3changeset_apply(): primary key mismatch for table t1}
|
|
|
|
]
|
|
|
|
do_execsql_test $tn.1.3 { SELECT * FROM t1 } {one two}
|
|
|
|
do_execsql_test -db db2 $tn.1.4 { SELECT * FROM t1 } {}
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------
|
|
|
|
do_execsql_test $tn.2.0 {
|
|
|
|
CREATE TABLE t2(x, y, z, PRIMARY KEY(x)) %WR%;
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.2.1 {
|
|
|
|
CREATE TABLE t2(x, y, PRIMARY KEY(x)) %WR%;
|
|
|
|
}
|
|
|
|
do_test $tn.2.2 {
|
|
|
|
db cache flush
|
|
|
|
set ::log {}
|
|
|
|
do_then_apply_sql { INSERT INTO t2 VALUES(1, 2, 3) }
|
|
|
|
set ::log
|
|
|
|
} [list SQLITE_SCHEMA \
|
|
|
|
{sqlite3changeset_apply(): table t2 has 2 columns, expected 3 or more}
|
|
|
|
]
|
|
|
|
do_execsql_test $tn.2.3 { SELECT * FROM t2 } {1 2 3}
|
|
|
|
do_execsql_test -db db2 $tn.2.4 { SELECT * FROM t2 } {}
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------
|
|
|
|
do_execsql_test $tn.3.0 {
|
|
|
|
CREATE TABLE t3(a, b, PRIMARY KEY(b)) %WR%;
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.3.1 {
|
|
|
|
CREATE TABLE t3(a, b, c DEFAULT 'D', PRIMARY KEY(b)) %WR%;
|
|
|
|
}
|
|
|
|
do_test $tn.3.2 {
|
2023-03-08 21:03:04 +03:00
|
|
|
do_then_apply_sql -ignorenoop {
|
2017-02-04 20:33:30 +03:00
|
|
|
INSERT INTO t3 VALUES(1, 2);
|
|
|
|
INSERT INTO t3 VALUES(3, 4);
|
|
|
|
INSERT INTO t3 VALUES(5, 6);
|
|
|
|
};
|
|
|
|
db2 eval {SELECT * FROM t3}
|
|
|
|
} {1 2 D 3 4 D 5 6 D}
|
|
|
|
do_test $tn.3.3 {
|
2023-03-08 21:03:04 +03:00
|
|
|
do_then_apply_sql -ignorenoop {
|
2017-02-04 20:33:30 +03:00
|
|
|
UPDATE t3 SET a=45 WHERE b=4;
|
|
|
|
DELETE FROM t3 WHERE a=5;
|
|
|
|
};
|
|
|
|
db2 eval {SELECT * FROM t3}
|
|
|
|
} {1 2 D 45 4 D}
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------
|
|
|
|
# 4.1: INSERT statements
|
|
|
|
# 4.2: DELETE statements
|
|
|
|
# 4.3: UPDATE statements
|
|
|
|
#
|
|
|
|
do_execsql_test $tn.4.1.0 {
|
|
|
|
CREATE TABLE t4(x INTEGER PRIMARY KEY, y) %WR%;
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.4.1.1 {
|
|
|
|
CREATE TABLE t4(x INTEGER PRIMARY KEY, y, z) %WR%;
|
|
|
|
INSERT INTO t4 VALUES(1, 2, 3);
|
|
|
|
INSERT INTO t4 VALUES(4, 5, 6);
|
|
|
|
}
|
|
|
|
do_conflict_test $tn.4.1.2 -tables t4 -sql {
|
|
|
|
INSERT INTO t4 VALUES(10, 20);
|
|
|
|
INSERT INTO t4 VALUES(4, 11);
|
|
|
|
} -conflicts {
|
|
|
|
{INSERT t4 CONFLICT {i 4 i 11} {i 4 i 5}}
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.4.1.3 {
|
|
|
|
SELECT * FROM t4 ORDER BY x
|
|
|
|
} {1 2 3 4 5 6 10 20 {}}
|
|
|
|
do_conflict_test $tn.4.1.4 -policy REPLACE -tables t4 -sql {
|
|
|
|
INSERT INTO t4 VALUES(1, 11);
|
|
|
|
} -conflicts {
|
|
|
|
{INSERT t4 CONFLICT {i 1 i 11} {i 1 i 2}}
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.4.1.5 {
|
|
|
|
SELECT * FROM t4 ORDER BY x
|
|
|
|
} {1 11 {} 4 5 6 10 20 {}}
|
|
|
|
|
|
|
|
do_execsql_test $tn.4.2.0 {
|
|
|
|
DELETE FROM t4;
|
|
|
|
INSERT INTO t4 VALUES(1, 'A');
|
|
|
|
INSERT INTO t4 VALUES(2, 'B');
|
|
|
|
INSERT INTO t4 VALUES(3, 'C');
|
|
|
|
INSERT INTO t4 VALUES(4, 'D');
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.4.2.1 {
|
|
|
|
DELETE FROM t4;
|
|
|
|
INSERT INTO t4 VALUES(1, 'A', 'a');
|
|
|
|
INSERT INTO t4 VALUES(3, 'C', 'c');
|
|
|
|
INSERT INTO t4 VALUES(4, 'E', 'd');
|
|
|
|
}
|
|
|
|
do_conflict_test $tn.4.2.2 -tables t4 -sql {
|
|
|
|
DELETE FROM t4 WHERE x=2;
|
|
|
|
DELETE FROM t4 WHERE x=4;
|
|
|
|
} -conflicts {
|
|
|
|
{DELETE t4 NOTFOUND {i 2 t B}}
|
|
|
|
{DELETE t4 DATA {i 4 t D} {i 4 t E}}
|
|
|
|
}
|
|
|
|
|
|
|
|
do_execsql_test $tn.4.3.0 {
|
|
|
|
CREATE TABLE t5(a, b, c PRIMARY KEY) %WR%;
|
|
|
|
INSERT INTO t5 VALUES(1,1,1), (2,2,2), (3,3,3), (4,4,4);
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.4.3.1 {
|
|
|
|
CREATE TABLE t5(a, b, c PRIMARY KEY, d CHECK(b!=10)) %WR%;
|
|
|
|
INSERT INTO t5 VALUES (2,2,2,2), (3,8,3,3), (4,4,4,4);
|
|
|
|
}
|
|
|
|
do_conflict_test $tn.4.3.2 -tables t5 -sql {
|
|
|
|
UPDATE t5 SET a=4 WHERE c=1;
|
|
|
|
UPDATE t5 SET b=9 WHERE c=3;
|
|
|
|
UPDATE t5 SET b=10 WHERE c=2;
|
|
|
|
} -conflicts {
|
|
|
|
{UPDATE t5 NOTFOUND {i 1 {} {} i 1} {i 4 {} {} {} {}}}
|
|
|
|
{UPDATE t5 DATA {{} {} i 3 i 3} {{} {} i 9 {} {}} {i 3 i 8 i 3}}
|
|
|
|
{UPDATE t5 CONSTRAINT {{} {} i 2 i 2} {{} {} i 10 {} {}}}
|
|
|
|
}
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------
|
|
|
|
do_execsql_test $tn.5.0 {
|
|
|
|
CREATE TABLE t6(a, b, c, PRIMARY KEY(a, b)) %WR%;
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.5.1 {
|
|
|
|
CREATE TABLE t6(a, b, c, d, e, PRIMARY KEY(a, b)) %WR%;
|
|
|
|
}
|
|
|
|
do_test $tn.5.2 {
|
|
|
|
set c1 [sql_exec_changeset db {
|
|
|
|
INSERT INTO t6 VALUES(1, 1, 1);
|
|
|
|
INSERT INTO t6 VALUES(2, 2, 2);
|
|
|
|
}]
|
|
|
|
set c2 [sql_exec_changeset db2 {
|
|
|
|
INSERT INTO t6 VALUES(3, 3, 3, 3, 3);
|
|
|
|
INSERT INTO t6 VALUES(4, 4, 4, 4, 4);
|
|
|
|
}]
|
|
|
|
list [catch { sqlite3changeset_concat $c1 $c2} msg] $msg
|
|
|
|
} {1 SQLITE_SCHEMA}
|
|
|
|
|
2017-06-17 19:39:10 +03:00
|
|
|
#-----------------------------------------------------------------------
|
|
|
|
db2 close
|
|
|
|
sqlite3 db2 test.db
|
|
|
|
do_execsql_test $tn.6.0 {
|
|
|
|
CREATE TABLE t7(a INTEGER PRIMARY KEY, b) %WR%;
|
|
|
|
INSERT INTO t7 VALUES(1, 1);
|
|
|
|
INSERT INTO t7 VALUES(2, 2);
|
|
|
|
INSERT INTO t7 VALUES(3, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
do_test $tn.6.1 {
|
|
|
|
set c1 [sql_exec_changeset db {
|
|
|
|
INSERT INTO t7 VALUES(4, 4);
|
|
|
|
DELETE FROM t7 WHERE a=1;
|
|
|
|
UPDATE t7 SET b=222 WHERE a=2;
|
|
|
|
}]
|
|
|
|
set cinv [sqlite3changeset_invert $c1]
|
|
|
|
execsql { SELECT * FROM t7 }
|
|
|
|
} {2 222 3 3 4 4}
|
|
|
|
|
|
|
|
do_execsql_test -db db2 $tn.6.2 {
|
|
|
|
ALTER TABLE t7 ADD COLUMN c DEFAULT 'ccc'
|
|
|
|
}
|
|
|
|
|
|
|
|
proc xConfict {args} { return "OMIT" }
|
|
|
|
do_test $tn.6.3 {
|
|
|
|
sqlite3changeset_apply db $cinv xConflict
|
|
|
|
execsql { SELECT * FROM t7 }
|
|
|
|
} {1 1 ccc 2 2 ccc 3 3 ccc}
|
2022-12-13 17:59:28 +03:00
|
|
|
|
|
|
|
#-----------------------------------------------------------------------
|
|
|
|
reset_test
|
|
|
|
do_execsql_test $tn.7.0 {
|
|
|
|
CREATE TABLE t8(a PRIMARY KEY, b, c);
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.7.1 {
|
|
|
|
CREATE TABLE t8(a PRIMARY KEY, b, c, d DEFAULT 'D', e DEFAULT 'E');
|
|
|
|
}
|
|
|
|
|
2023-03-08 21:03:04 +03:00
|
|
|
do_then_apply_sql -ignorenoop {
|
2022-12-13 17:59:28 +03:00
|
|
|
INSERT INTO t8 VALUES(1, 2, 3);
|
|
|
|
INSERT INTO t8 VALUES(4, 5, 6);
|
|
|
|
}
|
|
|
|
do_execsql_test $tn.7.2.1 {
|
|
|
|
SELECT * FROM t8
|
|
|
|
} {1 2 3 4 5 6}
|
|
|
|
do_execsql_test -db db2 $tn.7.2.2 {
|
|
|
|
SELECT * FROM t8
|
|
|
|
} {1 2 3 D E 4 5 6 D E}
|
|
|
|
|
2023-03-08 21:03:04 +03:00
|
|
|
do_then_apply_sql -ignorenoop {
|
2022-12-13 17:59:28 +03:00
|
|
|
UPDATE t8 SET c=45 WHERE a=4;
|
|
|
|
}
|
|
|
|
do_execsql_test $tn.7.3.1 {
|
|
|
|
SELECT * FROM t8
|
|
|
|
} {1 2 3 4 5 45}
|
|
|
|
do_execsql_test -db db2 $tn.7.3.2 {
|
|
|
|
SELECT * FROM t8
|
|
|
|
} {1 2 3 D E 4 5 45 D E}
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------
|
|
|
|
reset_test
|
|
|
|
do_execsql_test $tn.8.0 {
|
|
|
|
CREATE TABLE t9(a PRIMARY KEY, b, c, d, e, f, g, h);
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.8.1 {
|
|
|
|
CREATE TABLE t9(a PRIMARY KEY, b, c, d, e, f, g, h, i, j, k, l);
|
|
|
|
}
|
2023-03-08 21:03:04 +03:00
|
|
|
do_then_apply_sql -ignorenoop {
|
2022-12-13 17:59:28 +03:00
|
|
|
INSERT INTO t9 VALUES(1, 2, 3, 4, 5, 6, 7, 8);
|
|
|
|
}
|
|
|
|
do_then_apply_sql {
|
|
|
|
UPDATE t9 SET h=450 WHERE a=1
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.8.2 {
|
|
|
|
SELECT * FROM t9
|
|
|
|
} {1 2 3 4 5 6 7 450 {} {} {} {}}
|
2023-03-08 21:03:04 +03:00
|
|
|
do_then_apply_sql -ignorenoop {
|
2022-12-13 17:59:28 +03:00
|
|
|
UPDATE t9 SET h=NULL
|
|
|
|
}
|
|
|
|
do_execsql_test -db db2 $tn.8.2 {
|
|
|
|
SELECT * FROM t9
|
|
|
|
} {1 2 3 4 5 6 7 {} {} {} {} {}}
|
2017-02-04 20:33:30 +03:00
|
|
|
}]
|
|
|
|
}
|
|
|
|
|
2018-01-17 20:38:18 +03:00
|
|
|
catch { db close }
|
|
|
|
catch { db2 close }
|
|
|
|
sqlite3_shutdown
|
|
|
|
test_sqlite3_log
|
2017-02-04 20:33:30 +03:00
|
|
|
|
|
|
|
finish_test
|