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