1# 2016 March 30 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# 12# This file implements regression tests for the sessions module. 13# Specifically, it tests that UNIQUE constraints are dealt with correctly. 14# 15 16 17 18if {![info exists testdir]} { 19 set testdir [file join [file dirname [info script]] .. .. test] 20} 21source [file join [file dirname [info script]] session_common.tcl] 22source $testdir/tester.tcl 23ifcapable !session {finish_test; return} 24set testprefix sessionG 25 26 27forcedelete test.db2 28sqlite3 db2 test.db2 29 30do_test 1.0 { 31 do_common_sql { 32 CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); 33 INSERT INTO t1 VALUES(1, 'one'); 34 INSERT INTO t1 VALUES(2, 'two'); 35 INSERT INTO t1 VALUES(3, 'three'); 36 } 37 do_then_apply_sql { 38 DELETE FROM t1 WHERE a=1; 39 INSERT INTO t1 VALUES(4, 'one'); 40 } 41 compare_db db db2 42} {} 43 44do_test 1.1 { 45 do_then_apply_sql { 46 DELETE FROM t1 WHERE a=4; 47 INSERT INTO t1 VALUES(1, 'one'); 48 } 49 compare_db db db2 50} {} 51 52do_test 1.2 { 53 execsql { INSERT INTO t1 VALUES(5, 'five') } db2 54 do_then_apply_sql { 55 INSERT INTO t1 VALUES(11, 'eleven'); 56 INSERT INTO t1 VALUES(12, 'five'); 57 } 58 execsql { SELECT * FROM t1 } db2 59} {2 two 3 three 1 one 5 five 11 eleven} 60 61do_test 1.3 { 62 execsql { SELECT * FROM t1 } 63} {2 two 3 three 1 one 11 eleven 12 five} 64 65#------------------------------------------------------------------------- 66# 67reset_db 68db2 close 69forcedelete test.db2 70sqlite3 db2 test.db2 71 72do_test 2.1 { 73 do_common_sql { 74 CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c UNIQUE); 75 INSERT INTO t1 VALUES(1, 1, 1); 76 INSERT INTO t1 VALUES(2, 2, 2); 77 INSERT INTO t1 VALUES(3, 3, 3); 78 } 79} {} 80 81do_test 2.2.1 { 82 # It is not possible to apply the changeset generated by the following 83 # SQL, as none of the three updated rows may be updated as part of the 84 # first pass. 85 do_then_apply_sql { 86 UPDATE t1 SET b=0 WHERE a=1; 87 UPDATE t1 SET b=1 WHERE a=2; 88 UPDATE t1 SET b=2 WHERE a=3; 89 UPDATE t1 SET b=3 WHERE a=1; 90 } 91 db2 eval { SELECT a, b FROM t1 } 92} {1 1 2 2 3 3} 93do_test 2.2.2 { db eval { SELECT a, b FROM t1 } } {1 3 2 1 3 2} 94 95#------------------------------------------------------------------------- 96# 97reset_db 98db2 close 99forcedelete test.db2 100sqlite3 db2 test.db2 101 102do_test 3.1 { 103 do_common_sql { 104 CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c UNIQUE); 105 INSERT INTO t1 VALUES(1, 1, 1); 106 INSERT INTO t1 VALUES(2, 2, 2); 107 INSERT INTO t1 VALUES(3, 3, 3); 108 } 109} {} 110 111do_test 3.3 { 112 do_then_apply_sql { 113 UPDATE t1 SET b=4 WHERE a=3; 114 UPDATE t1 SET b=3 WHERE a=2; 115 UPDATE t1 SET b=2 WHERE a=1; 116 } 117 compare_db db db2 118} {} 119 120do_test 3.4 { 121 do_then_apply_sql { 122 UPDATE t1 SET b=1 WHERE a=1; 123 UPDATE t1 SET b=2 WHERE a=2; 124 UPDATE t1 SET b=3 WHERE a=3; 125 } 126 compare_db db db2 127} {} 128 129#------------------------------------------------------------------------- 130# 131reset_db 132db2 close 133forcedelete test.db2 134sqlite3 db2 test.db2 135 136do_test 4.1 { 137 do_common_sql { 138 CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); 139 INSERT INTO t1 VALUES(1, 1); 140 INSERT INTO t1 VALUES(2, 2); 141 INSERT INTO t1 VALUES(3, 3); 142 143 CREATE TABLE t2(a PRIMARY KEY, b UNIQUE); 144 INSERT INTO t2 VALUES(1, 1); 145 INSERT INTO t2 VALUES(2, 2); 146 INSERT INTO t2 VALUES(3, 3); 147 } 148} {} 149 150do_test 4.2 { 151 do_then_apply_sql { 152 UPDATE t1 SET b=4 WHERE a=3; 153 UPDATE t1 SET b=3 WHERE a=2; 154 UPDATE t1 SET b=2 WHERE a=1; 155 156 UPDATE t2 SET b=0 WHERE a=1; 157 UPDATE t2 SET b=1 WHERE a=2; 158 UPDATE t2 SET b=2 WHERE a=3; 159 } 160 compare_db db db2 161} {} 162 163do_test 4.3 { 164 do_then_apply_sql { 165 UPDATE t1 SET b=1 WHERE a=1; 166 UPDATE t1 SET b=2 WHERE a=2; 167 UPDATE t1 SET b=3 WHERE a=3; 168 169 UPDATE t2 SET b=3 WHERE a=3; 170 UPDATE t2 SET b=2 WHERE a=2; 171 UPDATE t2 SET b=1 WHERE a=1; 172 } 173 compare_db db db2 174} {} 175 176#------------------------------------------------------------------------- 177reset_db 178catch { db2 close } 179forcedelete test.db2 180sqlite3 db2 test.db2 181 182do_execsql_test 5.0.1 { 183 CREATE TABLE t1(a PRIMARY KEY, b, c); 184 CREATE TABLE t2(a, b, c PRIMARY KEY); 185 CREATE TABLE t3(a, b PRIMARY KEY, c); 186} 187do_execsql_test -db db2 5.0.2 { 188 CREATE TABLE t1(a PRIMARY KEY, b, c); 189 CREATE TABLE t2(a, b, c); 190 CREATE TABLE t3(a, b PRIMARY KEY, c); 191} 192 193do_test 5.1 { 194 do_then_apply_sql { 195 INSERT INTO t1 VALUES(1, 2, 3); 196 INSERT INTO t2 VALUES(4, 5, 6); 197 INSERT INTO t3 VALUES(7, 8, 9); 198 } 199 200 db2 eval { 201 SELECT * FROM t1; 202 SELECT * FROM t2; 203 SELECT * FROM t3; 204 } 205} {1 2 3 7 8 9} 206 207#------------------------------------------------------------------------- 208 209reset_db 210db func number_name number_name 211do_execsql_test 6.0 { 212 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 213 CREATE UNIQUE INDEX t1b ON t1(b); 214 WITH s(i) AS ( 215 SELECT 1 216 UNION ALL 217 SELECT i+1 FROM s WHERE i<1000 218 ) 219 INSERT INTO t1 SELECT i, number_name(i) FROM s; 220} 221 222do_test 6.1 { 223 db eval BEGIN 224 set ::C [changeset_from_sql { 225 DELETE FROM t1; 226 WITH s(i) AS ( 227 SELECT 1 228 UNION ALL 229 SELECT i+1 FROM s WHERE i<1000 230 ) 231 INSERT INTO t1 SELECT i, number_name(i+1) FROM s; 232 }] 233 db eval ROLLBACK 234 execsql { SELECT count(*) FROM t1 WHERE number_name(a) IS NOT b } 235} {0} 236 237proc xConflict {args} { exit ; return "OMIT" } 238do_test 6.2 { 239 sqlite3changeset_apply db $C xConflict 240} {} 241 242do_execsql_test 6.3 { SELECT count(*) FROM t1; } {1000} 243do_execsql_test 6.4 { 244 SELECT count(*) FROM t1 WHERE number_name(a+1) IS NOT b; 245} {0} 246 247# db eval { SELECT * FROM t1 } { puts "$a || $b" } 248 249 250finish_test 251 252