1# 2014 August 16 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# 13 14if {![info exists testdir]} { 15 set testdir [file join [file dirname [info script]] .. .. test] 16} 17source [file join [file dirname [info script]] session_common.tcl] 18source $testdir/tester.tcl 19ifcapable !session {finish_test; return} 20 21set testprefix sessionC 22 23#------------------------------------------------------------------------- 24# Test the outcome of a DELETE operation made as part of applying a 25# changeset failing with SQLITE_CONSTRAINT. This may happen if an 26# ON DELETE RESTRICT foreign key action is triggered, or if a trigger 27# program raises a constraint somehow. 28# 29# UPDATE: The above is no longer true, as "PRAGMA defer_foreign_keys" 30# now disables "RESTRICT" processing. The test below has been rewritten 31# to use a trigger instead of a foreign key to test this case. 32# 33do_execsql_test 1.0 { 34 PRAGMA foreign_keys = 1; 35 36 CREATE TABLE p(a PRIMARY KEY, b, c); 37 CREATE TABLE c(d PRIMARY KEY, e /* REFERENCES p ON DELETE RESTRICT */); 38 39 CREATE TRIGGER restrict_trig BEFORE DELETE ON p BEGIN 40 SELECT raise(ABORT, 'error!') FROM c WHERE e=old.a; 41 END; 42 43 INSERT INTO p VALUES('one', 1, 1); 44 INSERT INTO p VALUES('two', 2, 2); 45 INSERT INTO p VALUES('three', 3, 3); 46 47 INSERT INTO c VALUES(1, 'one'); 48 INSERT INTO c VALUES(3, 'three'); 49} 50 51do_test 1.1 { 52 execsql BEGIN 53 set C [changeset_from_sql { 54 INSERT INTO c VALUES(4, 'one'); 55 DELETE FROM p WHERE a='two'; 56 }] 57 execsql ROLLBACK 58 execsql { 59 INSERT INTO c VALUES(2, 'two'); 60 } 61} {} 62 63do_test 1.2.1 { 64 proc xConflict {args} { return "ABORT" } 65 catch { sqlite3changeset_apply db $C xConflict } msg 66 set msg 67} {SQLITE_ABORT} 68do_execsql_test 1.2.2 { SELECT * FROM c } {1 one 3 three 2 two} 69 70do_test 1.3.1 { 71 proc xConflict {args} { return "OMIT" } 72 catch { sqlite3changeset_apply db $C xConflict } msg 73 set msg 74} {} 75do_execsql_test 1.3.2 { SELECT * FROM c } {1 one 3 three 2 two 4 one} 76do_execsql_test 1.3.3 { 77 SELECT * FROM p; 78} {one 1 1 two 2 2 three 3 3} 79 80 81#------------------------------------------------------------------------- 82# Test that concatenating a changeset with a patchset does not work. 83# Any attempt to do so returns SQLITE_ERROR. 84# 85reset_db 86do_execsql_test 2.0 { 87 CREATE TABLE x1(t, v PRIMARY KEY); 88 INSERT INTO x1 VALUES(12, 55); 89 INSERT INTO x1 VALUES(55, 14); 90} 91 92do_test 2.1 { 93 execsql BEGIN 94 95 sqlite3session S1 db main 96 S1 attach * 97 execsql { 98 UPDATE x1 SET t=13 WHERE v=55; 99 INSERT INTO x1 VALUES(99, 123); 100 } 101 set patchset [S1 patchset] 102 S1 delete 103 104 sqlite3session S1 db main 105 S1 attach * 106 execsql { 107 UPDATE x1 SET t=56 WHERE v=14; 108 INSERT INTO x1 VALUES(22, 998); 109 } 110 set changeset [S1 changeset] 111 S1 delete 112 113 execsql ROLLBACK 114} {} 115 116do_test 2.2 { 117 set rc [catch { sqlite3changeset_concat $patchset $changeset } msg] 118 list $rc $msg 119} {1 SQLITE_ERROR} 120 121do_test 2.3 { 122 set rc [catch { sqlite3changeset_concat $changeset $patchset } msg] 123 list $rc $msg 124} {1 SQLITE_ERROR} 125 126do_test 2.4 { 127 set rc [catch { sqlite3changeset_concat {} $patchset } msg] 128 list $rc $msg 129} [list 0 $patchset] 130 131do_test 2.5 { 132 set rc [catch { sqlite3changeset_concat $patchset {} } msg] 133 list $rc $msg 134} [list 0 $patchset] 135 136do_test 2.6 { 137 set rc [catch { sqlite3changeset_concat {} $changeset } msg] 138 list $rc $msg 139} [list 0 $changeset] 140 141do_test 2.7 { 142 set rc [catch { sqlite3changeset_concat $changeset {} } msg] 143 list $rc $msg 144} [list 0 $changeset] 145 146do_test 2.8 { 147 set rc [catch { sqlite3changeset_concat {} {} } msg] 148 list $rc $msg 149} [list 0 {}] 150 151 152#------------------------------------------------------------------------- 153# Test that the xFilter argument to sqlite3changeset_apply() works. 154# 155reset_db 156do_execsql_test 3.0 { 157 CREATE TABLE t1(a PRIMARY KEY, b); 158 CREATE TABLE t2(a PRIMARY KEY, b); 159 CREATE TABLE t3(a PRIMARY KEY, b); 160} 161do_test 3.1 { 162 execsql BEGIN 163 set changeset [changeset_from_sql { 164 INSERT INTO t1 VALUES(1, 1); 165 INSERT INTO t2 VALUES(2, 2); 166 INSERT INTO t3 VALUES(3, 3); 167 }] 168 execsql ROLLBACK 169} {} 170do_test 3.2 { 171 proc xFilter {zName} { 172 if {$zName == "t1"} { return 1 } 173 return 0 174 } 175 sqlite3changeset_apply db $changeset noop xFilter 176 execsql { 177 SELECT * FROM t1; 178 SELECT * FROM t2; 179 SELECT * FROM t3; 180 } 181} {1 1} 182do_test 3.3 { 183 proc xFilter {zName} { 184 if {$zName == "t3"} { return 1 } 185 return 0 186 } 187 sqlite3changeset_apply db $changeset noop xFilter 188 execsql { 189 SELECT * FROM t1; 190 SELECT * FROM t2; 191 SELECT * FROM t3; 192 } 193} {1 1 3 3} 194 195 196 197finish_test 198