1d9151526Sdan# 2016 March 30 2d9151526Sdan# 3d9151526Sdan# The author disclaims copyright to this source code. In place of 4d9151526Sdan# a legal notice, here is a blessing: 5d9151526Sdan# 6d9151526Sdan# May you do good and not evil. 7d9151526Sdan# May you find forgiveness for yourself and forgive others. 8d9151526Sdan# May you share freely, never taking more than you give. 9d9151526Sdan# 10d9151526Sdan#*********************************************************************** 11d9151526Sdan# 12d9151526Sdan# This file implements regression tests for the sessions module. 13d9151526Sdan# Specifically, it tests that UNIQUE constraints are dealt with correctly. 14d9151526Sdan# 15d9151526Sdan 16d9151526Sdan 17d9151526Sdan 18d9151526Sdanif {![info exists testdir]} { 19d9151526Sdan set testdir [file join [file dirname [info script]] .. .. test] 20d9151526Sdan} 21d9151526Sdansource [file join [file dirname [info script]] session_common.tcl] 22d9151526Sdansource $testdir/tester.tcl 23d9151526Sdanifcapable !session {finish_test; return} 24d9151526Sdanset testprefix sessionG 25d9151526Sdan 26d9151526Sdan 27d9151526Sdanforcedelete test.db2 28d9151526Sdansqlite3 db2 test.db2 29d9151526Sdan 30d9151526Sdando_test 1.0 { 31d9151526Sdan do_common_sql { 32d9151526Sdan CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); 33d9151526Sdan INSERT INTO t1 VALUES(1, 'one'); 34d9151526Sdan INSERT INTO t1 VALUES(2, 'two'); 35d9151526Sdan INSERT INTO t1 VALUES(3, 'three'); 36d9151526Sdan } 37d9151526Sdan do_then_apply_sql { 38d9151526Sdan DELETE FROM t1 WHERE a=1; 39d9151526Sdan INSERT INTO t1 VALUES(4, 'one'); 40d9151526Sdan } 41d9151526Sdan compare_db db db2 42d9151526Sdan} {} 43d9151526Sdan 44d9151526Sdando_test 1.1 { 45d9151526Sdan do_then_apply_sql { 46d9151526Sdan DELETE FROM t1 WHERE a=4; 47d9151526Sdan INSERT INTO t1 VALUES(1, 'one'); 48d9151526Sdan } 49d9151526Sdan compare_db db db2 50d9151526Sdan} {} 51d9151526Sdan 52d9151526Sdando_test 1.2 { 53d9151526Sdan execsql { INSERT INTO t1 VALUES(5, 'five') } db2 54d9151526Sdan do_then_apply_sql { 55d9151526Sdan INSERT INTO t1 VALUES(11, 'eleven'); 56d9151526Sdan INSERT INTO t1 VALUES(12, 'five'); 57d9151526Sdan } 58d9151526Sdan execsql { SELECT * FROM t1 } db2 59d9151526Sdan} {2 two 3 three 1 one 5 five 11 eleven} 60d9151526Sdan 61d9151526Sdando_test 1.3 { 62d9151526Sdan execsql { SELECT * FROM t1 } 63d9151526Sdan} {2 two 3 three 1 one 11 eleven 12 five} 64d9151526Sdan 655f5663dcSdan#------------------------------------------------------------------------- 665f5663dcSdan# 675f5663dcSdanreset_db 685f5663dcSdandb2 close 695f5663dcSdanforcedelete test.db2 705f5663dcSdansqlite3 db2 test.db2 715f5663dcSdan 725f5663dcSdando_test 2.1 { 735f5663dcSdan do_common_sql { 745f5663dcSdan CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c UNIQUE); 755f5663dcSdan INSERT INTO t1 VALUES(1, 1, 1); 765f5663dcSdan INSERT INTO t1 VALUES(2, 2, 2); 775f5663dcSdan INSERT INTO t1 VALUES(3, 3, 3); 785f5663dcSdan } 795f5663dcSdan} {} 805f5663dcSdan 815f5663dcSdando_test 2.2.1 { 825f5663dcSdan # It is not possible to apply the changeset generated by the following 835f5663dcSdan # SQL, as none of the three updated rows may be updated as part of the 845f5663dcSdan # first pass. 855f5663dcSdan do_then_apply_sql { 865f5663dcSdan UPDATE t1 SET b=0 WHERE a=1; 875f5663dcSdan UPDATE t1 SET b=1 WHERE a=2; 885f5663dcSdan UPDATE t1 SET b=2 WHERE a=3; 895f5663dcSdan UPDATE t1 SET b=3 WHERE a=1; 905f5663dcSdan } 915f5663dcSdan db2 eval { SELECT a, b FROM t1 } 925f5663dcSdan} {1 1 2 2 3 3} 935f5663dcSdando_test 2.2.2 { db eval { SELECT a, b FROM t1 } } {1 3 2 1 3 2} 945f5663dcSdan 955f5663dcSdan#------------------------------------------------------------------------- 965f5663dcSdan# 975f5663dcSdanreset_db 985f5663dcSdandb2 close 995f5663dcSdanforcedelete test.db2 1005f5663dcSdansqlite3 db2 test.db2 1015f5663dcSdan 1025f5663dcSdando_test 3.1 { 1035f5663dcSdan do_common_sql { 1045f5663dcSdan CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c UNIQUE); 1055f5663dcSdan INSERT INTO t1 VALUES(1, 1, 1); 1065f5663dcSdan INSERT INTO t1 VALUES(2, 2, 2); 1075f5663dcSdan INSERT INTO t1 VALUES(3, 3, 3); 1085f5663dcSdan } 1095f5663dcSdan} {} 1105f5663dcSdan 1115f5663dcSdando_test 3.3 { 1125f5663dcSdan do_then_apply_sql { 1135f5663dcSdan UPDATE t1 SET b=4 WHERE a=3; 1145f5663dcSdan UPDATE t1 SET b=3 WHERE a=2; 1155f5663dcSdan UPDATE t1 SET b=2 WHERE a=1; 1165f5663dcSdan } 1175f5663dcSdan compare_db db db2 1185f5663dcSdan} {} 1195f5663dcSdan 1205f5663dcSdando_test 3.4 { 1215f5663dcSdan do_then_apply_sql { 1225f5663dcSdan UPDATE t1 SET b=1 WHERE a=1; 1235f5663dcSdan UPDATE t1 SET b=2 WHERE a=2; 1245f5663dcSdan UPDATE t1 SET b=3 WHERE a=3; 1255f5663dcSdan } 1265f5663dcSdan compare_db db db2 1275f5663dcSdan} {} 1285f5663dcSdan 1295f5663dcSdan#------------------------------------------------------------------------- 1305f5663dcSdan# 1315f5663dcSdanreset_db 1325f5663dcSdandb2 close 1335f5663dcSdanforcedelete test.db2 1345f5663dcSdansqlite3 db2 test.db2 1355f5663dcSdan 1365f5663dcSdando_test 4.1 { 1375f5663dcSdan do_common_sql { 1385f5663dcSdan CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); 1395f5663dcSdan INSERT INTO t1 VALUES(1, 1); 1405f5663dcSdan INSERT INTO t1 VALUES(2, 2); 1415f5663dcSdan INSERT INTO t1 VALUES(3, 3); 1425f5663dcSdan 1435f5663dcSdan CREATE TABLE t2(a PRIMARY KEY, b UNIQUE); 1445f5663dcSdan INSERT INTO t2 VALUES(1, 1); 1455f5663dcSdan INSERT INTO t2 VALUES(2, 2); 1465f5663dcSdan INSERT INTO t2 VALUES(3, 3); 1475f5663dcSdan } 1485f5663dcSdan} {} 1495f5663dcSdan 1505f5663dcSdando_test 4.2 { 1515f5663dcSdan do_then_apply_sql { 1525f5663dcSdan UPDATE t1 SET b=4 WHERE a=3; 1535f5663dcSdan UPDATE t1 SET b=3 WHERE a=2; 1545f5663dcSdan UPDATE t1 SET b=2 WHERE a=1; 1555f5663dcSdan 1565f5663dcSdan UPDATE t2 SET b=0 WHERE a=1; 1575f5663dcSdan UPDATE t2 SET b=1 WHERE a=2; 1585f5663dcSdan UPDATE t2 SET b=2 WHERE a=3; 1595f5663dcSdan } 1605f5663dcSdan compare_db db db2 1615f5663dcSdan} {} 1625f5663dcSdan 1635f5663dcSdando_test 4.3 { 1645f5663dcSdan do_then_apply_sql { 1655f5663dcSdan UPDATE t1 SET b=1 WHERE a=1; 1665f5663dcSdan UPDATE t1 SET b=2 WHERE a=2; 1675f5663dcSdan UPDATE t1 SET b=3 WHERE a=3; 1685f5663dcSdan 1695f5663dcSdan UPDATE t2 SET b=3 WHERE a=3; 1705f5663dcSdan UPDATE t2 SET b=2 WHERE a=2; 1715f5663dcSdan UPDATE t2 SET b=1 WHERE a=1; 1725f5663dcSdan } 1735f5663dcSdan compare_db db db2 1745f5663dcSdan} {} 1755f5663dcSdan 176f225059bSdan#------------------------------------------------------------------------- 177f225059bSdanreset_db 178f225059bSdancatch { db2 close } 179f225059bSdanforcedelete test.db2 180f225059bSdansqlite3 db2 test.db2 181f225059bSdan 182f225059bSdando_execsql_test 5.0.1 { 183f225059bSdan CREATE TABLE t1(a PRIMARY KEY, b, c); 184f225059bSdan CREATE TABLE t2(a, b, c PRIMARY KEY); 185f225059bSdan CREATE TABLE t3(a, b PRIMARY KEY, c); 186f225059bSdan} 187f225059bSdando_execsql_test -db db2 5.0.2 { 188f225059bSdan CREATE TABLE t1(a PRIMARY KEY, b, c); 189f225059bSdan CREATE TABLE t2(a, b, c); 190f225059bSdan CREATE TABLE t3(a, b PRIMARY KEY, c); 191f225059bSdan} 192f225059bSdan 193f225059bSdando_test 5.1 { 194f225059bSdan do_then_apply_sql { 195f225059bSdan INSERT INTO t1 VALUES(1, 2, 3); 196f225059bSdan INSERT INTO t2 VALUES(4, 5, 6); 197f225059bSdan INSERT INTO t3 VALUES(7, 8, 9); 198f225059bSdan } 199f225059bSdan 200f225059bSdan db2 eval { 201f225059bSdan SELECT * FROM t1; 202f225059bSdan SELECT * FROM t2; 203f225059bSdan SELECT * FROM t3; 204f225059bSdan } 205f225059bSdan} {1 2 3 7 8 9} 206f225059bSdan 207*3e259bcdSdan#------------------------------------------------------------------------- 208f225059bSdan 209*3e259bcdSdanreset_db 210*3e259bcdSdandb func number_name number_name 211*3e259bcdSdando_execsql_test 6.0 { 212*3e259bcdSdan CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 213*3e259bcdSdan CREATE UNIQUE INDEX t1b ON t1(b); 214*3e259bcdSdan WITH s(i) AS ( 215*3e259bcdSdan SELECT 1 216*3e259bcdSdan UNION ALL 217*3e259bcdSdan SELECT i+1 FROM s WHERE i<1000 218*3e259bcdSdan ) 219*3e259bcdSdan INSERT INTO t1 SELECT i, number_name(i) FROM s; 220*3e259bcdSdan} 221*3e259bcdSdan 222*3e259bcdSdando_test 6.1 { 223*3e259bcdSdan db eval BEGIN 224*3e259bcdSdan set ::C [changeset_from_sql { 225*3e259bcdSdan DELETE FROM t1; 226*3e259bcdSdan WITH s(i) AS ( 227*3e259bcdSdan SELECT 1 228*3e259bcdSdan UNION ALL 229*3e259bcdSdan SELECT i+1 FROM s WHERE i<1000 230*3e259bcdSdan ) 231*3e259bcdSdan INSERT INTO t1 SELECT i, number_name(i+1) FROM s; 232*3e259bcdSdan }] 233*3e259bcdSdan db eval ROLLBACK 234*3e259bcdSdan execsql { SELECT count(*) FROM t1 WHERE number_name(a) IS NOT b } 235*3e259bcdSdan} {0} 236*3e259bcdSdan 237*3e259bcdSdanproc xConflict {args} { exit ; return "OMIT" } 238*3e259bcdSdando_test 6.2 { 239*3e259bcdSdan sqlite3changeset_apply db $C xConflict 240*3e259bcdSdan} {} 241*3e259bcdSdan 242*3e259bcdSdando_execsql_test 6.3 { SELECT count(*) FROM t1; } {1000} 243*3e259bcdSdando_execsql_test 6.4 { 244*3e259bcdSdan SELECT count(*) FROM t1 WHERE number_name(a+1) IS NOT b; 245*3e259bcdSdan} {0} 246*3e259bcdSdan 247*3e259bcdSdan# db eval { SELECT * FROM t1 } { puts "$a || $b" } 248f225059bSdan 249f225059bSdan 250d9151526Sdanfinish_test 251