github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/fkey8.test (about) 1 # 2001 September 15 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 # This file implements regression tests for SQLite library. 12 # 13 # This file implements tests for foreign keys. 14 # 15 16 set testdir [file dirname $argv0] 17 source $testdir/tester.tcl 18 set testprefix fkey8 19 20 ifcapable {!foreignkey} { 21 finish_test 22 return 23 } 24 do_execsql_test 1.0 { PRAGMA foreign_keys = 1; } 25 26 27 foreach {tn use_stmt sql schema} { 28 1 1 "DELETE FROM p1" { 29 CREATE TABLE p1(a PRIMARY KEY); 30 CREATE TABLE c1(b REFERENCES p1); 31 } 32 33 2.1 0 "DELETE FROM p1" { 34 CREATE TABLE p1(a PRIMARY KEY); 35 CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE); 36 } 37 2.2 0 "DELETE FROM p1" { 38 CREATE TABLE p1(a PRIMARY KEY); 39 CREATE TABLE c1(b REFERENCES p1 ON DELETE SET NULL); 40 } 41 2.3 1 "DELETE FROM p1" { 42 CREATE TABLE p1(a PRIMARY KEY); 43 CREATE TABLE c1(b REFERENCES p1 ON DELETE SET DEFAULT); 44 } 45 46 3 1 "DELETE FROM p1" { 47 CREATE TABLE p1(a PRIMARY KEY); 48 CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE); 49 CREATE TRIGGER ct1 AFTER DELETE ON c1 BEGIN 50 INSERT INTO p1 VALUES('x'); 51 END; 52 } 53 54 4 1 "DELETE FROM p1" { 55 CREATE TABLE p1(a PRIMARY KEY); 56 CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY); 57 CREATE TABLE cc1(d REFERENCES c1); 58 } 59 60 5.1 0 "DELETE FROM p1" { 61 CREATE TABLE p1(a PRIMARY KEY); 62 CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY); 63 CREATE TABLE cc1(d REFERENCES c1 ON DELETE CASCADE); 64 } 65 5.2 0 "DELETE FROM p1" { 66 CREATE TABLE p1(a PRIMARY KEY); 67 CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY); 68 CREATE TABLE cc1(d REFERENCES c1 ON DELETE SET NULL); 69 } 70 5.3 1 "DELETE FROM p1" { 71 CREATE TABLE p1(a PRIMARY KEY); 72 CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY); 73 CREATE TABLE cc1(d REFERENCES c1 ON DELETE SET DEFAULT); 74 } 75 76 6.1 1 "UPDATE p1 SET a = ?" { 77 CREATE TABLE p1(a PRIMARY KEY); 78 CREATE TABLE c1(b REFERENCES p1 ON UPDATE SET NULL, c); 79 } 80 6.2 0 "UPDATE OR IGNORE p1 SET a = ?" { 81 CREATE TABLE p1(a PRIMARY KEY); 82 CREATE TABLE c1(b REFERENCES p1 ON UPDATE SET NULL, c); 83 } 84 6.3 1 "UPDATE OR IGNORE p1 SET a = ?" { 85 CREATE TABLE p1(a PRIMARY KEY); 86 CREATE TABLE c1(b REFERENCES p1 ON UPDATE CASCADE, c); 87 } 88 6.4 1 "UPDATE OR IGNORE p1 SET a = ?" { 89 CREATE TABLE p1(a PRIMARY KEY); 90 CREATE TABLE c1(b NOT NULL REFERENCES p1 ON UPDATE SET NULL, c); 91 } 92 93 } { 94 drop_all_tables 95 do_test 1.$tn { 96 execsql $schema 97 set stmt [sqlite3_prepare_v2 db $sql -1 dummy] 98 set ret [uses_stmt_journal $stmt] 99 sqlite3_finalize $stmt 100 set ret 101 } $use_stmt 102 } 103 104 #------------------------------------------------------------------------- 105 # The following tests check that foreign key constaint counters are 106 # correctly updated for any implicit DELETE operations that occur 107 # when a REPLACE command is executed against a WITHOUT ROWID table 108 # that has no triggers or auxiliary indexes. 109 # 110 reset_db 111 do_execsql_test 2.1.0 { 112 PRAGMA foreign_keys = on; 113 CREATE TABLE p1(a PRIMARY KEY, b) WITHOUT ROWID; 114 CREATE TABLE c1(x REFERENCES p1 DEFERRABLE INITIALLY DEFERRED); 115 116 INSERT INTO p1 VALUES(1, 'one'); 117 INSERT INTO p1 VALUES(2, 'two'); 118 INSERT INTO c1 VALUES(1); 119 INSERT INTO c1 VALUES(2); 120 } 121 122 do_catchsql_test 2.1.2 { 123 BEGIN; 124 DELETE FROM p1 WHERE a=1; 125 INSERT OR REPLACE INTO p1 VALUES(2, 'two'); 126 COMMIT; 127 } {1 {FOREIGN KEY constraint failed}} 128 129 reset_db 130 do_execsql_test 2.2.0 { 131 PRAGMA foreign_keys = on; 132 CREATE TABLE p2(a PRIMARY KEY, b); 133 CREATE TABLE c2( 134 x PRIMARY KEY, 135 y REFERENCES p2 DEFERRABLE INITIALLY DEFERRED 136 ) WITHOUT ROWID; 137 } 138 139 do_catchsql_test 2.2.1 { 140 BEGIN; 141 INSERT INTO c2 VALUES(13, 13); 142 INSERT OR REPLACE INTO c2 VALUES(13, 13); 143 DELETE FROM c2; 144 COMMIT; 145 } {0 {}} 146 147 reset_db 148 do_execsql_test 2.3.0 { 149 PRAGMA foreign_keys = on; 150 CREATE TABLE p3(a PRIMARY KEY, b) WITHOUT ROWID; 151 CREATE TABLE c3(x REFERENCES p3); 152 153 INSERT INTO p3 VALUES(1, 'one'); 154 INSERT INTO p3 VALUES(2, 'two'); 155 INSERT INTO c3 VALUES(1); 156 INSERT INTO c3 VALUES(2); 157 158 CREATE TRIGGER p3d AFTER DELETE ON p3 WHEN old.a=1 BEGIN 159 INSERT OR REPLACE INTO p3 VALUES(2, 'three'); 160 END; 161 } 162 163 do_catchsql_test 2.3.1 { 164 DELETE FROM p3 WHERE a=1 165 } {1 {FOREIGN KEY constraint failed}} 166 167 168 do_execsql_test 3.0 { 169 PRAGMA foreign_keys=ON; 170 CREATE TABLE t2( 171 a PRIMARY KEY, b, c, d, e, 172 FOREIGN KEY(b, c) REFERENCES t2(d, e) 173 ) WITHOUT ROWID; 174 CREATE UNIQUE INDEX idx ON t2(d, e); 175 176 INSERT INTO t2 VALUES(1, 'one', 'one', 'one', 'one'); -- row is parent of self 177 INSERT INTO t2 VALUES(2, 'one', 'one', 'one', NULL); -- parent is row 1 178 } 179 180 do_catchsql_test 3.1 { 181 DELETE FROM t2 WHERE a=1; 182 } {1 {FOREIGN KEY constraint failed}} 183 184 do_execsql_test 4.0 { 185 CREATE TABLE t1 ( 186 c1 PRIMARY KEY, 187 c2 NUMERIC, 188 FOREIGN KEY(c1) REFERENCES t1(c2) 189 ) WITHOUT ROWID ; 190 CREATE INDEX t1c1 ON t1(c1); 191 CREATE UNIQUE INDEX t1c1unique ON t1(c2); 192 } 193 do_catchsql_test 4.1 { 194 INSERT OR REPLACE INTO t1 VALUES(10000, 20000); 195 } {1 {FOREIGN KEY constraint failed}} 196 do_execsql_test 4.2 { 197 INSERT OR REPLACE INTO t1 VALUES(20000, 20000); 198 } 199 200 #------------------------------------------------------------------------- 201 reset_db 202 do_execsql_test 5.0 { 203 PRAGMA foreign_keys = true; 204 CREATE TABLE parent( 205 p TEXT PRIMARY KEY 206 ); 207 CREATE TABLE child( 208 c INTEGER UNIQUE, 209 FOREIGN KEY(c) REFERENCES parent(p) DEFERRABLE INITIALLY DEFERRED 210 ); 211 BEGIN; 212 INSERT INTO child VALUES(123); 213 INSERT INTO parent VALUES('123'); 214 COMMIT; 215 } 216 do_execsql_test 5.1 { 217 PRAGMA integrity_check; 218 } {ok} 219 220 do_execsql_test 5.2 { 221 INSERT INTO parent VALUES(1200); 222 BEGIN; 223 INSERT INTO child VALUES(456); 224 UPDATE parent SET p = '456' WHERE p=1200; 225 COMMIT; 226 } 227 do_execsql_test 5.3 { 228 PRAGMA integrity_check; 229 } {ok} 230 231 finish_test