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