1# 2009 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 16set testdir [file dirname $argv0] 17source $testdir/tester.tcl 18 19ifcapable {!foreignkey||!trigger} { 20 finish_test 21 return 22} 23 24#------------------------------------------------------------------------- 25# Test structure: 26# 27# fkey2-1.*: Simple tests to check that immediate and deferred foreign key 28# constraints work when not inside a transaction. 29# 30# fkey2-2.*: Tests to verify that deferred foreign keys work inside 31# explicit transactions (i.e that processing really is deferred). 32# 33# fkey2-3.*: Tests that a statement transaction is rolled back if an 34# immediate foreign key constraint is violated. 35# 36# fkey2-4.*: Test that FK actions may recurse even when recursive triggers 37# are disabled. 38# 39# fkey2-5.*: Check that if foreign-keys are enabled, it is not possible 40# to write to an FK column using the incremental blob API. 41# 42# fkey2-6.*: Test that FK processing is automatically disabled when 43# running VACUUM. 44# 45# fkey2-7.*: Test using an IPK as the key in the child (referencing) table. 46# 47# fkey2-8.*: Test that enabling/disabling foreign key support while a 48# transaction is active is not possible. 49# 50# fkey2-9.*: Test SET DEFAULT actions. 51# 52# fkey2-10.*: Test errors. 53# 54# fkey2-11.*: Test CASCADE actions. 55# 56# fkey2-12.*: Test RESTRICT actions. 57# 58# fkey2-13.*: Test that FK processing is performed when a row is REPLACED by 59# an UPDATE or INSERT statement. 60# 61# fkey2-14.*: Test the ALTER TABLE and DROP TABLE commands. 62# 63# fkey2-15.*: Test that if there are no (known) outstanding foreign key 64# constraint violations in the database, inserting into a parent 65# table or deleting from a child table does not cause SQLite 66# to check if this has repaired an outstanding violation. 67# 68# fkey2-16.*: Test that rows that refer to themselves may be inserted, 69# updated and deleted. 70# 71# fkey2-17.*: Test that the "count_changes" pragma does not interfere with 72# FK constraint processing. 73# 74# fkey2-18.*: Test that the authorization callback is invoked when processing 75# FK constraints. 76# 77# fkey2-20.*: Test that ON CONFLICT clauses specified as part of statements 78# do not affect the operation of FK constraints. 79# 80# fkey2-genfkey.*: Tests that were used with the shell tool .genfkey 81# command. Recycled to test the built-in implementation. 82# 83# fkey2-dd08e5.*: Tests to verify that ticket dd08e5a988d00decc4a543daa8d 84# has been fixed. 85# 86 87 88execsql { PRAGMA foreign_keys = on } 89 90set FkeySimpleSchema { 91 PRAGMA foreign_keys = on; 92 CREATE TABLE t1(a PRIMARY KEY, b); 93 CREATE TABLE t2(c REFERENCES t1(a) /D/ , d); 94 95 CREATE TABLE t3(a PRIMARY KEY, b); 96 CREATE TABLE t4(c REFERENCES t3 /D/, d); 97 98 CREATE TABLE t7(a, b INTEGER PRIMARY KEY); 99 CREATE TABLE t8(c REFERENCES t7 /D/, d); 100 101 CREATE TABLE t9(a REFERENCES nosuchtable, b); 102 CREATE TABLE t10(a REFERENCES t9(c) /D/, b); 103} 104 105 106set FkeySimpleTests { 107 1.1 "INSERT INTO t2 VALUES(1, 3)" {1 {FOREIGN KEY constraint failed}} 108 1.2 "INSERT INTO t1 VALUES(1, 2)" {0 {}} 109 1.3 "INSERT INTO t2 VALUES(1, 3)" {0 {}} 110 1.4 "INSERT INTO t2 VALUES(2, 4)" {1 {FOREIGN KEY constraint failed}} 111 1.5 "INSERT INTO t2 VALUES(NULL, 4)" {0 {}} 112 1.6 "UPDATE t2 SET c=2 WHERE d=4" {1 {FOREIGN KEY constraint failed}} 113 1.7 "UPDATE t2 SET c=1 WHERE d=4" {0 {}} 114 1.9 "UPDATE t2 SET c=1 WHERE d=4" {0 {}} 115 1.10 "UPDATE t2 SET c=NULL WHERE d=4" {0 {}} 116 1.11 "DELETE FROM t1 WHERE a=1" {1 {FOREIGN KEY constraint failed}} 117 1.12 "UPDATE t1 SET a = 2" {1 {FOREIGN KEY constraint failed}} 118 1.13 "UPDATE t1 SET a = 1" {0 {}} 119 120 2.1 "INSERT INTO t4 VALUES(1, 3)" {1 {FOREIGN KEY constraint failed}} 121 2.2 "INSERT INTO t3 VALUES(1, 2)" {0 {}} 122 2.3 "INSERT INTO t4 VALUES(1, 3)" {0 {}} 123 124 4.1 "INSERT INTO t8 VALUES(1, 3)" {1 {FOREIGN KEY constraint failed}} 125 4.2 "INSERT INTO t7 VALUES(2, 1)" {0 {}} 126 4.3 "INSERT INTO t8 VALUES(1, 3)" {0 {}} 127 4.4 "INSERT INTO t8 VALUES(2, 4)" {1 {FOREIGN KEY constraint failed}} 128 4.5 "INSERT INTO t8 VALUES(NULL, 4)" {0 {}} 129 4.6 "UPDATE t8 SET c=2 WHERE d=4" {1 {FOREIGN KEY constraint failed}} 130 4.7 "UPDATE t8 SET c=1 WHERE d=4" {0 {}} 131 4.9 "UPDATE t8 SET c=1 WHERE d=4" {0 {}} 132 4.10 "UPDATE t8 SET c=NULL WHERE d=4" {0 {}} 133 4.11 "DELETE FROM t7 WHERE b=1" {1 {FOREIGN KEY constraint failed}} 134 4.12 "UPDATE t7 SET b = 2" {1 {FOREIGN KEY constraint failed}} 135 4.13 "UPDATE t7 SET b = 1" {0 {}} 136 4.14 "INSERT INTO t8 VALUES('a', 'b')" {1 {FOREIGN KEY constraint failed}} 137 4.15 "UPDATE t7 SET b = 5" {1 {FOREIGN KEY constraint failed}} 138 4.16 "UPDATE t7 SET rowid = 5" {1 {FOREIGN KEY constraint failed}} 139 4.17 "UPDATE t7 SET a = 10" {0 {}} 140 141 5.1 "INSERT INTO t9 VALUES(1, 3)" {1 {no such table: main.nosuchtable}} 142 5.2 "INSERT INTO t10 VALUES(1, 3)" 143 {1 {foreign key mismatch - "t10" referencing "t9"}} 144} 145 146do_test fkey2-1.1.0 { 147 execsql [string map {/D/ {}} $FkeySimpleSchema] 148} {} 149foreach {tn zSql res} $FkeySimpleTests { 150 do_test fkey2-1.1.$tn.1 { catchsql $zSql } $res 151 do_test fkey2-1.1.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {} 152 do_test fkey2-1.1.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {} 153 do_test fkey2-1.1.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {} 154 do_test fkey2-1.1.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {} 155 do_test fkey2-1.1.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {} 156 do_test fkey2-1.1.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {} 157} 158drop_all_tables 159 160do_test fkey2-1.2.0 { 161 execsql [string map {/D/ {DEFERRABLE INITIALLY DEFERRED}} $FkeySimpleSchema] 162} {} 163foreach {tn zSql res} $FkeySimpleTests { 164 do_test fkey2-1.2.$tn { catchsql $zSql } $res 165 do_test fkey2-1.2.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {} 166 do_test fkey2-1.2.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {} 167 do_test fkey2-1.2.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {} 168 do_test fkey2-1.2.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {} 169 do_test fkey2-1.2.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {} 170 do_test fkey2-1.2.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {} 171} 172drop_all_tables 173 174do_test fkey2-1.3.0 { 175 execsql [string map {/D/ {}} $FkeySimpleSchema] 176 execsql { PRAGMA count_changes = 1 } 177} {} 178foreach {tn zSql res} $FkeySimpleTests { 179 if {$res == "0 {}"} { set res {0 1} } 180 do_test fkey2-1.3.$tn { catchsql $zSql } $res 181 do_test fkey2-1.3.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {} 182 do_test fkey2-1.3.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {} 183 do_test fkey2-1.3.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {} 184 do_test fkey2-1.3.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {} 185 do_test fkey2-1.3.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {} 186 do_test fkey2-1.3.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {} 187} 188execsql { PRAGMA count_changes = 0 } 189drop_all_tables 190 191do_test fkey2-1.4.0 { 192 execsql [string map {/D/ {}} $FkeySimpleSchema] 193 execsql { PRAGMA count_changes = 1 } 194} {} 195foreach {tn zSql res} $FkeySimpleTests { 196 if {$res == "0 {}"} { set res {0 1} } 197 execsql BEGIN 198 do_test fkey2-1.4.$tn { catchsql $zSql } $res 199 execsql COMMIT 200} 201execsql { PRAGMA count_changes = 0 } 202drop_all_tables 203 204# Special test: When the parent key is an IPK, make sure the affinity of 205# the IPK is not applied to the child key value before it is inserted 206# into the child table. 207do_test fkey2-1.5.1 { 208 execsql { 209 CREATE TABLE i(i INTEGER PRIMARY KEY); 210 CREATE TABLE j(j REFERENCES i); 211 INSERT INTO i VALUES(35); 212 INSERT INTO j VALUES('35.0'); 213 SELECT j, typeof(j) FROM j; 214 } 215} {35.0 text} 216do_test fkey2-1.5.2 { 217 catchsql { DELETE FROM i } 218} {1 {FOREIGN KEY constraint failed}} 219 220# Same test using a regular primary key with integer affinity. 221drop_all_tables 222do_test fkey2-1.6.1 { 223 execsql { 224 CREATE TABLE i(i INT UNIQUE); 225 CREATE TABLE j(j REFERENCES i(i)); 226 INSERT INTO i VALUES('35.0'); 227 INSERT INTO j VALUES('35.0'); 228 SELECT j, typeof(j) FROM j; 229 SELECT i, typeof(i) FROM i; 230 } 231} {35.0 text 35 integer} 232do_test fkey2-1.6.2 { 233 catchsql { DELETE FROM i } 234} {1 {FOREIGN KEY constraint failed}} 235 236# Use a collation sequence on the parent key. 237drop_all_tables 238do_test fkey2-1.7.1 { 239 execsql { 240 CREATE TABLE i(i TEXT COLLATE nocase PRIMARY KEY); 241 CREATE TABLE j(j TEXT COLLATE binary REFERENCES i(i)); 242 INSERT INTO i VALUES('SQLite'); 243 INSERT INTO j VALUES('sqlite'); 244 } 245 catchsql { DELETE FROM i } 246} {1 {FOREIGN KEY constraint failed}} 247 248# Use the parent key collation even if it is default and the child key 249# has an explicit value. 250drop_all_tables 251do_test fkey2-1.7.2 { 252 execsql { 253 CREATE TABLE i(i TEXT PRIMARY KEY); -- Colseq is "BINARY" 254 CREATE TABLE j(j TEXT COLLATE nocase REFERENCES i(i)); 255 INSERT INTO i VALUES('SQLite'); 256 } 257 catchsql { INSERT INTO j VALUES('sqlite') } 258} {1 {FOREIGN KEY constraint failed}} 259do_test fkey2-1.7.3 { 260 execsql { 261 INSERT INTO i VALUES('sqlite'); 262 INSERT INTO j VALUES('sqlite'); 263 DELETE FROM i WHERE i = 'SQLite'; 264 } 265 catchsql { DELETE FROM i WHERE i = 'sqlite' } 266} {1 {FOREIGN KEY constraint failed}} 267 268#------------------------------------------------------------------------- 269# This section (test cases fkey2-2.*) contains tests to check that the 270# deferred foreign key constraint logic works. 271# 272proc fkey2-2-test {tn nocommit sql {res {}}} { 273 if {$res eq "FKV"} { 274 set expected {1 {FOREIGN KEY constraint failed}} 275 } else { 276 set expected [list 0 $res] 277 } 278 do_test fkey2-2.$tn [list catchsql $sql] $expected 279 if {$nocommit} { 280 do_test fkey2-2.${tn}c { 281 catchsql COMMIT 282 } {1 {FOREIGN KEY constraint failed}} 283 } 284} 285 286fkey2-2-test 1 0 { 287 CREATE TABLE node( 288 nodeid PRIMARY KEY, 289 parent REFERENCES node DEFERRABLE INITIALLY DEFERRED 290 ); 291 CREATE TABLE leaf( 292 cellid PRIMARY KEY, 293 parent REFERENCES node DEFERRABLE INITIALLY DEFERRED 294 ); 295} 296 297fkey2-2-test 1 0 "INSERT INTO node VALUES(1, 0)" FKV 298fkey2-2-test 2 0 "BEGIN" 299fkey2-2-test 3 1 "INSERT INTO node VALUES(1, 0)" 300fkey2-2-test 4 0 "UPDATE node SET parent = NULL" 301fkey2-2-test 5 0 "COMMIT" 302fkey2-2-test 6 0 "SELECT * FROM node" {1 {}} 303 304fkey2-2-test 7 0 "BEGIN" 305fkey2-2-test 8 1 "INSERT INTO leaf VALUES('a', 2)" 306fkey2-2-test 9 1 "INSERT INTO node VALUES(2, 0)" 307fkey2-2-test 10 0 "UPDATE node SET parent = 1 WHERE nodeid = 2" 308fkey2-2-test 11 0 "COMMIT" 309fkey2-2-test 12 0 "SELECT * FROM node" {1 {} 2 1} 310fkey2-2-test 13 0 "SELECT * FROM leaf" {a 2} 311 312fkey2-2-test 14 0 "BEGIN" 313fkey2-2-test 15 1 "DELETE FROM node WHERE nodeid = 2" 314fkey2-2-test 16 0 "INSERT INTO node VALUES(2, NULL)" 315fkey2-2-test 17 0 "COMMIT" 316fkey2-2-test 18 0 "SELECT * FROM node" {1 {} 2 {}} 317fkey2-2-test 19 0 "SELECT * FROM leaf" {a 2} 318 319fkey2-2-test 20 0 "BEGIN" 320fkey2-2-test 21 0 "INSERT INTO leaf VALUES('b', 1)" 321fkey2-2-test 22 0 "SAVEPOINT save" 322fkey2-2-test 23 0 "DELETE FROM node WHERE nodeid = 1" 323fkey2-2-test 24 0 "ROLLBACK TO save" 324fkey2-2-test 25 0 "COMMIT" 325fkey2-2-test 26 0 "SELECT * FROM node" {1 {} 2 {}} 326fkey2-2-test 27 0 "SELECT * FROM leaf" {a 2 b 1} 327 328fkey2-2-test 28 0 "BEGIN" 329fkey2-2-test 29 0 "INSERT INTO leaf VALUES('c', 1)" 330fkey2-2-test 30 0 "SAVEPOINT save" 331fkey2-2-test 31 0 "DELETE FROM node WHERE nodeid = 1" 332fkey2-2-test 32 1 "RELEASE save" 333fkey2-2-test 33 1 "DELETE FROM leaf WHERE cellid = 'b'" 334fkey2-2-test 34 0 "DELETE FROM leaf WHERE cellid = 'c'" 335fkey2-2-test 35 0 "COMMIT" 336fkey2-2-test 36 0 "SELECT * FROM node" {2 {}} 337fkey2-2-test 37 0 "SELECT * FROM leaf" {a 2} 338 339fkey2-2-test 38 0 "SAVEPOINT outer" 340fkey2-2-test 39 1 "INSERT INTO leaf VALUES('d', 3)" 341fkey2-2-test 40 1 "RELEASE outer" FKV 342fkey2-2-test 41 1 "INSERT INTO leaf VALUES('e', 3)" 343fkey2-2-test 42 0 "INSERT INTO node VALUES(3, 2)" 344fkey2-2-test 43 0 "RELEASE outer" 345 346fkey2-2-test 44 0 "SAVEPOINT outer" 347fkey2-2-test 45 1 "DELETE FROM node WHERE nodeid=3" 348fkey2-2-test 47 0 "INSERT INTO node VALUES(3, 2)" 349fkey2-2-test 48 0 "ROLLBACK TO outer" 350fkey2-2-test 49 0 "RELEASE outer" 351 352fkey2-2-test 50 0 "SAVEPOINT outer" 353fkey2-2-test 51 1 "INSERT INTO leaf VALUES('f', 4)" 354fkey2-2-test 52 1 "SAVEPOINT inner" 355fkey2-2-test 53 1 "INSERT INTO leaf VALUES('g', 4)" 356fkey2-2-test 54 1 "RELEASE outer" FKV 357fkey2-2-test 55 1 "ROLLBACK TO inner" 358fkey2-2-test 56 0 "COMMIT" FKV 359fkey2-2-test 57 0 "INSERT INTO node VALUES(4, NULL)" 360fkey2-2-test 58 0 "RELEASE outer" 361fkey2-2-test 59 0 "SELECT * FROM node" {2 {} 3 2 4 {}} 362fkey2-2-test 60 0 "SELECT * FROM leaf" {a 2 d 3 e 3 f 4} 363 364# The following set of tests check that if a statement that affects 365# multiple rows violates some foreign key constraints, then strikes a 366# constraint that causes the statement-transaction to be rolled back, 367# the deferred constraint counter is correctly reset to the value it 368# had before the statement-transaction was opened. 369# 370fkey2-2-test 61 0 "BEGIN" 371fkey2-2-test 62 0 "DELETE FROM leaf" 372fkey2-2-test 63 0 "DELETE FROM node" 373fkey2-2-test 64 1 "INSERT INTO leaf VALUES('a', 1)" 374fkey2-2-test 65 1 "INSERT INTO leaf VALUES('b', 2)" 375fkey2-2-test 66 1 "INSERT INTO leaf VALUES('c', 1)" 376do_test fkey2-2-test-67 { 377 catchsql "INSERT INTO node SELECT parent, 3 FROM leaf" 378} {1 {UNIQUE constraint failed: node.nodeid}} 379fkey2-2-test 68 0 "COMMIT" FKV 380fkey2-2-test 69 1 "INSERT INTO node VALUES(1, NULL)" 381fkey2-2-test 70 0 "INSERT INTO node VALUES(2, NULL)" 382fkey2-2-test 71 0 "COMMIT" 383 384fkey2-2-test 72 0 "BEGIN" 385fkey2-2-test 73 1 "DELETE FROM node" 386fkey2-2-test 74 0 "INSERT INTO node(nodeid) SELECT DISTINCT parent FROM leaf" 387fkey2-2-test 75 0 "COMMIT" 388 389#------------------------------------------------------------------------- 390# Test cases fkey2-3.* test that a program that executes foreign key 391# actions (CASCADE, SET DEFAULT, SET NULL etc.) or tests FK constraints 392# opens a statement transaction if required. 393# 394# fkey2-3.1.*: Test UPDATE statements. 395# fkey2-3.2.*: Test DELETE statements. 396# 397drop_all_tables 398do_test fkey2-3.1.1 { 399 execsql { 400 CREATE TABLE ab(a PRIMARY KEY, b); 401 CREATE TABLE cd( 402 c PRIMARY KEY REFERENCES ab ON UPDATE CASCADE ON DELETE CASCADE, 403 d 404 ); 405 CREATE TABLE ef( 406 e REFERENCES cd ON UPDATE CASCADE, 407 f, CHECK (e!=5) 408 ); 409 } 410} {} 411do_test fkey2-3.1.2 { 412 execsql { 413 INSERT INTO ab VALUES(1, 'b'); 414 INSERT INTO cd VALUES(1, 'd'); 415 INSERT INTO ef VALUES(1, 'e'); 416 } 417} {} 418do_test fkey2-3.1.3 { 419 catchsql { UPDATE ab SET a = 5 } 420} {1 {CHECK constraint failed: ef}} 421do_test fkey2-3.1.4 { 422 execsql { SELECT * FROM ab } 423} {1 b} 424do_test fkey2-3.1.4 { 425 execsql BEGIN; 426 catchsql { UPDATE ab SET a = 5 } 427} {1 {CHECK constraint failed: ef}} 428do_test fkey2-3.1.5 { 429 execsql COMMIT; 430 execsql { SELECT * FROM ab; SELECT * FROM cd; SELECT * FROM ef } 431} {1 b 1 d 1 e} 432 433do_test fkey2-3.2.1 { 434 execsql BEGIN; 435 catchsql { DELETE FROM ab } 436} {1 {FOREIGN KEY constraint failed}} 437do_test fkey2-3.2.2 { 438 execsql COMMIT 439 execsql { SELECT * FROM ab; SELECT * FROM cd; SELECT * FROM ef } 440} {1 b 1 d 1 e} 441 442#------------------------------------------------------------------------- 443# Test cases fkey2-4.* test that recursive foreign key actions 444# (i.e. CASCADE) are allowed even if recursive triggers are disabled. 445# 446drop_all_tables 447do_test fkey2-4.1 { 448 execsql { 449 CREATE TABLE t1( 450 node PRIMARY KEY, 451 parent REFERENCES t1 ON DELETE CASCADE 452 ); 453 CREATE TABLE t2(node PRIMARY KEY, parent); 454 CREATE TRIGGER t2t AFTER DELETE ON t2 BEGIN 455 DELETE FROM t2 WHERE parent = old.node; 456 END; 457 INSERT INTO t1 VALUES(1, NULL); 458 INSERT INTO t1 VALUES(2, 1); 459 INSERT INTO t1 VALUES(3, 1); 460 INSERT INTO t1 VALUES(4, 2); 461 INSERT INTO t1 VALUES(5, 2); 462 INSERT INTO t1 VALUES(6, 3); 463 INSERT INTO t1 VALUES(7, 3); 464 INSERT INTO t2 SELECT * FROM t1; 465 } 466} {} 467do_test fkey2-4.2 { 468 execsql { PRAGMA recursive_triggers = off } 469 execsql { 470 BEGIN; 471 DELETE FROM t1 WHERE node = 1; 472 SELECT node FROM t1; 473 } 474} {} 475do_test fkey2-4.3 { 476 execsql { 477 DELETE FROM t2 WHERE node = 1; 478 SELECT node FROM t2; 479 ROLLBACK; 480 } 481} {4 5 6 7} 482do_test fkey2-4.4 { 483 execsql { PRAGMA recursive_triggers = on } 484 execsql { 485 BEGIN; 486 DELETE FROM t1 WHERE node = 1; 487 SELECT node FROM t1; 488 } 489} {} 490do_test fkey2-4.3 { 491 execsql { 492 DELETE FROM t2 WHERE node = 1; 493 SELECT node FROM t2; 494 ROLLBACK; 495 } 496} {} 497 498#------------------------------------------------------------------------- 499# Test cases fkey2-5.* verify that the incremental blob API may not 500# write to a foreign key column while foreign-keys are enabled. 501# 502drop_all_tables 503ifcapable incrblob { 504 do_test fkey2-5.1 { 505 execsql { 506 CREATE TABLE t1(a PRIMARY KEY, b); 507 CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1(a)); 508 INSERT INTO t1 VALUES('hello', 'world'); 509 INSERT INTO t2 VALUES('key', 'hello'); 510 } 511 } {} 512 do_test fkey2-5.2 { 513 set rc [catch { set fd [db incrblob t2 b 1] } msg] 514 list $rc $msg 515 } {1 {cannot open foreign key column for writing}} 516 do_test fkey2-5.3 { 517 set rc [catch { set fd [db incrblob -readonly t2 b 1] } msg] 518 close $fd 519 set rc 520 } {0} 521 do_test fkey2-5.4 { 522 execsql { PRAGMA foreign_keys = off } 523 set rc [catch { set fd [db incrblob t2 b 1] } msg] 524 close $fd 525 set rc 526 } {0} 527 do_test fkey2-5.5 { 528 execsql { PRAGMA foreign_keys = on } 529 } {} 530} 531 532drop_all_tables 533ifcapable vacuum { 534 do_test fkey2-6.1 { 535 execsql { 536 CREATE TABLE t1(a REFERENCES t2(c), b); 537 CREATE TABLE t2(c UNIQUE, b); 538 INSERT INTO t2 VALUES(1, 2); 539 INSERT INTO t1 VALUES(1, 2); 540 VACUUM; 541 } 542 } {} 543} 544 545#------------------------------------------------------------------------- 546# Test that it is possible to use an INTEGER PRIMARY KEY as the child key 547# of a foreign constraint. 548# 549drop_all_tables 550do_test fkey2-7.1 { 551 execsql { 552 CREATE TABLE t1(a PRIMARY KEY, b); 553 CREATE TABLE t2(c INTEGER PRIMARY KEY REFERENCES t1, b); 554 } 555} {} 556do_test fkey2-7.2 { 557 catchsql { INSERT INTO t2 VALUES(1, 'A'); } 558} {1 {FOREIGN KEY constraint failed}} 559do_test fkey2-7.3 { 560 execsql { 561 INSERT INTO t1 VALUES(1, 2); 562 INSERT INTO t1 VALUES(2, 3); 563 INSERT INTO t2 VALUES(1, 'A'); 564 } 565} {} 566do_test fkey2-7.4 { 567 execsql { UPDATE t2 SET c = 2 } 568} {} 569do_test fkey2-7.5 { 570 catchsql { UPDATE t2 SET c = 3 } 571} {1 {FOREIGN KEY constraint failed}} 572do_test fkey2-7.6 { 573 catchsql { DELETE FROM t1 WHERE a = 2 } 574} {1 {FOREIGN KEY constraint failed}} 575do_test fkey2-7.7 { 576 execsql { DELETE FROM t1 WHERE a = 1 } 577} {} 578do_test fkey2-7.8 { 579 catchsql { UPDATE t1 SET a = 3 } 580} {1 {FOREIGN KEY constraint failed}} 581do_test fkey2-7.9 { 582 catchsql { UPDATE t2 SET rowid = 3 } 583} {1 {FOREIGN KEY constraint failed}} 584 585#------------------------------------------------------------------------- 586# Test that it is not possible to enable/disable FK support while a 587# transaction is open. 588# 589drop_all_tables 590proc fkey2-8-test {tn zSql value} { 591 do_test fkey-2.8.$tn.1 [list execsql $zSql] {} 592 do_test fkey-2.8.$tn.2 { execsql "PRAGMA foreign_keys" } $value 593} 594fkey2-8-test 1 { PRAGMA foreign_keys = 0 } 0 595fkey2-8-test 2 { PRAGMA foreign_keys = 1 } 1 596fkey2-8-test 3 { BEGIN } 1 597fkey2-8-test 4 { PRAGMA foreign_keys = 0 } 1 598fkey2-8-test 5 { COMMIT } 1 599fkey2-8-test 6 { PRAGMA foreign_keys = 0 } 0 600fkey2-8-test 7 { BEGIN } 0 601fkey2-8-test 8 { PRAGMA foreign_keys = 1 } 0 602fkey2-8-test 9 { COMMIT } 0 603fkey2-8-test 10 { PRAGMA foreign_keys = 1 } 1 604fkey2-8-test 11 { PRAGMA foreign_keys = off } 0 605fkey2-8-test 12 { PRAGMA foreign_keys = on } 1 606fkey2-8-test 13 { PRAGMA foreign_keys = no } 0 607fkey2-8-test 14 { PRAGMA foreign_keys = yes } 1 608fkey2-8-test 15 { PRAGMA foreign_keys = false } 0 609fkey2-8-test 16 { PRAGMA foreign_keys = true } 1 610 611#------------------------------------------------------------------------- 612# The following tests, fkey2-9.*, test SET DEFAULT actions. 613# 614drop_all_tables 615do_test fkey2-9.1.1 { 616 execsql { 617 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 618 CREATE TABLE t2( 619 c INTEGER PRIMARY KEY, 620 d INTEGER DEFAULT 1 REFERENCES t1 ON DELETE SET DEFAULT 621 ); 622 DELETE FROM t1; 623 } 624} {} 625do_test fkey2-9.1.2 { 626 execsql { 627 INSERT INTO t1 VALUES(1, 'one'); 628 INSERT INTO t1 VALUES(2, 'two'); 629 INSERT INTO t2 VALUES(1, 2); 630 SELECT * FROM t2; 631 DELETE FROM t1 WHERE a = 2; 632 SELECT * FROM t2; 633 } 634} {1 2 1 1} 635do_test fkey2-9.1.3 { 636 execsql { 637 INSERT INTO t1 VALUES(2, 'two'); 638 UPDATE t2 SET d = 2; 639 DELETE FROM t1 WHERE a = 1; 640 SELECT * FROM t2; 641 } 642} {1 2} 643do_test fkey2-9.1.4 { 644 execsql { SELECT * FROM t1 } 645} {2 two} 646do_test fkey2-9.1.5 { 647 catchsql { DELETE FROM t1 } 648} {1 {FOREIGN KEY constraint failed}} 649 650do_test fkey2-9.2.1 { 651 execsql { 652 CREATE TABLE pp(a, b, c, PRIMARY KEY(b, c)); 653 CREATE TABLE cc(d DEFAULT 3, e DEFAULT 1, f DEFAULT 2, 654 FOREIGN KEY(f, d) REFERENCES pp 655 ON UPDATE SET DEFAULT 656 ON DELETE SET NULL 657 ); 658 INSERT INTO pp VALUES(1, 2, 3); 659 INSERT INTO pp VALUES(4, 5, 6); 660 INSERT INTO pp VALUES(7, 8, 9); 661 } 662} {} 663do_test fkey2-9.2.2 { 664 execsql { 665 INSERT INTO cc VALUES(6, 'A', 5); 666 INSERT INTO cc VALUES(6, 'B', 5); 667 INSERT INTO cc VALUES(9, 'A', 8); 668 INSERT INTO cc VALUES(9, 'B', 8); 669 UPDATE pp SET b = 1 WHERE a = 7; 670 SELECT * FROM cc; 671 } 672} {6 A 5 6 B 5 3 A 2 3 B 2} 673do_test fkey2-9.2.3 { 674 execsql { 675 DELETE FROM pp WHERE a = 4; 676 SELECT * FROM cc; 677 } 678} {{} A {} {} B {} 3 A 2 3 B 2} 679do_execsql_test fkey2-9.3.0 { 680 CREATE TABLE t3(x PRIMARY KEY REFERENCES t3 ON DELETE SET NULL); 681 INSERT INTO t3(x) VALUES(12345); 682 DROP TABLE t3; 683} {} 684 685#------------------------------------------------------------------------- 686# The following tests, fkey2-10.*, test "foreign key mismatch" and 687# other errors. 688# 689set tn 0 690foreach zSql [list { 691 CREATE TABLE p(a PRIMARY KEY, b); 692 CREATE TABLE c(x REFERENCES p(c)); 693} { 694 CREATE TABLE c(x REFERENCES v(y)); 695 CREATE VIEW v AS SELECT x AS y FROM c; 696} { 697 CREATE TABLE p(a, b, PRIMARY KEY(a, b)); 698 CREATE TABLE c(x REFERENCES p); 699} { 700 CREATE TABLE p(a COLLATE binary, b); 701 CREATE UNIQUE INDEX i ON p(a COLLATE nocase); 702 CREATE TABLE c(x REFERENCES p(a)); 703}] { 704 drop_all_tables 705 do_test fkey2-10.1.[incr tn] { 706 execsql $zSql 707 catchsql { INSERT INTO c DEFAULT VALUES } 708 } {/1 {foreign key mismatch - "c" referencing "."}/} 709} 710 711# "rowid" cannot be used as part of a child or parent key definition 712# unless it happens to be the name of an explicitly declared column. 713# 714do_test fkey2-10.2.1 { 715 drop_all_tables 716 catchsql { 717 CREATE TABLE t1(a PRIMARY KEY, b); 718 CREATE TABLE t2(c, d, FOREIGN KEY(rowid) REFERENCES t1(a)); 719 } 720} {1 {unknown column "rowid" in foreign key definition}} 721do_test fkey2-10.2.2 { 722 drop_all_tables 723 catchsql { 724 CREATE TABLE t1(a PRIMARY KEY, b); 725 CREATE TABLE t2(rowid, d, FOREIGN KEY(rowid) REFERENCES t1(a)); 726 } 727} {0 {}} 728do_test fkey2-10.2.1 { 729 drop_all_tables 730 catchsql { 731 CREATE TABLE t1(a, b); 732 CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(rowid)); 733 INSERT INTO t1(rowid, a, b) VALUES(1, 1, 1); 734 INSERT INTO t2 VALUES(1, 1); 735 } 736} {1 {foreign key mismatch - "t2" referencing "t1"}} 737do_test fkey2-10.2.2 { 738 drop_all_tables 739 catchsql { 740 CREATE TABLE t1(rowid PRIMARY KEY, b); 741 CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(rowid)); 742 INSERT INTO t1(rowid, b) VALUES(1, 1); 743 INSERT INTO t2 VALUES(1, 1); 744 } 745} {0 {}} 746 747 748#------------------------------------------------------------------------- 749# The following tests, fkey2-11.*, test CASCADE actions. 750# 751drop_all_tables 752do_test fkey2-11.1.1 { 753 execsql { 754 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, rowid, _rowid_, oid); 755 CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(a) ON UPDATE CASCADE); 756 757 INSERT INTO t1 VALUES(10, 100, 'abc', 'def', 'ghi'); 758 INSERT INTO t2 VALUES(10, 100); 759 UPDATE t1 SET a = 15; 760 SELECT * FROM t2; 761 } 762} {15 100} 763 764#------------------------------------------------------------------------- 765# The following tests, fkey2-12.*, test RESTRICT actions. 766# 767drop_all_tables 768do_test fkey2-12.1.1 { 769 execsql { 770 CREATE TABLE t1(a, b PRIMARY KEY); 771 CREATE TABLE t2( 772 x REFERENCES t1 ON UPDATE RESTRICT DEFERRABLE INITIALLY DEFERRED 773 ); 774 INSERT INTO t1 VALUES(1, 'one'); 775 INSERT INTO t1 VALUES(2, 'two'); 776 INSERT INTO t1 VALUES(3, 'three'); 777 } 778} {} 779do_test fkey2-12.1.2 { 780 execsql "BEGIN" 781 execsql "INSERT INTO t2 VALUES('two')" 782} {} 783do_test fkey2-12.1.3 { 784 execsql "UPDATE t1 SET b = 'four' WHERE b = 'one'" 785} {} 786do_test fkey2-12.1.4 { 787 catchsql "UPDATE t1 SET b = 'five' WHERE b = 'two'" 788} {1 {FOREIGN KEY constraint failed}} 789do_test fkey2-12.1.5 { 790 execsql "DELETE FROM t1 WHERE b = 'two'" 791} {} 792do_test fkey2-12.1.6 { 793 catchsql "COMMIT" 794} {1 {FOREIGN KEY constraint failed}} 795do_test fkey2-12.1.7 { 796 execsql { 797 INSERT INTO t1 VALUES(2, 'two'); 798 COMMIT; 799 } 800} {} 801 802drop_all_tables 803do_test fkey2-12.2.1 { 804 execsql { 805 CREATE TABLE t1(x COLLATE NOCASE PRIMARY KEY); 806 CREATE TRIGGER tt1 AFTER DELETE ON t1 807 WHEN EXISTS ( SELECT 1 FROM t2 WHERE old.x = y ) 808 BEGIN 809 INSERT INTO t1 VALUES(old.x); 810 END; 811 CREATE TABLE t2(y REFERENCES t1); 812 INSERT INTO t1 VALUES('A'); 813 INSERT INTO t1 VALUES('B'); 814 INSERT INTO t2 VALUES('a'); 815 INSERT INTO t2 VALUES('b'); 816 817 SELECT * FROM t1; 818 SELECT * FROM t2; 819 } 820} {A B a b} 821do_test fkey2-12.2.2 { 822 execsql { DELETE FROM t1 } 823 execsql { 824 SELECT * FROM t1; 825 SELECT * FROM t2; 826 } 827} {A B a b} 828do_test fkey2-12.2.3 { 829 execsql { 830 DROP TABLE t2; 831 CREATE TABLE t2(y REFERENCES t1 ON DELETE RESTRICT); 832 INSERT INTO t2 VALUES('a'); 833 INSERT INTO t2 VALUES('b'); 834 } 835 catchsql { DELETE FROM t1 } 836} {1 {FOREIGN KEY constraint failed}} 837do_test fkey2-12.2.4 { 838 execsql { 839 SELECT * FROM t1; 840 SELECT * FROM t2; 841 } 842} {A B a b} 843 844drop_all_tables 845do_test fkey2-12.3.1 { 846 execsql { 847 CREATE TABLE up( 848 c00, c01, c02, c03, c04, c05, c06, c07, c08, c09, 849 c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, 850 c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, 851 c30, c31, c32, c33, c34, c35, c36, c37, c38, c39, 852 PRIMARY KEY(c34, c35) 853 ); 854 CREATE TABLE down( 855 c00, c01, c02, c03, c04, c05, c06, c07, c08, c09, 856 c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, 857 c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, 858 c30, c31, c32, c33, c34, c35, c36, c37, c38, c39, 859 FOREIGN KEY(c39, c38) REFERENCES up ON UPDATE CASCADE 860 ); 861 } 862} {} 863do_test fkey2-12.3.2 { 864 execsql { 865 INSERT INTO up(c34, c35) VALUES('yes', 'no'); 866 INSERT INTO down(c39, c38) VALUES('yes', 'no'); 867 UPDATE up SET c34 = 'possibly'; 868 SELECT c38, c39 FROM down; 869 DELETE FROM down; 870 } 871} {no possibly} 872do_test fkey2-12.3.3 { 873 catchsql { INSERT INTO down(c39, c38) VALUES('yes', 'no') } 874} {1 {FOREIGN KEY constraint failed}} 875do_test fkey2-12.3.4 { 876 execsql { 877 INSERT INTO up(c34, c35) VALUES('yes', 'no'); 878 INSERT INTO down(c39, c38) VALUES('yes', 'no'); 879 } 880 catchsql { DELETE FROM up WHERE c34 = 'yes' } 881} {1 {FOREIGN KEY constraint failed}} 882do_test fkey2-12.3.5 { 883 execsql { 884 DELETE FROM up WHERE c34 = 'possibly'; 885 SELECT c34, c35 FROM up; 886 SELECT c39, c38 FROM down; 887 } 888} {yes no yes no} 889 890#------------------------------------------------------------------------- 891# The following tests, fkey2-13.*, test that FK processing is performed 892# when rows are REPLACEd. 893# 894drop_all_tables 895do_test fkey2-13.1.1 { 896 execsql { 897 CREATE TABLE pp(a UNIQUE, b, c, PRIMARY KEY(b, c)); 898 CREATE TABLE cc(d, e, f UNIQUE, FOREIGN KEY(d, e) REFERENCES pp); 899 INSERT INTO pp VALUES(1, 2, 3); 900 INSERT INTO cc VALUES(2, 3, 1); 901 } 902} {} 903foreach {tn stmt} { 904 1 "REPLACE INTO pp VALUES(1, 4, 5)" 905 2 "REPLACE INTO pp(rowid, a, b, c) VALUES(1, 2, 3, 4)" 906} { 907 do_test fkey2-13.1.$tn.1 { 908 catchsql $stmt 909 } {1 {FOREIGN KEY constraint failed}} 910 do_test fkey2-13.1.$tn.2 { 911 execsql { 912 SELECT * FROM pp; 913 SELECT * FROM cc; 914 } 915 } {1 2 3 2 3 1} 916 do_test fkey2-13.1.$tn.3 { 917 execsql BEGIN; 918 catchsql $stmt 919 } {1 {FOREIGN KEY constraint failed}} 920 do_test fkey2-13.1.$tn.4 { 921 execsql { 922 COMMIT; 923 SELECT * FROM pp; 924 SELECT * FROM cc; 925 } 926 } {1 2 3 2 3 1} 927} 928do_test fkey2-13.1.3 { 929 execsql { 930 REPLACE INTO pp(rowid, a, b, c) VALUES(1, 2, 2, 3); 931 SELECT rowid, * FROM pp; 932 SELECT * FROM cc; 933 } 934} {1 2 2 3 2 3 1} 935do_test fkey2-13.1.4 { 936 execsql { 937 REPLACE INTO pp(rowid, a, b, c) VALUES(2, 2, 2, 3); 938 SELECT rowid, * FROM pp; 939 SELECT * FROM cc; 940 } 941} {2 2 2 3 2 3 1} 942 943#------------------------------------------------------------------------- 944# The following tests, fkey2-14.*, test that the "DROP TABLE" and "ALTER 945# TABLE" commands work as expected wrt foreign key constraints. 946# 947# fkey2-14.1*: ALTER TABLE ADD COLUMN 948# fkey2-14.2*: ALTER TABLE RENAME TABLE 949# fkey2-14.3*: DROP TABLE 950# 951drop_all_tables 952ifcapable altertable { 953 do_test fkey2-14.1.1 { 954 # Adding a column with a REFERENCES clause is not supported. 955 execsql { 956 CREATE TABLE t1(a PRIMARY KEY); 957 CREATE TABLE t2(a, b); 958 } 959 catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } 960 } {0 {}} 961 do_test fkey2-14.1.2 { 962 catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 } 963 } {0 {}} 964 do_test fkey2-14.1.3 { 965 catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL} 966 } {0 {}} 967 do_test fkey2-14.1.4 { 968 catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'} 969 } {1 {Cannot add a REFERENCES column with non-NULL default value}} 970 do_test fkey2-14.1.5 { 971 catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 } 972 } {1 {Cannot add a REFERENCES column with non-NULL default value}} 973 do_test fkey2-14.1.6 { 974 execsql { 975 PRAGMA foreign_keys = off; 976 ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1; 977 PRAGMA foreign_keys = on; 978 SELECT sql FROM sqlite_master WHERE name='t2'; 979 } 980 } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} 981 982 983 # Test the sqlite_rename_parent() function directly. 984 # 985 proc test_rename_parent {zCreate zOld zNew} { 986 db eval {SELECT sqlite_rename_table( 987 'main', 'table', 't1', $zCreate, $zOld, $zNew, 0 988 )} 989 } 990 do_test fkey2-14.2.1.1 { 991 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 992 } {{CREATE TABLE t1(a REFERENCES "t3")}} 993 do_test fkey2-14.2.1.2 { 994 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 995 } {{CREATE TABLE t1(a REFERENCES t2)}} 996 do_test fkey2-14.2.1.3 { 997 test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 998 } {{CREATE TABLE t1(a REFERENCES "t3")}} 999 1000 # Test ALTER TABLE RENAME TABLE a bit. 1001 # 1002 do_test fkey2-14.2.2.1 { 1003 drop_all_tables 1004 execsql { 1005 CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1); 1006 CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2); 1007 CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1); 1008 } 1009 execsql { SELECT sql FROM sqlite_master WHERE type = 'table'} 1010 } [list \ 1011 {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)} \ 1012 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)} \ 1013 {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \ 1014 ] 1015 do_test fkey2-14.2.2.2 { 1016 execsql { ALTER TABLE t1 RENAME TO t4 } 1017 execsql { SELECT sql FROM sqlite_master WHERE type = 'table'} 1018 } [list \ 1019 {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")} \ 1020 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)} \ 1021 {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \ 1022 ] 1023 do_test fkey2-14.2.2.3 { 1024 catchsql { INSERT INTO t3 VALUES(1, 2, 3) } 1025 } {1 {FOREIGN KEY constraint failed}} 1026 do_test fkey2-14.2.2.4 { 1027 execsql { INSERT INTO t4 VALUES(1, NULL) } 1028 } {} 1029 do_test fkey2-14.2.2.5 { 1030 catchsql { UPDATE t4 SET b = 5 } 1031 } {1 {FOREIGN KEY constraint failed}} 1032 do_test fkey2-14.2.2.6 { 1033 catchsql { UPDATE t4 SET b = 1 } 1034 } {0 {}} 1035 do_test fkey2-14.2.2.7 { 1036 execsql { INSERT INTO t3 VALUES(1, NULL, 1) } 1037 } {} 1038 1039 # Repeat for TEMP tables 1040 # 1041 drop_all_tables 1042 do_test fkey2-14.1tmp.1 { 1043 # Adding a column with a REFERENCES clause is not supported. 1044 execsql { 1045 CREATE TEMP TABLE t1(a PRIMARY KEY); 1046 CREATE TEMP TABLE t2(a, b); 1047 } 1048 catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } 1049 } {0 {}} 1050 do_test fkey2-14.1tmp.2 { 1051 catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 } 1052 } {0 {}} 1053 do_test fkey2-14.1tmp.3 { 1054 catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL} 1055 } {0 {}} 1056 do_test fkey2-14.1tmp.4 { 1057 catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'} 1058 } {1 {Cannot add a REFERENCES column with non-NULL default value}} 1059 do_test fkey2-14.1tmp.5 { 1060 catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 } 1061 } {1 {Cannot add a REFERENCES column with non-NULL default value}} 1062 do_test fkey2-14.1tmp.6 { 1063 execsql { 1064 PRAGMA foreign_keys = off; 1065 ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1; 1066 PRAGMA foreign_keys = on; 1067 SELECT sql FROM temp.sqlite_master WHERE name='t2'; 1068 } 1069 } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} 1070 1071 do_test fkey2-14.2tmp.1.1 { 1072 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 1073 } {{CREATE TABLE t1(a REFERENCES "t3")}} 1074 do_test fkey2-14.2tmp.1.2 { 1075 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 1076 } {{CREATE TABLE t1(a REFERENCES t2)}} 1077 do_test fkey2-14.2tmp.1.3 { 1078 test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 1079 } {{CREATE TABLE t1(a REFERENCES "t3")}} 1080 1081 # Test ALTER TABLE RENAME TABLE a bit. 1082 # 1083 do_test fkey2-14.2tmp.2.1 { 1084 drop_all_tables 1085 execsql { 1086 CREATE TEMP TABLE t1(a PRIMARY KEY, b REFERENCES t1); 1087 CREATE TEMP TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2); 1088 CREATE TEMP TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1); 1089 } 1090 execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'} 1091 } [list \ 1092 {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)} \ 1093 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)} \ 1094 {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \ 1095 ] 1096 do_test fkey2-14.2tmp.2.2 { 1097 execsql { ALTER TABLE t1 RENAME TO t4 } 1098 execsql { SELECT sql FROM temp.sqlite_master WHERE type = 'table'} 1099 } [list \ 1100 {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")} \ 1101 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)} \ 1102 {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \ 1103 ] 1104 do_test fkey2-14.2tmp.2.3 { 1105 catchsql { INSERT INTO t3 VALUES(1, 2, 3) } 1106 } {1 {FOREIGN KEY constraint failed}} 1107 do_test fkey2-14.2tmp.2.4 { 1108 execsql { INSERT INTO t4 VALUES(1, NULL) } 1109 } {} 1110 do_test fkey2-14.2tmp.2.5 { 1111 catchsql { UPDATE t4 SET b = 5 } 1112 } {1 {FOREIGN KEY constraint failed}} 1113 do_test fkey2-14.2tmp.2.6 { 1114 catchsql { UPDATE t4 SET b = 1 } 1115 } {0 {}} 1116 do_test fkey2-14.2tmp.2.7 { 1117 execsql { INSERT INTO t3 VALUES(1, NULL, 1) } 1118 } {} 1119 1120 # Repeat for ATTACH-ed tables 1121 # 1122 drop_all_tables 1123 do_test fkey2-14.1aux.1 { 1124 # Adding a column with a REFERENCES clause is not supported. 1125 execsql { 1126 ATTACH ':memory:' AS aux; 1127 CREATE TABLE aux.t1(a PRIMARY KEY); 1128 CREATE TABLE aux.t2(a, b); 1129 } 1130 catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } 1131 } {0 {}} 1132 do_test fkey2-14.1aux.2 { 1133 catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 } 1134 } {0 {}} 1135 do_test fkey2-14.1aux.3 { 1136 catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL} 1137 } {0 {}} 1138 do_test fkey2-14.1aux.4 { 1139 catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'} 1140 } {1 {Cannot add a REFERENCES column with non-NULL default value}} 1141 do_test fkey2-14.1aux.5 { 1142 catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 } 1143 } {1 {Cannot add a REFERENCES column with non-NULL default value}} 1144 do_test fkey2-14.1aux.6 { 1145 execsql { 1146 PRAGMA foreign_keys = off; 1147 ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1; 1148 PRAGMA foreign_keys = on; 1149 SELECT sql FROM aux.sqlite_master WHERE name='t2'; 1150 } 1151 } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} 1152 1153 do_test fkey2-14.2aux.1.1 { 1154 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 1155 } {{CREATE TABLE t1(a REFERENCES "t3")}} 1156 do_test fkey2-14.2aux.1.2 { 1157 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 1158 } {{CREATE TABLE t1(a REFERENCES t2)}} 1159 do_test fkey2-14.2aux.1.3 { 1160 test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 1161 } {{CREATE TABLE t1(a REFERENCES "t3")}} 1162 1163 # Test ALTER TABLE RENAME TABLE a bit. 1164 # 1165 do_test fkey2-14.2aux.2.1 { 1166 drop_all_tables 1167 execsql { 1168 CREATE TABLE aux.t1(a PRIMARY KEY, b REFERENCES t1); 1169 CREATE TABLE aux.t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2); 1170 CREATE TABLE aux.t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1); 1171 } 1172 execsql { SELECT sql FROM aux.sqlite_master WHERE type = 'table'} 1173 } [list \ 1174 {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)} \ 1175 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)} \ 1176 {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \ 1177 ] 1178 do_test fkey2-14.2aux.2.2 { 1179 execsql { ALTER TABLE t1 RENAME TO t4 } 1180 execsql { SELECT sql FROM aux.sqlite_master WHERE type = 'table'} 1181 } [list \ 1182 {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")} \ 1183 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)} \ 1184 {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \ 1185 ] 1186 do_test fkey2-14.2aux.2.3 { 1187 catchsql { INSERT INTO t3 VALUES(1, 2, 3) } 1188 } {1 {FOREIGN KEY constraint failed}} 1189 do_test fkey2-14.2aux.2.4 { 1190 execsql { INSERT INTO t4 VALUES(1, NULL) } 1191 } {} 1192 do_test fkey2-14.2aux.2.5 { 1193 catchsql { UPDATE t4 SET b = 5 } 1194 } {1 {FOREIGN KEY constraint failed}} 1195 do_test fkey2-14.2aux.2.6 { 1196 catchsql { UPDATE t4 SET b = 1 } 1197 } {0 {}} 1198 do_test fkey2-14.2aux.2.7 { 1199 execsql { INSERT INTO t3 VALUES(1, NULL, 1) } 1200 } {} 1201} 1202 1203do_test fkey-2.14.3.1 { 1204 drop_all_tables 1205 execsql { 1206 CREATE TABLE t1(a, b REFERENCES nosuchtable); 1207 DROP TABLE t1; 1208 } 1209} {} 1210do_test fkey-2.14.3.2 { 1211 execsql { 1212 CREATE TABLE t1(a PRIMARY KEY, b); 1213 INSERT INTO t1 VALUES('a', 1); 1214 CREATE TABLE t2(x REFERENCES t1); 1215 INSERT INTO t2 VALUES('a'); 1216 } 1217} {} 1218do_test fkey-2.14.3.3 { 1219 catchsql { DROP TABLE t1 } 1220} {1 {FOREIGN KEY constraint failed}} 1221do_test fkey-2.14.3.4 { 1222 execsql { 1223 DELETE FROM t2; 1224 DROP TABLE t1; 1225 } 1226} {} 1227do_test fkey-2.14.3.4 { 1228 catchsql { INSERT INTO t2 VALUES('x') } 1229} {1 {no such table: main.t1}} 1230do_test fkey-2.14.3.5 { 1231 execsql { 1232 CREATE TABLE t1(x PRIMARY KEY); 1233 INSERT INTO t1 VALUES('x'); 1234 } 1235 execsql { INSERT INTO t2 VALUES('x') } 1236} {} 1237do_test fkey-2.14.3.6 { 1238 catchsql { DROP TABLE t1 } 1239} {1 {FOREIGN KEY constraint failed}} 1240do_test fkey-2.14.3.7 { 1241 execsql { 1242 DROP TABLE t2; 1243 DROP TABLE t1; 1244 } 1245} {} 1246do_test fkey-2.14.3.8 { 1247 execsql { 1248 CREATE TABLE pp(x, y, PRIMARY KEY(x, y)); 1249 CREATE TABLE cc(a, b, FOREIGN KEY(a, b) REFERENCES pp(x, z)); 1250 } 1251 catchsql { INSERT INTO cc VALUES(1, 2) } 1252} {1 {foreign key mismatch - "cc" referencing "pp"}} 1253do_test fkey-2.14.3.9 { 1254 execsql { DROP TABLE cc } 1255} {} 1256do_test fkey-2.14.3.10 { 1257 execsql { 1258 CREATE TABLE cc(a, b, 1259 FOREIGN KEY(a, b) REFERENCES pp DEFERRABLE INITIALLY DEFERRED 1260 ); 1261 } 1262 execsql { 1263 INSERT INTO pp VALUES('a', 'b'); 1264 INSERT INTO cc VALUES('a', 'b'); 1265 BEGIN; 1266 DROP TABLE pp; 1267 CREATE TABLE pp(a, b, c, PRIMARY KEY(b, c)); 1268 INSERT INTO pp VALUES(1, 'a', 'b'); 1269 COMMIT; 1270 } 1271} {} 1272do_test fkey-2.14.3.11 { 1273 execsql { 1274 BEGIN; 1275 DROP TABLE cc; 1276 DROP TABLE pp; 1277 COMMIT; 1278 } 1279} {} 1280do_test fkey-2.14.3.12 { 1281 execsql { 1282 CREATE TABLE b1(a, b); 1283 CREATE TABLE b2(a, b REFERENCES b1); 1284 DROP TABLE b1; 1285 } 1286} {} 1287do_test fkey-2.14.3.13 { 1288 execsql { 1289 CREATE TABLE b3(a, b REFERENCES b2 DEFERRABLE INITIALLY DEFERRED); 1290 DROP TABLE b2; 1291 } 1292} {} 1293 1294# Test that nothing goes wrong when dropping a table that refers to a view. 1295# Or dropping a view that an existing FK (incorrectly) refers to. Or either 1296# of the above scenarios with a virtual table. 1297drop_all_tables 1298do_test fkey-2.14.4.1 { 1299 execsql { 1300 CREATE TABLE t1(x REFERENCES v); 1301 CREATE VIEW v AS SELECT * FROM t1; 1302 } 1303} {} 1304do_test fkey-2.14.4.2 { 1305 execsql { 1306 DROP VIEW v; 1307 } 1308} {} 1309ifcapable vtab { 1310 register_echo_module db 1311 do_test fkey-2.14.4.3 { 1312 execsql { CREATE VIRTUAL TABLE v USING echo(t1) } 1313 } {} 1314 do_test fkey-2.14.4.2 { 1315 execsql { 1316 DROP TABLE v; 1317 } 1318 } {} 1319} 1320 1321#------------------------------------------------------------------------- 1322# The following tests, fkey2-15.*, test that unnecessary FK related scans 1323# and lookups are avoided when the constraint counters are zero. 1324# 1325drop_all_tables 1326proc execsqlS {zSql} { 1327 set ::sqlite_search_count 0 1328 set ::sqlite_found_count 0 1329 set res [uplevel [list execsql $zSql]] 1330 concat [expr $::sqlite_found_count + $::sqlite_search_count] $res 1331} 1332do_test fkey2-15.1.1 { 1333 execsql { 1334 CREATE TABLE pp(a PRIMARY KEY, b); 1335 CREATE TABLE cc(x, y REFERENCES pp DEFERRABLE INITIALLY DEFERRED); 1336 INSERT INTO pp VALUES(1, 'one'); 1337 INSERT INTO pp VALUES(2, 'two'); 1338 INSERT INTO cc VALUES('neung', 1); 1339 INSERT INTO cc VALUES('song', 2); 1340 } 1341} {} 1342do_test fkey2-15.1.2 { 1343 execsqlS { INSERT INTO pp VALUES(3, 'three') } 1344} {0} 1345do_test fkey2-15.1.3 { 1346 execsql { 1347 BEGIN; 1348 INSERT INTO cc VALUES('see', 4); -- Violates deferred constraint 1349 } 1350 execsqlS { INSERT INTO pp VALUES(5, 'five') } 1351} {2} 1352do_test fkey2-15.1.4 { 1353 execsql { DELETE FROM cc WHERE x = 'see' } 1354 execsqlS { INSERT INTO pp VALUES(6, 'six') } 1355} {0} 1356do_test fkey2-15.1.5 { 1357 execsql COMMIT 1358} {} 1359do_test fkey2-15.1.6 { 1360 execsql BEGIN 1361 execsqlS { 1362 DELETE FROM cc WHERE x = 'neung'; 1363 ROLLBACK; 1364 } 1365} {1} 1366do_test fkey2-15.1.7 { 1367 execsql { 1368 BEGIN; 1369 DELETE FROM pp WHERE a = 2; 1370 } 1371 execsqlS { 1372 DELETE FROM cc WHERE x = 'neung'; 1373 ROLLBACK; 1374 } 1375} {2} 1376 1377#------------------------------------------------------------------------- 1378# This next block of tests, fkey2-16.*, test that rows that refer to 1379# themselves may be inserted and deleted. 1380# 1381foreach {tn zSchema} { 1382 1 { CREATE TABLE self(a INTEGER PRIMARY KEY, b REFERENCES self(a)) } 1383 2 { CREATE TABLE self(a PRIMARY KEY, b REFERENCES self(a)) } 1384 3 { CREATE TABLE self(a UNIQUE, b INTEGER PRIMARY KEY REFERENCES self(a)) } 1385} { 1386 drop_all_tables 1387 do_test fkey2-16.1.$tn.1 { 1388 execsql $zSchema 1389 execsql { INSERT INTO self VALUES(13, 13) } 1390 } {} 1391 do_test fkey2-16.1.$tn.2 { 1392 execsql { UPDATE self SET a = 14, b = 14 } 1393 } {} 1394 1395 do_test fkey2-16.1.$tn.3 { 1396 catchsql { UPDATE self SET b = 15 } 1397 } {1 {FOREIGN KEY constraint failed}} 1398 1399 do_test fkey2-16.1.$tn.4 { 1400 catchsql { UPDATE self SET a = 15 } 1401 } {1 {FOREIGN KEY constraint failed}} 1402 1403 do_test fkey2-16.1.$tn.5 { 1404 catchsql { UPDATE self SET a = 15, b = 16 } 1405 } {1 {FOREIGN KEY constraint failed}} 1406 1407 do_test fkey2-16.1.$tn.6 { 1408 catchsql { UPDATE self SET a = 17, b = 17 } 1409 } {0 {}} 1410 1411 do_test fkey2-16.1.$tn.7 { 1412 execsql { DELETE FROM self } 1413 } {} 1414 do_test fkey2-16.1.$tn.8 { 1415 catchsql { INSERT INTO self VALUES(20, 21) } 1416 } {1 {FOREIGN KEY constraint failed}} 1417} 1418 1419#------------------------------------------------------------------------- 1420# This next block of tests, fkey2-17.*, tests that if "PRAGMA count_changes" 1421# is turned on statements that violate immediate FK constraints return 1422# SQLITE_CONSTRAINT immediately, not after returning a number of rows. 1423# Whereas statements that violate deferred FK constraints return the number 1424# of rows before failing. 1425# 1426# Also test that rows modified by FK actions are not counted in either the 1427# returned row count or the values returned by sqlite3_changes(). Like 1428# trigger related changes, they are included in sqlite3_total_changes() though. 1429# 1430drop_all_tables 1431do_test fkey2-17.1.1 { 1432 execsql { PRAGMA count_changes = 1 } 1433 execsql { 1434 CREATE TABLE one(a, b, c, UNIQUE(b, c)); 1435 CREATE TABLE two(d, e, f, FOREIGN KEY(e, f) REFERENCES one(b, c)); 1436 INSERT INTO one VALUES(1, 2, 3); 1437 } 1438} {1} 1439do_test fkey2-17.1.2 { 1440 set STMT [sqlite3_prepare_v2 db "INSERT INTO two VALUES(4, 5, 6)" -1 dummy] 1441 sqlite3_step $STMT 1442} {SQLITE_CONSTRAINT} 1443verify_ex_errcode fkey2-17.1.2b SQLITE_CONSTRAINT_FOREIGNKEY 1444ifcapable autoreset { 1445 do_test fkey2-17.1.3 { 1446 sqlite3_step $STMT 1447 } {SQLITE_CONSTRAINT} 1448 verify_ex_errcode fkey2-17.1.3b SQLITE_CONSTRAINT_FOREIGNKEY 1449} else { 1450 do_test fkey2-17.1.3 { 1451 sqlite3_step $STMT 1452 } {SQLITE_MISUSE} 1453} 1454do_test fkey2-17.1.4 { 1455 sqlite3_finalize $STMT 1456} {SQLITE_CONSTRAINT} 1457verify_ex_errcode fkey2-17.1.4b SQLITE_CONSTRAINT_FOREIGNKEY 1458do_test fkey2-17.1.5 { 1459 execsql { 1460 INSERT INTO one VALUES(2, 3, 4); 1461 INSERT INTO one VALUES(3, 4, 5); 1462 INSERT INTO two VALUES(1, 2, 3); 1463 INSERT INTO two VALUES(2, 3, 4); 1464 INSERT INTO two VALUES(3, 4, 5); 1465 } 1466} {1 1 1 1 1} 1467do_test fkey2-17.1.6 { 1468 catchsql { 1469 BEGIN; 1470 INSERT INTO one VALUES(0, 0, 0); 1471 UPDATE two SET e=e+1, f=f+1; 1472 } 1473} {1 {FOREIGN KEY constraint failed}} 1474do_test fkey2-17.1.7 { 1475 execsql { SELECT * FROM one } 1476} {1 2 3 2 3 4 3 4 5 0 0 0} 1477do_test fkey2-17.1.8 { 1478 execsql { SELECT * FROM two } 1479} {1 2 3 2 3 4 3 4 5} 1480do_test fkey2-17.1.9 { 1481 execsql COMMIT 1482} {} 1483do_test fkey2-17.1.10 { 1484 execsql { 1485 CREATE TABLE three( 1486 g, h, i, 1487 FOREIGN KEY(h, i) REFERENCES one(b, c) DEFERRABLE INITIALLY DEFERRED 1488 ); 1489 } 1490} {} 1491do_test fkey2-17.1.11 { 1492 set STMT [sqlite3_prepare_v2 db "INSERT INTO three VALUES(7, 8, 9)" -1 dummy] 1493 sqlite3_step $STMT 1494} {SQLITE_ROW} 1495do_test fkey2-17.1.12 { 1496 sqlite3_column_text $STMT 0 1497} {1} 1498do_test fkey2-17.1.13 { 1499 sqlite3_step $STMT 1500} {SQLITE_CONSTRAINT} 1501verify_ex_errcode fkey2-17.1.13b SQLITE_CONSTRAINT_FOREIGNKEY 1502do_test fkey2-17.1.14 { 1503 sqlite3_finalize $STMT 1504} {SQLITE_CONSTRAINT} 1505verify_ex_errcode fkey2-17.1.14b SQLITE_CONSTRAINT_FOREIGNKEY 1506 1507drop_all_tables 1508do_test fkey2-17.2.1 { 1509 execsql { 1510 CREATE TABLE high("a'b!" PRIMARY KEY, b); 1511 CREATE TABLE low( 1512 c, 1513 "d&6" REFERENCES high ON UPDATE CASCADE ON DELETE CASCADE 1514 ); 1515 } 1516} {} 1517do_test fkey2-17.2.2 { 1518 execsql { 1519 INSERT INTO high VALUES('a', 'b'); 1520 INSERT INTO low VALUES('b', 'a'); 1521 } 1522 db changes 1523} {1} 1524set nTotal [db total_changes] 1525do_test fkey2-17.2.3 { 1526 execsql { UPDATE high SET "a'b!" = 'c' } 1527} {1} 1528do_test fkey2-17.2.4 { 1529 db changes 1530} {1} 1531do_test fkey2-17.2.5 { 1532 expr [db total_changes] - $nTotal 1533} {2} 1534do_test fkey2-17.2.6 { 1535 execsql { SELECT * FROM high ; SELECT * FROM low } 1536} {c b b c} 1537do_test fkey2-17.2.7 { 1538 execsql { DELETE FROM high } 1539} {1} 1540do_test fkey2-17.2.8 { 1541 db changes 1542} {1} 1543do_test fkey2-17.2.9 { 1544 expr [db total_changes] - $nTotal 1545} {4} 1546do_test fkey2-17.2.10 { 1547 execsql { SELECT * FROM high ; SELECT * FROM low } 1548} {} 1549execsql { PRAGMA count_changes = 0 } 1550 1551#------------------------------------------------------------------------- 1552# Test that the authorization callback works. 1553# 1554 1555ifcapable auth { 1556 do_test fkey2-18.1 { 1557 execsql { 1558 CREATE TABLE long(a, b PRIMARY KEY, c); 1559 CREATE TABLE short(d, e, f REFERENCES long); 1560 CREATE TABLE mid(g, h, i REFERENCES long DEFERRABLE INITIALLY DEFERRED); 1561 } 1562 } {} 1563 1564 proc auth {args} {eval lappend ::authargs [lrange $args 0 4]; return SQLITE_OK} 1565 db auth auth 1566 1567 # An insert on the parent table must read the child key of any deferred 1568 # foreign key constraints. But not the child key of immediate constraints. 1569 set authargs {} 1570 do_test fkey2-18.2 { 1571 execsql { INSERT INTO long VALUES(1, 2, 3) } 1572 set authargs 1573 } {SQLITE_INSERT long {} main {} SQLITE_READ mid i main {}} 1574 1575 # An insert on the child table of an immediate constraint must read the 1576 # parent key columns (to see if it is a violation or not). 1577 set authargs {} 1578 do_test fkey2-18.3 { 1579 execsql { INSERT INTO short VALUES(1, 3, 2) } 1580 set authargs 1581 } {SQLITE_INSERT short {} main {} SQLITE_READ long b main {}} 1582 1583 # As must an insert on the child table of a deferred constraint. 1584 set authargs {} 1585 do_test fkey2-18.4 { 1586 execsql { INSERT INTO mid VALUES(1, 3, 2) } 1587 set authargs 1588 } {SQLITE_INSERT mid {} main {} SQLITE_READ long b main {}} 1589 1590 do_test fkey2-18.5 { 1591 execsql { 1592 CREATE TABLE nought(a, b PRIMARY KEY, c); 1593 CREATE TABLE cross(d, e, f, 1594 FOREIGN KEY(e) REFERENCES nought(b) ON UPDATE CASCADE 1595 ); 1596 } 1597 execsql { INSERT INTO nought VALUES(2, 1, 2) } 1598 execsql { INSERT INTO cross VALUES(0, 1, 0) } 1599 set authargs [list] 1600 execsql { UPDATE nought SET b = 5 } 1601 set authargs 1602 } {SQLITE_UPDATE nought b main {} SQLITE_READ cross e main {} SQLITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_UPDATE cross e main {} SQLITE_READ nought b main {} SQLITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {}} 1603 1604 do_test fkey2-18.6 { 1605 execsql {SELECT * FROM cross} 1606 } {0 5 0} 1607 1608 do_test fkey2-18.7 { 1609 execsql { 1610 CREATE TABLE one(a INTEGER PRIMARY KEY, b); 1611 CREATE TABLE two(b, c REFERENCES one); 1612 INSERT INTO one VALUES(101, 102); 1613 } 1614 set authargs [list] 1615 execsql { INSERT INTO two VALUES(100, 101); } 1616 set authargs 1617 } {SQLITE_INSERT two {} main {} SQLITE_READ one a main {}} 1618 1619 # Return SQLITE_IGNORE to requests to read from the parent table. This 1620 # causes inserts of non-NULL keys into the child table to fail. 1621 # 1622 rename auth {} 1623 proc auth {args} { 1624 if {[lindex $args 1] == "long"} {return SQLITE_IGNORE} 1625 return SQLITE_OK 1626 } 1627 do_test fkey2-18.8 { 1628 catchsql { INSERT INTO short VALUES(1, 3, 2) } 1629 } {1 {FOREIGN KEY constraint failed}} 1630 do_test fkey2-18.9 { 1631 execsql { INSERT INTO short VALUES(1, 3, NULL) } 1632 } {} 1633 do_test fkey2-18.10 { 1634 execsql { SELECT * FROM short } 1635 } {1 3 2 1 3 {}} 1636 do_test fkey2-18.11 { 1637 catchsql { UPDATE short SET f = 2 WHERE f IS NULL } 1638 } {1 {FOREIGN KEY constraint failed}} 1639 1640 db auth {} 1641 unset authargs 1642} 1643 1644 1645do_test fkey2-19.1 { 1646 execsql { 1647 CREATE TABLE main(id INTEGER PRIMARY KEY); 1648 CREATE TABLE sub(id INT REFERENCES main(id)); 1649 INSERT INTO main VALUES(1); 1650 INSERT INTO main VALUES(2); 1651 INSERT INTO sub VALUES(2); 1652 } 1653} {} 1654do_test fkey2-19.2 { 1655 set S [sqlite3_prepare_v2 db "DELETE FROM main WHERE id = ?" -1 dummy] 1656 sqlite3_bind_int $S 1 2 1657 sqlite3_step $S 1658} {SQLITE_CONSTRAINT} 1659verify_ex_errcode fkey2-19.2b SQLITE_CONSTRAINT_FOREIGNKEY 1660do_test fkey2-19.3 { 1661 sqlite3_reset $S 1662} {SQLITE_CONSTRAINT} 1663verify_ex_errcode fkey2-19.3b SQLITE_CONSTRAINT_FOREIGNKEY 1664do_test fkey2-19.4 { 1665 sqlite3_bind_int $S 1 1 1666 sqlite3_step $S 1667} {SQLITE_DONE} 1668do_test fkey2-19.4 { 1669 sqlite3_finalize $S 1670} {SQLITE_OK} 1671 1672drop_all_tables 1673do_test fkey2-20.1 { 1674 execsql { 1675 CREATE TABLE pp(a PRIMARY KEY, b); 1676 CREATE TABLE cc(c PRIMARY KEY, d REFERENCES pp); 1677 } 1678} {} 1679 1680foreach {tn insert} { 1681 1 "INSERT" 1682 2 "INSERT OR IGNORE" 1683 3 "INSERT OR ABORT" 1684 4 "INSERT OR ROLLBACK" 1685 5 "INSERT OR REPLACE" 1686 6 "INSERT OR FAIL" 1687} { 1688 do_test fkey2-20.2.$tn.1 { 1689 catchsql "$insert INTO cc VALUES(1, 2)" 1690 } {1 {FOREIGN KEY constraint failed}} 1691 do_test fkey2-20.2.$tn.2 { 1692 execsql { SELECT * FROM cc } 1693 } {} 1694 do_test fkey2-20.2.$tn.3 { 1695 execsql { 1696 BEGIN; 1697 INSERT INTO pp VALUES(2, 'two'); 1698 INSERT INTO cc VALUES(1, 2); 1699 } 1700 catchsql "$insert INTO cc VALUES(3, 4)" 1701 } {1 {FOREIGN KEY constraint failed}} 1702 do_test fkey2-20.2.$tn.4 { 1703 execsql { COMMIT ; SELECT * FROM cc } 1704 } {1 2} 1705 do_test fkey2-20.2.$tn.5 { 1706 execsql { DELETE FROM cc ; DELETE FROM pp } 1707 } {} 1708} 1709 1710foreach {tn update} { 1711 1 "UPDATE" 1712 2 "UPDATE OR IGNORE" 1713 3 "UPDATE OR ABORT" 1714 4 "UPDATE OR ROLLBACK" 1715 5 "UPDATE OR REPLACE" 1716 6 "UPDATE OR FAIL" 1717} { 1718 do_test fkey2-20.3.$tn.1 { 1719 execsql { 1720 INSERT INTO pp VALUES(2, 'two'); 1721 INSERT INTO cc VALUES(1, 2); 1722 } 1723 } {} 1724 do_test fkey2-20.3.$tn.2 { 1725 catchsql "$update pp SET a = 1" 1726 } {1 {FOREIGN KEY constraint failed}} 1727 do_test fkey2-20.3.$tn.3 { 1728 execsql { SELECT * FROM pp } 1729 } {2 two} 1730 do_test fkey2-20.3.$tn.4 { 1731 catchsql "$update cc SET d = 1" 1732 } {1 {FOREIGN KEY constraint failed}} 1733 do_test fkey2-20.3.$tn.5 { 1734 execsql { SELECT * FROM cc } 1735 } {1 2} 1736 do_test fkey2-20.3.$tn.6 { 1737 execsql { 1738 BEGIN; 1739 INSERT INTO pp VALUES(3, 'three'); 1740 } 1741 catchsql "$update pp SET a = 1 WHERE a = 2" 1742 } {1 {FOREIGN KEY constraint failed}} 1743 do_test fkey2-20.3.$tn.7 { 1744 execsql { COMMIT ; SELECT * FROM pp } 1745 } {2 two 3 three} 1746 do_test fkey2-20.3.$tn.8 { 1747 execsql { 1748 BEGIN; 1749 INSERT INTO cc VALUES(2, 2); 1750 } 1751 catchsql "$update cc SET d = 1 WHERE c = 1" 1752 } {1 {FOREIGN KEY constraint failed}} 1753 do_test fkey2-20.3.$tn.9 { 1754 execsql { COMMIT ; SELECT * FROM cc } 1755 } {1 2 2 2} 1756 do_test fkey2-20.3.$tn.10 { 1757 execsql { DELETE FROM cc ; DELETE FROM pp } 1758 } {} 1759} 1760 1761#------------------------------------------------------------------------- 1762# The following block of tests, those prefixed with "fkey2-genfkey.", are 1763# the same tests that were used to test the ".genfkey" command provided 1764# by the shell tool. So these tests show that the built-in foreign key 1765# implementation is more or less compatible with the triggers generated 1766# by genfkey. 1767# 1768drop_all_tables 1769do_test fkey2-genfkey.1.1 { 1770 execsql { 1771 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c)); 1772 CREATE TABLE t2(e REFERENCES t1, f); 1773 CREATE TABLE t3(g, h, i, FOREIGN KEY (h, i) REFERENCES t1(b, c)); 1774 } 1775} {} 1776do_test fkey2-genfkey.1.2 { 1777 catchsql { INSERT INTO t2 VALUES(1, 2) } 1778} {1 {FOREIGN KEY constraint failed}} 1779do_test fkey2-genfkey.1.3 { 1780 execsql { 1781 INSERT INTO t1 VALUES(1, 2, 3); 1782 INSERT INTO t2 VALUES(1, 2); 1783 } 1784} {} 1785do_test fkey2-genfkey.1.4 { 1786 execsql { INSERT INTO t2 VALUES(NULL, 3) } 1787} {} 1788do_test fkey2-genfkey.1.5 { 1789 catchsql { UPDATE t2 SET e = 5 WHERE e IS NULL } 1790} {1 {FOREIGN KEY constraint failed}} 1791do_test fkey2-genfkey.1.6 { 1792 execsql { UPDATE t2 SET e = 1 WHERE e IS NULL } 1793} {} 1794do_test fkey2-genfkey.1.7 { 1795 execsql { UPDATE t2 SET e = NULL WHERE f = 3 } 1796} {} 1797do_test fkey2-genfkey.1.8 { 1798 catchsql { UPDATE t1 SET a = 10 } 1799} {1 {FOREIGN KEY constraint failed}} 1800do_test fkey2-genfkey.1.9 { 1801 catchsql { UPDATE t1 SET a = NULL } 1802} {1 {datatype mismatch}} 1803do_test fkey2-genfkey.1.10 { 1804 catchsql { DELETE FROM t1 } 1805} {1 {FOREIGN KEY constraint failed}} 1806do_test fkey2-genfkey.1.11 { 1807 execsql { UPDATE t2 SET e = NULL } 1808} {} 1809do_test fkey2-genfkey.1.12 { 1810 execsql { 1811 UPDATE t1 SET a = 10; 1812 DELETE FROM t1; 1813 DELETE FROM t2; 1814 } 1815} {} 1816do_test fkey2-genfkey.1.13 { 1817 execsql { 1818 INSERT INTO t3 VALUES(1, NULL, NULL); 1819 INSERT INTO t3 VALUES(1, 2, NULL); 1820 INSERT INTO t3 VALUES(1, NULL, 3); 1821 } 1822} {} 1823do_test fkey2-genfkey.1.14 { 1824 catchsql { INSERT INTO t3 VALUES(3, 1, 4) } 1825} {1 {FOREIGN KEY constraint failed}} 1826do_test fkey2-genfkey.1.15 { 1827 execsql { 1828 INSERT INTO t1 VALUES(1, 1, 4); 1829 INSERT INTO t3 VALUES(3, 1, 4); 1830 } 1831} {} 1832do_test fkey2-genfkey.1.16 { 1833 catchsql { DELETE FROM t1 } 1834} {1 {FOREIGN KEY constraint failed}} 1835do_test fkey2-genfkey.1.17 { 1836 catchsql { UPDATE t1 SET b = 10} 1837} {1 {FOREIGN KEY constraint failed}} 1838do_test fkey2-genfkey.1.18 { 1839 execsql { UPDATE t1 SET a = 10} 1840} {} 1841do_test fkey2-genfkey.1.19 { 1842 catchsql { UPDATE t3 SET h = 'hello' WHERE i = 3} 1843} {1 {FOREIGN KEY constraint failed}} 1844 1845drop_all_tables 1846do_test fkey2-genfkey.2.1 { 1847 execsql { 1848 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c)); 1849 CREATE TABLE t2(e REFERENCES t1 ON UPDATE CASCADE ON DELETE CASCADE, f); 1850 CREATE TABLE t3(g, h, i, 1851 FOREIGN KEY (h, i) 1852 REFERENCES t1(b, c) ON UPDATE CASCADE ON DELETE CASCADE 1853 ); 1854 } 1855} {} 1856do_test fkey2-genfkey.2.2 { 1857 execsql { 1858 INSERT INTO t1 VALUES(1, 2, 3); 1859 INSERT INTO t1 VALUES(4, 5, 6); 1860 INSERT INTO t2 VALUES(1, 'one'); 1861 INSERT INTO t2 VALUES(4, 'four'); 1862 } 1863} {} 1864do_test fkey2-genfkey.2.3 { 1865 execsql { 1866 UPDATE t1 SET a = 2 WHERE a = 1; 1867 SELECT * FROM t2; 1868 } 1869} {2 one 4 four} 1870do_test fkey2-genfkey.2.4 { 1871 execsql { 1872 DELETE FROM t1 WHERE a = 4; 1873 SELECT * FROM t2; 1874 } 1875} {2 one} 1876 1877do_test fkey2-genfkey.2.5 { 1878 execsql { 1879 INSERT INTO t3 VALUES('hello', 2, 3); 1880 UPDATE t1 SET c = 2; 1881 SELECT * FROM t3; 1882 } 1883} {hello 2 2} 1884do_test fkey2-genfkey.2.6 { 1885 execsql { 1886 DELETE FROM t1; 1887 SELECT * FROM t3; 1888 } 1889} {} 1890 1891drop_all_tables 1892do_test fkey2-genfkey.3.1 { 1893 execsql { 1894 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(c, b)); 1895 CREATE TABLE t2(e REFERENCES t1 ON UPDATE SET NULL ON DELETE SET NULL, f); 1896 CREATE TABLE t3(g, h, i, 1897 FOREIGN KEY (h, i) 1898 REFERENCES t1(b, c) ON UPDATE SET NULL ON DELETE SET NULL 1899 ); 1900 } 1901} {} 1902do_test fkey2-genfkey.3.2 { 1903 execsql { 1904 INSERT INTO t1 VALUES(1, 2, 3); 1905 INSERT INTO t1 VALUES(4, 5, 6); 1906 INSERT INTO t2 VALUES(1, 'one'); 1907 INSERT INTO t2 VALUES(4, 'four'); 1908 } 1909} {} 1910do_test fkey2-genfkey.3.3 { 1911 execsql { 1912 UPDATE t1 SET a = 2 WHERE a = 1; 1913 SELECT * FROM t2; 1914 } 1915} {{} one 4 four} 1916do_test fkey2-genfkey.3.4 { 1917 execsql { 1918 DELETE FROM t1 WHERE a = 4; 1919 SELECT * FROM t2; 1920 } 1921} {{} one {} four} 1922do_test fkey2-genfkey.3.5 { 1923 execsql { 1924 INSERT INTO t3 VALUES('hello', 2, 3); 1925 UPDATE t1 SET c = 2; 1926 SELECT * FROM t3; 1927 } 1928} {hello {} {}} 1929do_test fkey2-genfkey.3.6 { 1930 execsql { 1931 UPDATE t3 SET h = 2, i = 2; 1932 DELETE FROM t1; 1933 SELECT * FROM t3; 1934 } 1935} {hello {} {}} 1936 1937#------------------------------------------------------------------------- 1938# Verify that ticket dd08e5a988d00decc4a543daa8dbbfab9c577ad8 has been 1939# fixed. 1940# 1941do_test fkey2-dd08e5.1.1 { 1942 execsql { 1943 PRAGMA foreign_keys=ON; 1944 CREATE TABLE tdd08(a INTEGER PRIMARY KEY, b); 1945 CREATE UNIQUE INDEX idd08 ON tdd08(a,b); 1946 INSERT INTO tdd08 VALUES(200,300); 1947 1948 CREATE TABLE tdd08_b(w,x,y, FOREIGN KEY(x,y) REFERENCES tdd08(a,b)); 1949 INSERT INTO tdd08_b VALUES(100,200,300); 1950 } 1951} {} 1952do_test fkey2-dd08e5.1.2 { 1953 catchsql { 1954 DELETE FROM tdd08; 1955 } 1956} {1 {FOREIGN KEY constraint failed}} 1957do_test fkey2-dd08e5.1.3 { 1958 execsql { 1959 SELECT * FROM tdd08; 1960 } 1961} {200 300} 1962do_test fkey2-dd08e5.1.4 { 1963 catchsql { 1964 INSERT INTO tdd08_b VALUES(400,500,300); 1965 } 1966} {1 {FOREIGN KEY constraint failed}} 1967do_test fkey2-dd08e5.1.5 { 1968 catchsql { 1969 UPDATE tdd08_b SET x=x+1; 1970 } 1971} {1 {FOREIGN KEY constraint failed}} 1972do_test fkey2-dd08e5.1.6 { 1973 catchsql { 1974 UPDATE tdd08 SET a=a+1; 1975 } 1976} {1 {FOREIGN KEY constraint failed}} 1977 1978#------------------------------------------------------------------------- 1979# Verify that ticket ce7c133ea6cc9ccdc1a60d80441f80b6180f5eba 1980# fixed. 1981# 1982do_test fkey2-ce7c13.1.1 { 1983 execsql { 1984 CREATE TABLE tce71(a INTEGER PRIMARY KEY, b); 1985 CREATE UNIQUE INDEX ice71 ON tce71(a,b); 1986 INSERT INTO tce71 VALUES(100,200); 1987 CREATE TABLE tce72(w, x, y, FOREIGN KEY(x,y) REFERENCES tce71(a,b)); 1988 INSERT INTO tce72 VALUES(300,100,200); 1989 UPDATE tce71 set b = 200 where a = 100; 1990 SELECT * FROM tce71, tce72; 1991 } 1992} {100 200 300 100 200} 1993do_test fkey2-ce7c13.1.2 { 1994 catchsql { 1995 UPDATE tce71 set b = 201 where a = 100; 1996 } 1997} {1 {FOREIGN KEY constraint failed}} 1998do_test fkey2-ce7c13.1.3 { 1999 catchsql { 2000 UPDATE tce71 set a = 101 where a = 100; 2001 } 2002} {1 {FOREIGN KEY constraint failed}} 2003do_test fkey2-ce7c13.1.4 { 2004 execsql { 2005 CREATE TABLE tce73(a INTEGER PRIMARY KEY, b, UNIQUE(a,b)); 2006 INSERT INTO tce73 VALUES(100,200); 2007 CREATE TABLE tce74(w, x, y, FOREIGN KEY(x,y) REFERENCES tce73(a,b)); 2008 INSERT INTO tce74 VALUES(300,100,200); 2009 UPDATE tce73 set b = 200 where a = 100; 2010 SELECT * FROM tce73, tce74; 2011 } 2012} {100 200 300 100 200} 2013do_test fkey2-ce7c13.1.5 { 2014 catchsql { 2015 UPDATE tce73 set b = 201 where a = 100; 2016 } 2017} {1 {FOREIGN KEY constraint failed}} 2018do_test fkey2-ce7c13.1.6 { 2019 catchsql { 2020 UPDATE tce73 set a = 101 where a = 100; 2021 } 2022} {1 {FOREIGN KEY constraint failed}} 2023 2024# 2015-04-16: Foreign key errors propagate back up to the parser. 2025# 2026do_test fkey2-20150416-100 { 2027 db close 2028 sqlite3 db :memory: 2029 catchsql { 2030 PRAGMA foreign_keys=1; 2031 CREATE TABLE t1(x PRIMARY KEY); 2032 CREATE TABLE t(y REFERENCES t0(x)ON DELETE SET DEFAULT); 2033 CREATE TABLE t0(y REFERENCES t1 ON DELETE SET NULL); 2034 REPLACE INTO t1 SELECT(0);CREATE TABLE t2(x);CREATE TABLE t3; 2035 } 2036} {1 {foreign key mismatch - "t" referencing "t0"}} 2037 2038finish_test 2039