104668833Sdan# 2001 September 15 204668833Sdan# 304668833Sdan# The author disclaims copyright to this source code. In place of 404668833Sdan# a legal notice, here is a blessing: 504668833Sdan# 604668833Sdan# May you do good and not evil. 704668833Sdan# May you find forgiveness for yourself and forgive others. 804668833Sdan# May you share freely, never taking more than you give. 904668833Sdan# 1004668833Sdan#*********************************************************************** 1104668833Sdan# This file implements regression tests for SQLite library. 1204668833Sdan# 1304668833Sdan# This file implements tests for foreign keys. 1404668833Sdan# 1504668833Sdan 1604668833Sdanset testdir [file dirname $argv0] 1704668833Sdansource $testdir/tester.tcl 1804668833Sdanset testprefix fkey8 1904668833Sdan 2004668833Sdanifcapable {!foreignkey} { 2104668833Sdan finish_test 2204668833Sdan return 2304668833Sdan} 2404668833Sdando_execsql_test 1.0 { PRAGMA foreign_keys = 1; } 2504668833Sdan 2604668833Sdan 2704668833Sdanforeach {tn use_stmt sql schema} { 2804668833Sdan 1 1 "DELETE FROM p1" { 2904668833Sdan CREATE TABLE p1(a PRIMARY KEY); 3004668833Sdan CREATE TABLE c1(b REFERENCES p1); 3104668833Sdan } 3204668833Sdan 3304668833Sdan 2.1 0 "DELETE FROM p1" { 3404668833Sdan CREATE TABLE p1(a PRIMARY KEY); 3504668833Sdan CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE); 3604668833Sdan } 3704668833Sdan 2.2 0 "DELETE FROM p1" { 3804668833Sdan CREATE TABLE p1(a PRIMARY KEY); 3904668833Sdan CREATE TABLE c1(b REFERENCES p1 ON DELETE SET NULL); 4004668833Sdan } 4104668833Sdan 2.3 1 "DELETE FROM p1" { 4204668833Sdan CREATE TABLE p1(a PRIMARY KEY); 4304668833Sdan CREATE TABLE c1(b REFERENCES p1 ON DELETE SET DEFAULT); 4404668833Sdan } 4504668833Sdan 4604668833Sdan 3 1 "DELETE FROM p1" { 4704668833Sdan CREATE TABLE p1(a PRIMARY KEY); 4804668833Sdan CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE); 4904668833Sdan CREATE TRIGGER ct1 AFTER DELETE ON c1 BEGIN 5004668833Sdan INSERT INTO p1 VALUES('x'); 5104668833Sdan END; 5204668833Sdan } 5304668833Sdan 5404668833Sdan 4 1 "DELETE FROM p1" { 5504668833Sdan CREATE TABLE p1(a PRIMARY KEY); 5604668833Sdan CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY); 5704668833Sdan CREATE TABLE cc1(d REFERENCES c1); 5804668833Sdan } 5904668833Sdan 6004668833Sdan 5.1 0 "DELETE FROM p1" { 6104668833Sdan CREATE TABLE p1(a PRIMARY KEY); 6204668833Sdan CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY); 6304668833Sdan CREATE TABLE cc1(d REFERENCES c1 ON DELETE CASCADE); 6404668833Sdan } 6504668833Sdan 5.2 0 "DELETE FROM p1" { 6604668833Sdan CREATE TABLE p1(a PRIMARY KEY); 6704668833Sdan CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY); 6804668833Sdan CREATE TABLE cc1(d REFERENCES c1 ON DELETE SET NULL); 6904668833Sdan } 70d4572711Sdan 5.3 1 "DELETE FROM p1" { 71d4572711Sdan CREATE TABLE p1(a PRIMARY KEY); 72d4572711Sdan CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY); 73d4572711Sdan CREATE TABLE cc1(d REFERENCES c1 ON DELETE SET DEFAULT); 74d4572711Sdan } 75d4572711Sdan 76d4572711Sdan 6.1 1 "UPDATE p1 SET a = ?" { 77d4572711Sdan CREATE TABLE p1(a PRIMARY KEY); 78d4572711Sdan CREATE TABLE c1(b REFERENCES p1 ON UPDATE SET NULL, c); 79d4572711Sdan } 80d4572711Sdan 6.2 0 "UPDATE OR IGNORE p1 SET a = ?" { 81d4572711Sdan CREATE TABLE p1(a PRIMARY KEY); 82d4572711Sdan CREATE TABLE c1(b REFERENCES p1 ON UPDATE SET NULL, c); 83d4572711Sdan } 84d4572711Sdan 6.3 1 "UPDATE OR IGNORE p1 SET a = ?" { 85d4572711Sdan CREATE TABLE p1(a PRIMARY KEY); 86d4572711Sdan CREATE TABLE c1(b REFERENCES p1 ON UPDATE CASCADE, c); 87d4572711Sdan } 88d4572711Sdan 6.4 1 "UPDATE OR IGNORE p1 SET a = ?" { 89d4572711Sdan CREATE TABLE p1(a PRIMARY KEY); 90d4572711Sdan CREATE TABLE c1(b NOT NULL REFERENCES p1 ON UPDATE SET NULL, c); 91d4572711Sdan } 9204668833Sdan 9304668833Sdan} { 9404668833Sdan drop_all_tables 9504668833Sdan do_test 1.$tn { 9604668833Sdan execsql $schema 9704668833Sdan set stmt [sqlite3_prepare_v2 db $sql -1 dummy] 9804668833Sdan set ret [uses_stmt_journal $stmt] 9904668833Sdan sqlite3_finalize $stmt 10004668833Sdan set ret 10104668833Sdan } $use_stmt 10204668833Sdan} 10304668833Sdan 104f9a12a10Sdan#------------------------------------------------------------------------- 105f9a12a10Sdan# The following tests check that foreign key constaint counters are 106f9a12a10Sdan# correctly updated for any implicit DELETE operations that occur 107f9a12a10Sdan# when a REPLACE command is executed against a WITHOUT ROWID table 108f9a12a10Sdan# that has no triggers or auxiliary indexes. 109f9a12a10Sdan# 110f9a12a10Sdanreset_db 111f9a12a10Sdando_execsql_test 2.1.0 { 112f9a12a10Sdan PRAGMA foreign_keys = on; 113f9a12a10Sdan CREATE TABLE p1(a PRIMARY KEY, b) WITHOUT ROWID; 114f9a12a10Sdan CREATE TABLE c1(x REFERENCES p1 DEFERRABLE INITIALLY DEFERRED); 115f9a12a10Sdan 116f9a12a10Sdan INSERT INTO p1 VALUES(1, 'one'); 117f9a12a10Sdan INSERT INTO p1 VALUES(2, 'two'); 118f9a12a10Sdan INSERT INTO c1 VALUES(1); 119f9a12a10Sdan INSERT INTO c1 VALUES(2); 120f9a12a10Sdan} 121f9a12a10Sdan 122f9a12a10Sdando_catchsql_test 2.1.2 { 123f9a12a10Sdan BEGIN; 124f9a12a10Sdan DELETE FROM p1 WHERE a=1; 125f9a12a10Sdan INSERT OR REPLACE INTO p1 VALUES(2, 'two'); 126f9a12a10Sdan COMMIT; 127f9a12a10Sdan} {1 {FOREIGN KEY constraint failed}} 128f9a12a10Sdan 129f9a12a10Sdanreset_db 130f9a12a10Sdando_execsql_test 2.2.0 { 131f9a12a10Sdan PRAGMA foreign_keys = on; 132f9a12a10Sdan CREATE TABLE p2(a PRIMARY KEY, b); 133f9a12a10Sdan CREATE TABLE c2( 134f9a12a10Sdan x PRIMARY KEY, 135f9a12a10Sdan y REFERENCES p2 DEFERRABLE INITIALLY DEFERRED 136f9a12a10Sdan ) WITHOUT ROWID; 137f9a12a10Sdan} 138f9a12a10Sdan 139f9a12a10Sdando_catchsql_test 2.2.1 { 140f9a12a10Sdan BEGIN; 141f9a12a10Sdan INSERT INTO c2 VALUES(13, 13); 142f9a12a10Sdan INSERT OR REPLACE INTO c2 VALUES(13, 13); 143f9a12a10Sdan DELETE FROM c2; 144f9a12a10Sdan COMMIT; 145f9a12a10Sdan} {0 {}} 146f9a12a10Sdan 147f9a12a10Sdanreset_db 148f9a12a10Sdando_execsql_test 2.3.0 { 149f9a12a10Sdan PRAGMA foreign_keys = on; 150f9a12a10Sdan CREATE TABLE p3(a PRIMARY KEY, b) WITHOUT ROWID; 151f9a12a10Sdan CREATE TABLE c3(x REFERENCES p3); 152f9a12a10Sdan 153f9a12a10Sdan INSERT INTO p3 VALUES(1, 'one'); 154f9a12a10Sdan INSERT INTO p3 VALUES(2, 'two'); 155f9a12a10Sdan INSERT INTO c3 VALUES(1); 156f9a12a10Sdan INSERT INTO c3 VALUES(2); 157f9a12a10Sdan 158f9a12a10Sdan CREATE TRIGGER p3d AFTER DELETE ON p3 WHEN old.a=1 BEGIN 159f9a12a10Sdan INSERT OR REPLACE INTO p3 VALUES(2, 'three'); 160f9a12a10Sdan END; 161f9a12a10Sdan} 162f9a12a10Sdan 163f9a12a10Sdando_catchsql_test 2.3.1 { 164f9a12a10Sdan DELETE FROM p3 WHERE a=1 165f9a12a10Sdan} {1 {FOREIGN KEY constraint failed}} 16604668833Sdan 167e46201e2Sdan 168e46201e2Sdando_execsql_test 3.0 { 169e46201e2Sdan PRAGMA foreign_keys=ON; 170e46201e2Sdan CREATE TABLE t2( 171e46201e2Sdan a PRIMARY KEY, b, c, d, e, 172e46201e2Sdan FOREIGN KEY(b, c) REFERENCES t2(d, e) 173e46201e2Sdan ) WITHOUT ROWID; 174e46201e2Sdan CREATE UNIQUE INDEX idx ON t2(d, e); 175e46201e2Sdan 176e46201e2Sdan INSERT INTO t2 VALUES(1, 'one', 'one', 'one', 'one'); -- row is parent of self 177e46201e2Sdan INSERT INTO t2 VALUES(2, 'one', 'one', 'one', NULL); -- parent is row 1 178e46201e2Sdan} 179e46201e2Sdan 180e46201e2Sdando_catchsql_test 3.1 { 181e46201e2Sdan DELETE FROM t2 WHERE a=1; 182e46201e2Sdan} {1 {FOREIGN KEY constraint failed}} 183e46201e2Sdan 184e46201e2Sdando_execsql_test 4.0 { 185e46201e2Sdan CREATE TABLE t1 ( 186e46201e2Sdan c1 PRIMARY KEY, 187e46201e2Sdan c2 NUMERIC, 188e46201e2Sdan FOREIGN KEY(c1) REFERENCES t1(c2) 189e46201e2Sdan ) WITHOUT ROWID ; 190e46201e2Sdan CREATE INDEX t1c1 ON t1(c1); 191e46201e2Sdan CREATE UNIQUE INDEX t1c1unique ON t1(c2); 192e46201e2Sdan} 193e46201e2Sdando_catchsql_test 4.1 { 194e46201e2Sdan INSERT OR REPLACE INTO t1 VALUES(10000, 20000); 195e46201e2Sdan} {1 {FOREIGN KEY constraint failed}} 196e46201e2Sdando_execsql_test 4.2 { 197e46201e2Sdan INSERT OR REPLACE INTO t1 VALUES(20000, 20000); 198e46201e2Sdan} 199e46201e2Sdan 200244edd01Sdan#------------------------------------------------------------------------- 201244edd01Sdanreset_db 202244edd01Sdando_execsql_test 5.0 { 203244edd01Sdan PRAGMA foreign_keys = true; 204244edd01Sdan CREATE TABLE parent( 205244edd01Sdan p TEXT PRIMARY KEY 206244edd01Sdan ); 207244edd01Sdan CREATE TABLE child( 208244edd01Sdan c INTEGER UNIQUE, 209244edd01Sdan FOREIGN KEY(c) REFERENCES parent(p) DEFERRABLE INITIALLY DEFERRED 210244edd01Sdan ); 211244edd01Sdan BEGIN; 212244edd01Sdan INSERT INTO child VALUES(123); 213244edd01Sdan INSERT INTO parent VALUES('123'); 214244edd01Sdan COMMIT; 215244edd01Sdan} 216244edd01Sdando_execsql_test 5.1 { 217244edd01Sdan PRAGMA integrity_check; 218244edd01Sdan} {ok} 219244edd01Sdan 220244edd01Sdando_execsql_test 5.2 { 221244edd01Sdan INSERT INTO parent VALUES(1200); 222244edd01Sdan BEGIN; 223244edd01Sdan INSERT INTO child VALUES(456); 224244edd01Sdan UPDATE parent SET p = '456' WHERE p=1200; 225244edd01Sdan COMMIT; 226244edd01Sdan} 227244edd01Sdando_execsql_test 5.3 { 228244edd01Sdan PRAGMA integrity_check; 229244edd01Sdan} {ok} 230244edd01Sdan 231*b1929708Sdan#------------------------------------------------------------------------- 232*b1929708Sdanreset_db 233*b1929708Sdanforcedelete test.db2 234*b1929708Sdando_execsql_test 6.1 { 235*b1929708Sdan PRAGMA foreign_keys = on; 236*b1929708Sdan CREATE TABLE c1(b); 237*b1929708Sdan INSERT INTO c1 VALUES(123); 238*b1929708Sdan} 239*b1929708Sdan 240*b1929708Sdando_execsql_test 6.2 { 241*b1929708Sdan ATTACH 'test.db2' AS aux; 242*b1929708Sdan CREATE TABLE aux.p1(a INTEGER PRIMARY KEY); 243*b1929708Sdan CREATE TABLE aux.c1(b REFERENCES p1(a) ON DELETE RESTRICT); 244*b1929708Sdan 245*b1929708Sdan INSERT INTO aux.p1 VALUES(123); 246*b1929708Sdan} 247*b1929708Sdan 248*b1929708Sdando_execsql_test 6.3 { 249*b1929708Sdan DELETE FROM aux.p1 WHERE a=123; 250*b1929708Sdan} 251*b1929708Sdan 252*b1929708Sdan 25304668833Sdanfinish_test 254