Annotation of embedaddon/sqlite3/test/e_fkey.test, revision 1.1.1.1

1.1       misho       1: # 2009 October 7
                      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: #
                     12: # This file implements tests to verify the "testable statements" in the
                     13: # foreignkeys.in document.
                     14: #
                     15: # The tests in this file are arranged to mirror the structure of 
                     16: # foreignkey.in, with one exception: The statements in section 2, which 
                     17: # deals with enabling/disabling foreign key support, is tested first,
                     18: # before section 1. This is because some statements in section 2 deal
                     19: # with builds that do not include complete foreign key support (because
                     20: # either SQLITE_OMIT_TRIGGER or SQLITE_OMIT_FOREIGN_KEY was defined
                     21: # at build time).
                     22: #
                     23: 
                     24: set testdir [file dirname $argv0]
                     25: source $testdir/tester.tcl
                     26: 
                     27: proc eqp {sql {db db}} { uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db }
                     28: 
                     29: ###########################################################################
                     30: ### SECTION 2: Enabling Foreign Key Support
                     31: ###########################################################################
                     32: 
                     33: #-------------------------------------------------------------------------
                     34: # EVIDENCE-OF: R-33710-56344 In order to use foreign key constraints in
                     35: # SQLite, the library must be compiled with neither
                     36: # SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER defined.
                     37: #
                     38: ifcapable trigger&&foreignkey {
                     39:   do_test e_fkey-1 {
                     40:     execsql {
                     41:       PRAGMA foreign_keys = ON;
                     42:       CREATE TABLE p(i PRIMARY KEY);
                     43:       CREATE TABLE c(j REFERENCES p ON UPDATE CASCADE);
                     44:       INSERT INTO p VALUES('hello');
                     45:       INSERT INTO c VALUES('hello');
                     46:       UPDATE p SET i = 'world';
                     47:       SELECT * FROM c;
                     48:     }
                     49:   } {world}
                     50: }
                     51: 
                     52: #-------------------------------------------------------------------------
                     53: # Test the effects of defining OMIT_TRIGGER but not OMIT_FOREIGN_KEY.
                     54: #
                     55: # EVIDENCE-OF: R-44697-61543 If SQLITE_OMIT_TRIGGER is defined but
                     56: # SQLITE_OMIT_FOREIGN_KEY is not, then SQLite behaves as it did prior to
                     57: # version 3.6.19 - foreign key definitions are parsed and may be queried
                     58: # using PRAGMA foreign_key_list, but foreign key constraints are not
                     59: # enforced.
                     60: #
                     61: # Specifically, test that "PRAGMA foreign_keys" is a no-op in this case.
                     62: # When using the pragma to query the current setting, 0 rows are returned.
                     63: #
                     64: # EVIDENCE-OF: R-22567-44039 The PRAGMA foreign_keys command is a no-op
                     65: # in this configuration.
                     66: #
                     67: # EVIDENCE-OF: R-41784-13339 Tip: If the command "PRAGMA foreign_keys"
                     68: # returns no data instead of a single row containing "0" or "1", then
                     69: # the version of SQLite you are using does not support foreign keys
                     70: # (either because it is older than 3.6.19 or because it was compiled
                     71: # with SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER defined).
                     72: #
                     73: reset_db
                     74: ifcapable !trigger&&foreignkey {
                     75:   do_test e_fkey-2.1 {
                     76:     execsql {
                     77:       PRAGMA foreign_keys = ON;
                     78:       CREATE TABLE p(i PRIMARY KEY);
                     79:       CREATE TABLE c(j REFERENCES p ON UPDATE CASCADE);
                     80:       INSERT INTO p VALUES('hello');
                     81:       INSERT INTO c VALUES('hello');
                     82:       UPDATE p SET i = 'world';
                     83:       SELECT * FROM c;
                     84:     }
                     85:   } {hello}
                     86:   do_test e_fkey-2.2 {
                     87:     execsql { PRAGMA foreign_key_list(c) }
                     88:   } {0 0 p j {} CASCADE {NO ACTION} NONE}
                     89:   do_test e_fkey-2.3 {
                     90:     execsql { PRAGMA foreign_keys }
                     91:   } {}
                     92: }
                     93: 
                     94: 
                     95: #-------------------------------------------------------------------------
                     96: # Test the effects of defining OMIT_FOREIGN_KEY.
                     97: #
                     98: # EVIDENCE-OF: R-58428-36660 If OMIT_FOREIGN_KEY is defined, then
                     99: # foreign key definitions cannot even be parsed (attempting to specify a
                    100: # foreign key definition is a syntax error).
                    101: #
                    102: # Specifically, test that foreign key constraints cannot even be parsed 
                    103: # in such a build.
                    104: #
                    105: reset_db
                    106: ifcapable !foreignkey {
                    107:   do_test e_fkey-3.1 {
                    108:     execsql { CREATE TABLE p(i PRIMARY KEY) }
                    109:     catchsql { CREATE TABLE c(j REFERENCES p ON UPDATE CASCADE) }
                    110:   } {1 {near "ON": syntax error}}
                    111:   do_test e_fkey-3.2 {
                    112:     # This is allowed, as in this build, "REFERENCES" is not a keyword.
                    113:     # The declared datatype of column j is "REFERENCES p".
                    114:     execsql { CREATE TABLE c(j REFERENCES p) }
                    115:   } {}
                    116:   do_test e_fkey-3.3 {
                    117:     execsql { PRAGMA table_info(c) }
                    118:   } {0 j {REFERENCES p} 0 {} 0}
                    119:   do_test e_fkey-3.4 {
                    120:     execsql { PRAGMA foreign_key_list(c) }
                    121:   } {}
                    122:   do_test e_fkey-3.5 {
                    123:     execsql { PRAGMA foreign_keys }
                    124:   } {}
                    125: }
                    126: 
                    127: ifcapable !foreignkey||!trigger { finish_test ; return }
                    128: reset_db
                    129: 
                    130: 
                    131: #-------------------------------------------------------------------------
                    132: # EVIDENCE-OF: R-07280-60510 Assuming the library is compiled with
                    133: # foreign key constraints enabled, it must still be enabled by the
                    134: # application at runtime, using the PRAGMA foreign_keys command.
                    135: #
                    136: # This also tests that foreign key constraints are disabled by default.
                    137: #
                    138: # EVIDENCE-OF: R-59578-04990 Foreign key constraints are disabled by
                    139: # default (for backwards compatibility), so must be enabled separately
                    140: # for each database connection separately.
                    141: #
                    142: drop_all_tables
                    143: do_test e_fkey-4.1 {
                    144:   execsql {
                    145:     CREATE TABLE p(i PRIMARY KEY);
                    146:     CREATE TABLE c(j REFERENCES p ON UPDATE CASCADE);
                    147:     INSERT INTO p VALUES('hello');
                    148:     INSERT INTO c VALUES('hello');
                    149:     UPDATE p SET i = 'world';
                    150:     SELECT * FROM c;
                    151:   } 
                    152: } {hello}
                    153: do_test e_fkey-4.2 {
                    154:   execsql {
                    155:     DELETE FROM c;
                    156:     DELETE FROM p;
                    157:     PRAGMA foreign_keys = ON;
                    158:     INSERT INTO p VALUES('hello');
                    159:     INSERT INTO c VALUES('hello');
                    160:     UPDATE p SET i = 'world';
                    161:     SELECT * FROM c;
                    162:   } 
                    163: } {world}
                    164: 
                    165: #-------------------------------------------------------------------------
                    166: # EVIDENCE-OF: R-15278-54456 The application can can also use a PRAGMA
                    167: # foreign_keys statement to determine if foreign keys are currently
                    168: # enabled.
                    169: #
                    170: # This also tests the example code in section 2 of foreignkeys.in.
                    171: #
                    172: # EVIDENCE-OF: R-11255-19907
                    173: # 
                    174: reset_db
                    175: do_test e_fkey-5.1 {
                    176:   execsql { PRAGMA foreign_keys }
                    177: } {0}
                    178: do_test e_fkey-5.2 {
                    179:   execsql { 
                    180:     PRAGMA foreign_keys = ON;
                    181:     PRAGMA foreign_keys;
                    182:   }
                    183: } {1}
                    184: do_test e_fkey-5.3 {
                    185:   execsql { 
                    186:     PRAGMA foreign_keys = OFF;
                    187:     PRAGMA foreign_keys;
                    188:   }
                    189: } {0}
                    190: 
                    191: #-------------------------------------------------------------------------
                    192: # Test that it is not possible to enable or disable foreign key support
                    193: # while not in auto-commit mode.
                    194: #
                    195: # EVIDENCE-OF: R-46649-58537 It is not possible to enable or disable
                    196: # foreign key constraints in the middle of a multi-statement transaction
                    197: # (when SQLite is not in autocommit mode). Attempting to do so does not
                    198: # return an error; it simply has no effect.
                    199: #
                    200: reset_db
                    201: do_test e_fkey-6.1 {
                    202:   execsql {
                    203:     PRAGMA foreign_keys = ON;
                    204:     CREATE TABLE t1(a UNIQUE, b);
                    205:     CREATE TABLE t2(c, d REFERENCES t1(a));
                    206:     INSERT INTO t1 VALUES(1, 2);
                    207:     INSERT INTO t2 VALUES(2, 1);
                    208:     BEGIN;
                    209:       PRAGMA foreign_keys = OFF;
                    210:   }
                    211:   catchsql {
                    212:       DELETE FROM t1
                    213:   }
                    214: } {1 {foreign key constraint failed}}
                    215: do_test e_fkey-6.2 {
                    216:   execsql { PRAGMA foreign_keys }
                    217: } {1}
                    218: do_test e_fkey-6.3 {
                    219:   execsql {
                    220:     COMMIT;
                    221:     PRAGMA foreign_keys = OFF;
                    222:     BEGIN;
                    223:       PRAGMA foreign_keys = ON;
                    224:       DELETE FROM t1;
                    225:       PRAGMA foreign_keys;
                    226:   }
                    227: } {0}
                    228: do_test e_fkey-6.4 {
                    229:   execsql COMMIT
                    230: } {}
                    231: 
                    232: ###########################################################################
                    233: ### SECTION 1: Introduction to Foreign Key Constraints
                    234: ###########################################################################
                    235: execsql "PRAGMA foreign_keys = ON"
                    236: 
                    237: #-------------------------------------------------------------------------
                    238: # Verify that the syntax in the first example in section 1 is valid.
                    239: #
                    240: # EVIDENCE-OF: R-04042-24825 To do so, a foreign key definition may be
                    241: # added by modifying the declaration of the track table to the
                    242: # following: CREATE TABLE track( trackid INTEGER, trackname TEXT,
                    243: # trackartist INTEGER, FOREIGN KEY(trackartist) REFERENCES
                    244: # artist(artistid) );
                    245: #
                    246: do_test e_fkey-7.1 {
                    247:   execsql {
                    248:     CREATE TABLE artist(
                    249:       artistid    INTEGER PRIMARY KEY, 
                    250:       artistname  TEXT
                    251:     );
                    252:     CREATE TABLE track(
                    253:       trackid     INTEGER, 
                    254:       trackname   TEXT, 
                    255:       trackartist INTEGER,
                    256:       FOREIGN KEY(trackartist) REFERENCES artist(artistid)
                    257:     );
                    258:   }
                    259: } {}
                    260: 
                    261: #-------------------------------------------------------------------------
                    262: # EVIDENCE-OF: R-61362-32087 Attempting to insert a row into the track
                    263: # table that does not correspond to any row in the artist table will
                    264: # fail,
                    265: #
                    266: do_test e_fkey-8.1 {
                    267:   catchsql { INSERT INTO track VALUES(1, 'track 1', 1) }
                    268: } {1 {foreign key constraint failed}}
                    269: do_test e_fkey-8.2 {
                    270:   execsql { INSERT INTO artist VALUES(2, 'artist 1') }
                    271:   catchsql { INSERT INTO track VALUES(1, 'track 1', 1) }
                    272: } {1 {foreign key constraint failed}}
                    273: do_test e_fkey-8.2 {
                    274:   execsql { INSERT INTO track VALUES(1, 'track 1', 2) }
                    275: } {}
                    276: 
                    277: #-------------------------------------------------------------------------
                    278: # Attempting to delete a row from the 'artist' table while there are 
                    279: # dependent rows in the track table also fails.
                    280: #
                    281: # EVIDENCE-OF: R-24401-52400 as will attempting to delete a row from the
                    282: # artist table when there exist dependent rows in the track table
                    283: #
                    284: do_test e_fkey-9.1 {
                    285:   catchsql { DELETE FROM artist WHERE artistid = 2 }
                    286: } {1 {foreign key constraint failed}}
                    287: do_test e_fkey-9.2 {
                    288:   execsql { 
                    289:     DELETE FROM track WHERE trackartist = 2;
                    290:     DELETE FROM artist WHERE artistid = 2;
                    291:   }
                    292: } {}
                    293: 
                    294: #-------------------------------------------------------------------------
                    295: # If the foreign key column (trackartist) in table 'track' is set to NULL,
                    296: # there is no requirement for a matching row in the 'artist' table.
                    297: #
                    298: # EVIDENCE-OF: R-23980-48859 There is one exception: if the foreign key
                    299: # column in the track table is NULL, then no corresponding entry in the
                    300: # artist table is required.
                    301: #
                    302: do_test e_fkey-10.1 {
                    303:   execsql {
                    304:     INSERT INTO track VALUES(1, 'track 1', NULL);
                    305:     INSERT INTO track VALUES(2, 'track 2', NULL);
                    306:   }
                    307: } {}
                    308: do_test e_fkey-10.2 {
                    309:   execsql { SELECT * FROM artist }
                    310: } {}
                    311: do_test e_fkey-10.3 {
                    312:   # Setting the trackid to a non-NULL value fails, of course.
                    313:   catchsql { UPDATE track SET trackartist = 5 WHERE trackid = 1 }
                    314: } {1 {foreign key constraint failed}}
                    315: do_test e_fkey-10.4 {
                    316:   execsql {
                    317:     INSERT INTO artist VALUES(5, 'artist 5');
                    318:     UPDATE track SET trackartist = 5 WHERE trackid = 1;
                    319:   }
                    320:   catchsql { DELETE FROM artist WHERE artistid = 5}
                    321: } {1 {foreign key constraint failed}}
                    322: do_test e_fkey-10.5 {
                    323:   execsql { 
                    324:     UPDATE track SET trackartist = NULL WHERE trackid = 1;
                    325:     DELETE FROM artist WHERE artistid = 5;
                    326:   }
                    327: } {}
                    328: 
                    329: #-------------------------------------------------------------------------
                    330: # Test that the following is true fo all rows in the track table:
                    331: #
                    332: #   trackartist IS NULL OR 
                    333: #   EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist)
                    334: #
                    335: # EVIDENCE-OF: R-52486-21352 Expressed in SQL, this means that for every
                    336: # row in the track table, the following expression evaluates to true:
                    337: # trackartist IS NULL OR EXISTS(SELECT 1 FROM artist WHERE
                    338: # artistid=trackartist)
                    339: 
                    340: # This procedure executes a test case to check that statement 
                    341: # R-52486-21352 is true after executing the SQL statement passed.
                    342: # as the second argument.
                    343: proc test_r52486_21352 {tn sql} {
                    344:   set res [catchsql $sql]
                    345:   set results {
                    346:     {0 {}} 
                    347:     {1 {PRIMARY KEY must be unique}} 
                    348:     {1 {foreign key constraint failed}}
                    349:   }
                    350:   if {[lsearch $results $res]<0} {
                    351:     error $res
                    352:   }
                    353: 
                    354:   do_test e_fkey-11.$tn {
                    355:     execsql {
                    356:       SELECT count(*) FROM track WHERE NOT (
                    357:         trackartist IS NULL OR 
                    358:         EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist)
                    359:       )
                    360:     }
                    361:   } {0}
                    362: }
                    363: 
                    364: # Execute a series of random INSERT, UPDATE and DELETE operations
                    365: # (some of which may fail due to FK or PK constraint violations) on 
                    366: # the two tables in the example schema. Test that R-52486-21352
                    367: # is true after executing each operation.
                    368: #
                    369: set Template {
                    370:   {INSERT INTO track VALUES($t, 'track $t', $a)}
                    371:   {DELETE FROM track WHERE trackid = $t}
                    372:   {UPDATE track SET trackartist = $a WHERE trackid = $t}
                    373:   {INSERT INTO artist VALUES($a, 'artist $a')}
                    374:   {DELETE FROM artist WHERE artistid = $a}
                    375:   {UPDATE artist SET artistid = $a2 WHERE artistid = $a}
                    376: }
                    377: for {set i 0} {$i < 500} {incr i} {
                    378:   set a   [expr int(rand()*10)]
                    379:   set a2  [expr int(rand()*10)]
                    380:   set t   [expr int(rand()*50)]
                    381:   set sql [subst [lindex $Template [expr int(rand()*6)]]]
                    382: 
                    383:   test_r52486_21352 $i $sql
                    384: }
                    385: 
                    386: #-------------------------------------------------------------------------
                    387: # Check that a NOT NULL constraint can be added to the example schema
                    388: # to prohibit NULL child keys from being inserted.
                    389: #
                    390: # EVIDENCE-OF: R-42412-59321 Tip: If the application requires a stricter
                    391: # relationship between artist and track, where NULL values are not
                    392: # permitted in the trackartist column, simply add the appropriate "NOT
                    393: # NULL" constraint to the schema.
                    394: #
                    395: drop_all_tables
                    396: do_test e_fkey-12.1 {
                    397:   execsql {
                    398:     CREATE TABLE artist(
                    399:       artistid    INTEGER PRIMARY KEY, 
                    400:       artistname  TEXT
                    401:     );
                    402:     CREATE TABLE track(
                    403:       trackid     INTEGER, 
                    404:       trackname   TEXT, 
                    405:       trackartist INTEGER NOT NULL,
                    406:       FOREIGN KEY(trackartist) REFERENCES artist(artistid)
                    407:     );
                    408:   }
                    409: } {}
                    410: do_test e_fkey-12.2 {
                    411:   catchsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL) }
                    412: } {1 {track.trackartist may not be NULL}}
                    413: 
                    414: #-------------------------------------------------------------------------
                    415: # EVIDENCE-OF: R-16127-35442
                    416: #
                    417: # Test an example from foreignkeys.html.
                    418: #
                    419: drop_all_tables
                    420: do_test e_fkey-13.1 {
                    421:   execsql {
                    422:     CREATE TABLE artist(
                    423:       artistid    INTEGER PRIMARY KEY, 
                    424:       artistname  TEXT
                    425:     );
                    426:     CREATE TABLE track(
                    427:       trackid     INTEGER, 
                    428:       trackname   TEXT, 
                    429:       trackartist INTEGER,
                    430:       FOREIGN KEY(trackartist) REFERENCES artist(artistid)
                    431:     );
                    432:     INSERT INTO artist VALUES(1, 'Dean Martin');
                    433:     INSERT INTO artist VALUES(2, 'Frank Sinatra');
                    434:     INSERT INTO track VALUES(11, 'That''s Amore', 1);
                    435:     INSERT INTO track VALUES(12, 'Christmas Blues', 1);
                    436:     INSERT INTO track VALUES(13, 'My Way', 2);
                    437:   }
                    438: } {}
                    439: do_test e_fkey-13.2 {
                    440:   catchsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', 3) }
                    441: } {1 {foreign key constraint failed}}
                    442: do_test e_fkey-13.3 {
                    443:   execsql { INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL) }
                    444: } {}
                    445: do_test e_fkey-13.4 {
                    446:   catchsql { 
                    447:     UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles';
                    448:   }
                    449: } {1 {foreign key constraint failed}}
                    450: do_test e_fkey-13.5 {
                    451:   execsql {
                    452:     INSERT INTO artist VALUES(3, 'Sammy Davis Jr.');
                    453:     UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles';
                    454:     INSERT INTO track VALUES(15, 'Boogie Woogie', 3);
                    455:   }
                    456: } {}
                    457: 
                    458: #-------------------------------------------------------------------------
                    459: # EVIDENCE-OF: R-15958-50233
                    460: #
                    461: # Test the second example from the first section of foreignkeys.html.
                    462: #
                    463: do_test e_fkey-14.1 {
                    464:   catchsql {
                    465:     DELETE FROM artist WHERE artistname = 'Frank Sinatra';
                    466:   }
                    467: } {1 {foreign key constraint failed}}
                    468: do_test e_fkey-14.2 {
                    469:   execsql {
                    470:     DELETE FROM track WHERE trackname = 'My Way';
                    471:     DELETE FROM artist WHERE artistname = 'Frank Sinatra';
                    472:   }
                    473: } {}
                    474: do_test e_fkey-14.3 {
                    475:   catchsql {
                    476:     UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin';
                    477:   }
                    478: } {1 {foreign key constraint failed}}
                    479: do_test e_fkey-14.4 {
                    480:   execsql {
                    481:     DELETE FROM track WHERE trackname IN('That''s Amore', 'Christmas Blues');
                    482:     UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin';
                    483:   }
                    484: } {}
                    485: 
                    486: 
                    487: #-------------------------------------------------------------------------
                    488: # EVIDENCE-OF: R-56032-24923 The foreign key constraint is satisfied if
                    489: # for each row in the child table either one or more of the child key
                    490: # columns are NULL, or there exists a row in the parent table for which
                    491: # each parent key column contains a value equal to the value in its
                    492: # associated child key column.
                    493: #
                    494: # Test also that the usual comparison rules are used when testing if there 
                    495: # is a matching row in the parent table of a foreign key constraint.
                    496: #
                    497: # EVIDENCE-OF: R-57765-12380 In the above paragraph, the term "equal"
                    498: # means equal when values are compared using the rules specified here.
                    499: #
                    500: drop_all_tables
                    501: do_test e_fkey-15.1 {
                    502:   execsql {
                    503:     CREATE TABLE par(p PRIMARY KEY);
                    504:     CREATE TABLE chi(c REFERENCES par);
                    505: 
                    506:     INSERT INTO par VALUES(1);
                    507:     INSERT INTO par VALUES('1');
                    508:     INSERT INTO par VALUES(X'31');
                    509:     SELECT typeof(p) FROM par;
                    510:   }
                    511: } {integer text blob}
                    512: 
                    513: proc test_efkey_45 {tn isError sql} {
                    514:   do_test e_fkey-15.$tn.1 "
                    515:     catchsql {$sql}
                    516:   " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError]
                    517: 
                    518:   do_test e_fkey-15.$tn.2 {
                    519:     execsql {
                    520:       SELECT * FROM chi WHERE c IS NOT NULL AND c NOT IN (SELECT p FROM par)
                    521:     }
                    522:   } {}
                    523: }
                    524: 
                    525: test_efkey_45 1 0 "INSERT INTO chi VALUES(1)"
                    526: test_efkey_45 2 1 "INSERT INTO chi VALUES('1.0')"
                    527: test_efkey_45 3 0 "INSERT INTO chi VALUES('1')"
                    528: test_efkey_45 4 1 "DELETE FROM par WHERE p = '1'"
                    529: test_efkey_45 5 0 "DELETE FROM chi WHERE c = '1'"
                    530: test_efkey_45 6 0 "DELETE FROM par WHERE p = '1'"
                    531: test_efkey_45 7 1 "INSERT INTO chi VALUES('1')"
                    532: test_efkey_45 8 0 "INSERT INTO chi VALUES(X'31')"
                    533: test_efkey_45 9 1 "INSERT INTO chi VALUES(X'32')"
                    534: 
                    535: #-------------------------------------------------------------------------
                    536: # Specifically, test that when comparing child and parent key values the
                    537: # default collation sequence of the parent key column is used.
                    538: #
                    539: # EVIDENCE-OF: R-15796-47513 When comparing text values, the collating
                    540: # sequence associated with the parent key column is always used.
                    541: #
                    542: drop_all_tables
                    543: do_test e_fkey-16.1 {
                    544:   execsql {
                    545:     CREATE TABLE t1(a COLLATE nocase PRIMARY KEY);
                    546:     CREATE TABLE t2(b REFERENCES t1);
                    547:   }
                    548: } {}
                    549: do_test e_fkey-16.2 {
                    550:   execsql {
                    551:     INSERT INTO t1 VALUES('oNe');
                    552:     INSERT INTO t2 VALUES('one');
                    553:     INSERT INTO t2 VALUES('ONE');
                    554:     UPDATE t2 SET b = 'OnE';
                    555:     UPDATE t1 SET a = 'ONE';
                    556:   }
                    557: } {}
                    558: do_test e_fkey-16.3 {
                    559:   catchsql { UPDATE t2 SET b = 'two' WHERE rowid = 1 }
                    560: } {1 {foreign key constraint failed}}
                    561: do_test e_fkey-16.4 {
                    562:   catchsql { DELETE FROM t1 WHERE rowid = 1 }
                    563: } {1 {foreign key constraint failed}}
                    564: 
                    565: #-------------------------------------------------------------------------
                    566: # Specifically, test that when comparing child and parent key values the
                    567: # affinity of the parent key column is applied to the child key value
                    568: # before the comparison takes place.
                    569: #
                    570: # EVIDENCE-OF: R-04240-13860 When comparing values, if the parent key
                    571: # column has an affinity, then that affinity is applied to the child key
                    572: # value before the comparison is performed.
                    573: #
                    574: drop_all_tables
                    575: do_test e_fkey-17.1 {
                    576:   execsql {
                    577:     CREATE TABLE t1(a NUMERIC PRIMARY KEY);
                    578:     CREATE TABLE t2(b TEXT REFERENCES t1);
                    579:   }
                    580: } {}
                    581: do_test e_fkey-17.2 {
                    582:   execsql {
                    583:     INSERT INTO t1 VALUES(1);
                    584:     INSERT INTO t1 VALUES(2);
                    585:     INSERT INTO t1 VALUES('three');
                    586:     INSERT INTO t2 VALUES('2.0');
                    587:     SELECT b, typeof(b) FROM t2;
                    588:   }
                    589: } {2.0 text}
                    590: do_test e_fkey-17.3 {
                    591:   execsql { SELECT typeof(a) FROM t1 }
                    592: } {integer integer text}
                    593: do_test e_fkey-17.4 {
                    594:   catchsql { DELETE FROM t1 WHERE rowid = 2 }
                    595: } {1 {foreign key constraint failed}}
                    596: 
                    597: ###########################################################################
                    598: ### SECTION 3: Required and Suggested Database Indexes
                    599: ###########################################################################
                    600: 
                    601: #-------------------------------------------------------------------------
                    602: # A parent key must be either a PRIMARY KEY, subject to a UNIQUE 
                    603: # constraint, or have a UNIQUE index created on it.
                    604: #
                    605: # EVIDENCE-OF: R-13435-26311 Usually, the parent key of a foreign key
                    606: # constraint is the primary key of the parent table. If they are not the
                    607: # primary key, then the parent key columns must be collectively subject
                    608: # to a UNIQUE constraint or have a UNIQUE index.
                    609: # 
                    610: # Also test that if a parent key is not subject to a PRIMARY KEY or UNIQUE
                    611: # constraint, but does have a UNIQUE index created on it, then the UNIQUE index
                    612: # must use the default collation sequences associated with the parent key
                    613: # columns.
                    614: #
                    615: # EVIDENCE-OF: R-00376-39212 If the parent key columns have a UNIQUE
                    616: # index, then that index must use the collation sequences that are
                    617: # specified in the CREATE TABLE statement for the parent table.
                    618: #
                    619: drop_all_tables
                    620: do_test e_fkey-18.1 {
                    621:   execsql {
                    622:     CREATE TABLE t2(a REFERENCES t1(x));
                    623:   }
                    624: } {}
                    625: proc test_efkey_57 {tn isError sql} {
                    626:   catchsql { DROP TABLE t1 }
                    627:   execsql $sql
                    628:   do_test e_fkey-18.$tn {
                    629:     catchsql { INSERT INTO t2 VALUES(NULL) }
                    630:   } [lindex {{0 {}} {1 {foreign key mismatch}}} $isError]
                    631: }
                    632: test_efkey_57 2 0 { CREATE TABLE t1(x PRIMARY KEY) }
                    633: test_efkey_57 3 0 { CREATE TABLE t1(x UNIQUE) }
                    634: test_efkey_57 4 0 { CREATE TABLE t1(x); CREATE UNIQUE INDEX t1i ON t1(x) }
                    635: test_efkey_57 5 1 { 
                    636:   CREATE TABLE t1(x); 
                    637:   CREATE UNIQUE INDEX t1i ON t1(x COLLATE nocase);
                    638: }
                    639: test_efkey_57 6 1 { CREATE TABLE t1(x) }
                    640: test_efkey_57 7 1 { CREATE TABLE t1(x, y, PRIMARY KEY(x, y)) }
                    641: test_efkey_57 8 1 { CREATE TABLE t1(x, y, UNIQUE(x, y)) }
                    642: test_efkey_57 9 1 { 
                    643:   CREATE TABLE t1(x, y); 
                    644:   CREATE UNIQUE INDEX t1i ON t1(x, y);
                    645: }
                    646: 
                    647: 
                    648: #-------------------------------------------------------------------------
                    649: # This block tests an example in foreignkeys.html. Several testable
                    650: # statements refer to this example, as follows
                    651: #
                    652: # EVIDENCE-OF: R-27484-01467
                    653: #
                    654: # FK Constraints on child1, child2 and child3 are Ok.
                    655: #
                    656: # Problem with FK on child4:
                    657: #
                    658: # EVIDENCE-OF: R-51039-44840 The foreign key declared as part of table
                    659: # child4 is an error because even though the parent key column is
                    660: # indexed, the index is not UNIQUE.
                    661: #
                    662: # Problem with FK on child5:
                    663: #
                    664: # EVIDENCE-OF: R-01060-48788 The foreign key for table child5 is an
                    665: # error because even though the parent key column has a unique index,
                    666: # the index uses a different collating sequence.
                    667: #
                    668: # Problem with FK on child6 and child7:
                    669: #
                    670: # EVIDENCE-OF: R-63088-37469 Tables child6 and child7 are incorrect
                    671: # because while both have UNIQUE indices on their parent keys, the keys
                    672: # are not an exact match to the columns of a single UNIQUE index.
                    673: #
                    674: drop_all_tables
                    675: do_test e_fkey-19.1 {
                    676:   execsql {
                    677:     CREATE TABLE parent(a PRIMARY KEY, b UNIQUE, c, d, e, f);
                    678:     CREATE UNIQUE INDEX i1 ON parent(c, d);
                    679:     CREATE INDEX i2 ON parent(e);
                    680:     CREATE UNIQUE INDEX i3 ON parent(f COLLATE nocase);
                    681: 
                    682:     CREATE TABLE child1(f, g REFERENCES parent(a));                       -- Ok
                    683:     CREATE TABLE child2(h, i REFERENCES parent(b));                       -- Ok
                    684:     CREATE TABLE child3(j, k, FOREIGN KEY(j, k) REFERENCES parent(c, d)); -- Ok
                    685:     CREATE TABLE child4(l, m REFERENCES parent(e));                       -- Err
                    686:     CREATE TABLE child5(n, o REFERENCES parent(f));                       -- Err
                    687:     CREATE TABLE child6(p, q, FOREIGN KEY(p,q) REFERENCES parent(b, c));  -- Err
                    688:     CREATE TABLE child7(r REFERENCES parent(c));                          -- Err
                    689:   }
                    690: } {}
                    691: do_test e_fkey-19.2 {
                    692:   execsql {
                    693:     INSERT INTO parent VALUES(1, 2, 3, 4, 5, 6);
                    694:     INSERT INTO child1 VALUES('xxx', 1);
                    695:     INSERT INTO child2 VALUES('xxx', 2);
                    696:     INSERT INTO child3 VALUES(3, 4);
                    697:   }
                    698: } {}
                    699: do_test e_fkey-19.2 {
                    700:   catchsql { INSERT INTO child4 VALUES('xxx', 5) }
                    701: } {1 {foreign key mismatch}}
                    702: do_test e_fkey-19.3 {
                    703:   catchsql { INSERT INTO child5 VALUES('xxx', 6) }
                    704: } {1 {foreign key mismatch}}
                    705: do_test e_fkey-19.4 {
                    706:   catchsql { INSERT INTO child6 VALUES(2, 3) }
                    707: } {1 {foreign key mismatch}}
                    708: do_test e_fkey-19.5 {
                    709:   catchsql { INSERT INTO child7 VALUES(3) }
                    710: } {1 {foreign key mismatch}}
                    711: 
                    712: #-------------------------------------------------------------------------
                    713: # Test errors in the database schema that are detected while preparing
                    714: # DML statements. The error text for these messages always matches 
                    715: # either "foreign key mismatch" or "no such table*" (using [string match]).
                    716: #
                    717: # EVIDENCE-OF: R-45488-08504 If the database schema contains foreign key
                    718: # errors that require looking at more than one table definition to
                    719: # identify, then those errors are not detected when the tables are
                    720: # created.
                    721: #
                    722: # EVIDENCE-OF: R-48391-38472 Instead, such errors prevent the
                    723: # application from preparing SQL statements that modify the content of
                    724: # the child or parent tables in ways that use the foreign keys.
                    725: #
                    726: # EVIDENCE-OF: R-03108-63659 The English language error message for
                    727: # foreign key DML errors is usually "foreign key mismatch" but can also
                    728: # be "no such table" if the parent table does not exist.
                    729: #
                    730: # EVIDENCE-OF: R-60781-26576 Foreign key DML errors are may be reported
                    731: # if: The parent table does not exist, or The parent key columns named
                    732: # in the foreign key constraint do not exist, or The parent key columns
                    733: # named in the foreign key constraint are not the primary key of the
                    734: # parent table and are not subject to a unique constraint using
                    735: # collating sequence specified in the CREATE TABLE, or The child table
                    736: # references the primary key of the parent without specifying the
                    737: # primary key columns and the number of primary key columns in the
                    738: # parent do not match the number of child key columns.
                    739: #
                    740: do_test e_fkey-20.1 {
                    741:   execsql {
                    742:     CREATE TABLE c1(c REFERENCES nosuchtable, d);
                    743: 
                    744:     CREATE TABLE p2(a, b, UNIQUE(a, b));
                    745:     CREATE TABLE c2(c, d, FOREIGN KEY(c, d) REFERENCES p2(a, x));
                    746: 
                    747:     CREATE TABLE p3(a PRIMARY KEY, b);
                    748:     CREATE TABLE c3(c REFERENCES p3(b), d);
                    749: 
                    750:     CREATE TABLE p4(a PRIMARY KEY, b);
                    751:     CREATE UNIQUE INDEX p4i ON p4(b COLLATE nocase);
                    752:     CREATE TABLE c4(c REFERENCES p4(b), d);
                    753: 
                    754:     CREATE TABLE p5(a PRIMARY KEY, b COLLATE nocase);
                    755:     CREATE UNIQUE INDEX p5i ON p5(b COLLATE binary);
                    756:     CREATE TABLE c5(c REFERENCES p5(b), d);
                    757: 
                    758:     CREATE TABLE p6(a PRIMARY KEY, b);
                    759:     CREATE TABLE c6(c, d, FOREIGN KEY(c, d) REFERENCES p6);
                    760: 
                    761:     CREATE TABLE p7(a, b, PRIMARY KEY(a, b));
                    762:     CREATE TABLE c7(c, d REFERENCES p7);
                    763:   }
                    764: } {}
                    765: 
                    766: foreach {tn tbl ptbl err} {
                    767:   2 c1 {} "no such table: main.nosuchtable"
                    768:   3 c2 p2 "foreign key mismatch"
                    769:   4 c3 p3 "foreign key mismatch"
                    770:   5 c4 p4 "foreign key mismatch"
                    771:   6 c5 p5 "foreign key mismatch"
                    772:   7 c6 p6 "foreign key mismatch"
                    773:   8 c7 p7 "foreign key mismatch"
                    774: } {
                    775:   do_test e_fkey-20.$tn.1 {
                    776:     catchsql "INSERT INTO $tbl VALUES('a', 'b')"
                    777:   } [list 1 $err]
                    778:   do_test e_fkey-20.$tn.2 {
                    779:     catchsql "UPDATE $tbl SET c = ?, d = ?"
                    780:   } [list 1 $err]
                    781:   do_test e_fkey-20.$tn.3 {
                    782:     catchsql "INSERT INTO $tbl SELECT ?, ?"
                    783:   } [list 1 $err]
                    784: 
                    785:   if {$ptbl ne ""} {
                    786:     do_test e_fkey-20.$tn.4 {
                    787:       catchsql "DELETE FROM $ptbl"
                    788:     } [list 1 $err]
                    789:     do_test e_fkey-20.$tn.5 {
                    790:       catchsql "UPDATE $ptbl SET a = ?, b = ?"
                    791:     } [list 1 $err]
                    792:     do_test e_fkey-20.$tn.6 {
                    793:       catchsql "INSERT INTO $ptbl SELECT ?, ?"
                    794:     } [list 1 $err]
                    795:   }
                    796: }
                    797: 
                    798: #-------------------------------------------------------------------------
                    799: # EVIDENCE-OF: R-19353-43643
                    800: #
                    801: # Test the example of foreign key mismatch errors caused by implicitly
                    802: # mapping a child key to the primary key of the parent table when the
                    803: # child key consists of a different number of columns to that primary key.
                    804: # 
                    805: drop_all_tables
                    806: do_test e_fkey-21.1 {
                    807:   execsql {
                    808:     CREATE TABLE parent2(a, b, PRIMARY KEY(a,b));
                    809: 
                    810:     CREATE TABLE child8(x, y, FOREIGN KEY(x,y) REFERENCES parent2);     -- Ok
                    811:     CREATE TABLE child9(x REFERENCES parent2);                          -- Err
                    812:     CREATE TABLE child10(x,y,z, FOREIGN KEY(x,y,z) REFERENCES parent2); -- Err
                    813:   }
                    814: } {}
                    815: do_test e_fkey-21.2 {
                    816:   execsql {
                    817:     INSERT INTO parent2 VALUES('I', 'II');
                    818:     INSERT INTO child8 VALUES('I', 'II');
                    819:   }
                    820: } {}
                    821: do_test e_fkey-21.3 {
                    822:   catchsql { INSERT INTO child9 VALUES('I') }
                    823: } {1 {foreign key mismatch}}
                    824: do_test e_fkey-21.4 {
                    825:   catchsql { INSERT INTO child9 VALUES('II') }
                    826: } {1 {foreign key mismatch}}
                    827: do_test e_fkey-21.5 {
                    828:   catchsql { INSERT INTO child9 VALUES(NULL) }
                    829: } {1 {foreign key mismatch}}
                    830: do_test e_fkey-21.6 {
                    831:   catchsql { INSERT INTO child10 VALUES('I', 'II', 'III') }
                    832: } {1 {foreign key mismatch}}
                    833: do_test e_fkey-21.7 {
                    834:   catchsql { INSERT INTO child10 VALUES(1, 2, 3) }
                    835: } {1 {foreign key mismatch}}
                    836: do_test e_fkey-21.8 {
                    837:   catchsql { INSERT INTO child10 VALUES(NULL, NULL, NULL) }
                    838: } {1 {foreign key mismatch}}
                    839: 
                    840: #-------------------------------------------------------------------------
                    841: # Test errors that are reported when creating the child table. 
                    842: # Specifically:
                    843: #
                    844: #   * different number of child and parent key columns, and
                    845: #   * child columns that do not exist.
                    846: #
                    847: # EVIDENCE-OF: R-23682-59820 By contrast, if foreign key errors can be
                    848: # recognized simply by looking at the definition of the child table and
                    849: # without having to consult the parent table definition, then the CREATE
                    850: # TABLE statement for the child table fails.
                    851: #
                    852: # These errors are reported whether or not FK support is enabled.
                    853: #
                    854: # EVIDENCE-OF: R-33883-28833 Foreign key DDL errors are reported
                    855: # regardless of whether or not foreign key constraints are enabled when
                    856: # the table is created.
                    857: #
                    858: drop_all_tables
                    859: foreach fk [list OFF ON] {
                    860:   execsql "PRAGMA foreign_keys = $fk"
                    861:   set i 0
                    862:   foreach {sql error} {
                    863:     "CREATE TABLE child1(a, b, FOREIGN KEY(a, b) REFERENCES p(c))"
                    864:       {number of columns in foreign key does not match the number of columns in the referenced table}
                    865:     "CREATE TABLE child2(a, b, FOREIGN KEY(a, b) REFERENCES p(c, d, e))"
                    866:       {number of columns in foreign key does not match the number of columns in the referenced table}
                    867:     "CREATE TABLE child2(a, b, FOREIGN KEY(a, c) REFERENCES p(c, d))"
                    868:       {unknown column "c" in foreign key definition}
                    869:     "CREATE TABLE child2(a, b, FOREIGN KEY(c, b) REFERENCES p(c, d))"
                    870:       {unknown column "c" in foreign key definition}
                    871:   } {
                    872:     do_test e_fkey-22.$fk.[incr i] {
                    873:       catchsql $sql
                    874:     } [list 1 $error]
                    875:   }
                    876: }
                    877: 
                    878: #-------------------------------------------------------------------------
                    879: # Test that a REFERENCING clause that does not specify parent key columns
                    880: # implicitly maps to the primary key of the parent table.
                    881: #
                    882: # EVIDENCE-OF: R-43879-08025 Attaching a "REFERENCES <parent-table>"
                    883: # clause to a column definition creates a foreign
                    884: # key constraint that maps the column to the primary key of
                    885: # <parent-table>.
                    886: # 
                    887: do_test e_fkey-23.1 {
                    888:   execsql {
                    889:     CREATE TABLE p1(a, b, PRIMARY KEY(a, b));
                    890:     CREATE TABLE p2(a, b PRIMARY KEY);
                    891:     CREATE TABLE c1(c, d, FOREIGN KEY(c, d) REFERENCES p1);
                    892:     CREATE TABLE c2(a, b REFERENCES p2);
                    893:   }
                    894: } {}
                    895: proc test_efkey_60 {tn isError sql} {
                    896:   do_test e_fkey-23.$tn "
                    897:     catchsql {$sql}
                    898:   " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError]
                    899: }
                    900: 
                    901: test_efkey_60 2 1 "INSERT INTO c1 VALUES(239, 231)"
                    902: test_efkey_60 3 0 "INSERT INTO p1 VALUES(239, 231)"
                    903: test_efkey_60 4 0 "INSERT INTO c1 VALUES(239, 231)"
                    904: test_efkey_60 5 1 "INSERT INTO c2 VALUES(239, 231)"
                    905: test_efkey_60 6 0 "INSERT INTO p2 VALUES(239, 231)"
                    906: test_efkey_60 7 0 "INSERT INTO c2 VALUES(239, 231)"
                    907: 
                    908: #-------------------------------------------------------------------------
                    909: # Test that an index on on the child key columns of an FK constraint
                    910: # is optional.
                    911: #
                    912: # EVIDENCE-OF: R-15417-28014 Indices are not required for child key
                    913: # columns
                    914: #
                    915: # Also test that if an index is created on the child key columns, it does
                    916: # not make a difference whether or not it is a UNIQUE index.
                    917: #
                    918: # EVIDENCE-OF: R-15741-50893 The child key index does not have to be
                    919: # (and usually will not be) a UNIQUE index.
                    920: #
                    921: drop_all_tables
                    922: do_test e_fkey-24.1 {
                    923:   execsql {
                    924:     CREATE TABLE parent(x, y, UNIQUE(y, x));
                    925:     CREATE TABLE c1(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y));
                    926:     CREATE TABLE c2(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y));
                    927:     CREATE TABLE c3(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y));
                    928:     CREATE INDEX c2i ON c2(a, b);
                    929:     CREATE UNIQUE INDEX c3i ON c2(b, a);
                    930:   }
                    931: } {}
                    932: proc test_efkey_61 {tn isError sql} {
                    933:   do_test e_fkey-24.$tn "
                    934:     catchsql {$sql}
                    935:   " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError]
                    936: }
                    937: foreach {tn c} [list 2 c1 3 c2 4 c3] {
                    938:   test_efkey_61 $tn.1 1 "INSERT INTO $c VALUES(1, 2)"
                    939:   test_efkey_61 $tn.2 0 "INSERT INTO parent VALUES(1, 2)"
                    940:   test_efkey_61 $tn.3 0 "INSERT INTO $c VALUES(1, 2)"
                    941: 
                    942:   execsql "DELETE FROM $c ; DELETE FROM parent"
                    943: }
                    944: 
                    945: #-------------------------------------------------------------------------
                    946: # EVIDENCE-OF: R-00279-52283
                    947: #
                    948: # Test an example showing that when a row is deleted from the parent 
                    949: # table, the child table is queried for orphaned rows as follows:
                    950: #
                    951: #   SELECT rowid FROM track WHERE trackartist = ?
                    952: #
                    953: # EVIDENCE-OF: R-23302-30956 If this SELECT returns any rows at all,
                    954: # then SQLite concludes that deleting the row from the parent table
                    955: # would violate the foreign key constraint and returns an error.
                    956: #
                    957: do_test e_fkey-25.1 {
                    958:   execsql {
                    959:     CREATE TABLE artist(
                    960:       artistid    INTEGER PRIMARY KEY, 
                    961:       artistname  TEXT
                    962:     );
                    963:     CREATE TABLE track(
                    964:       trackid     INTEGER, 
                    965:       trackname   TEXT, 
                    966:       trackartist INTEGER,
                    967:       FOREIGN KEY(trackartist) REFERENCES artist(artistid)
                    968:     );
                    969:   }
                    970: } {}
                    971: do_execsql_test e_fkey-25.2 {
                    972:   PRAGMA foreign_keys = OFF;
                    973:   EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
                    974:   EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?;
                    975: } {
                    976:   0 0 0 {SCAN TABLE artist (~1000000 rows)} 
                    977:   0 0 0 {SCAN TABLE track (~100000 rows)}
                    978: }
                    979: do_execsql_test e_fkey-25.3 {
                    980:   PRAGMA foreign_keys = ON;
                    981:   EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
                    982: } {
                    983:   0 0 0 {SCAN TABLE artist (~1000000 rows)} 
                    984:   0 0 0 {SCAN TABLE track (~100000 rows)}
                    985: }
                    986: do_test e_fkey-25.4 {
                    987:   execsql {
                    988:     INSERT INTO artist VALUES(5, 'artist 5');
                    989:     INSERT INTO artist VALUES(6, 'artist 6');
                    990:     INSERT INTO artist VALUES(7, 'artist 7');
                    991:     INSERT INTO track VALUES(1, 'track 1', 5);
                    992:     INSERT INTO track VALUES(2, 'track 2', 6);
                    993:   }
                    994: } {}
                    995: 
                    996: do_test e_fkey-25.5 {
                    997:   concat \
                    998:     [execsql { SELECT rowid FROM track WHERE trackartist = 5 }]   \
                    999:     [catchsql { DELETE FROM artist WHERE artistid = 5 }]
                   1000: } {1 1 {foreign key constraint failed}}
                   1001: 
                   1002: do_test e_fkey-25.6 {
                   1003:   concat \
                   1004:     [execsql { SELECT rowid FROM track WHERE trackartist = 7 }]   \
                   1005:     [catchsql { DELETE FROM artist WHERE artistid = 7 }]
                   1006: } {0 {}}
                   1007: 
                   1008: do_test e_fkey-25.7 {
                   1009:   concat \
                   1010:     [execsql { SELECT rowid FROM track WHERE trackartist = 6 }]   \
                   1011:     [catchsql { DELETE FROM artist WHERE artistid = 6 }]
                   1012: } {2 1 {foreign key constraint failed}}
                   1013: 
                   1014: #-------------------------------------------------------------------------
                   1015: # EVIDENCE-OF: R-47936-10044 Or, more generally:
                   1016: # SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value
                   1017: #
                   1018: # Test that when a row is deleted from the parent table of an FK 
                   1019: # constraint, the child table is queried for orphaned rows. The
                   1020: # query is equivalent to:
                   1021: #
                   1022: #   SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value
                   1023: #
                   1024: # Also test that when a row is inserted into the parent table, or when the 
                   1025: # parent key values of an existing row are modified, a query equivalent
                   1026: # to the following is planned. In some cases it is not executed, but it
                   1027: # is always planned.
                   1028: #
                   1029: #   SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value
                   1030: #
                   1031: # EVIDENCE-OF: R-61616-46700 Similar queries may be run if the content
                   1032: # of the parent key is modified or a new row is inserted into the parent
                   1033: # table.
                   1034: #
                   1035: #
                   1036: drop_all_tables
                   1037: do_test e_fkey-26.1 {
                   1038:   execsql { CREATE TABLE parent(x, y, UNIQUE(y, x)) }
                   1039: } {}
                   1040: foreach {tn sql} {
                   1041:   2 { 
                   1042:     CREATE TABLE child(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y))
                   1043:   }
                   1044:   3 { 
                   1045:     CREATE TABLE child(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y));
                   1046:     CREATE INDEX childi ON child(a, b);
                   1047:   }
                   1048:   4 { 
                   1049:     CREATE TABLE child(a, b, FOREIGN KEY(a, b) REFERENCES parent(x, y));
                   1050:     CREATE UNIQUE INDEX childi ON child(b, a);
                   1051:   }
                   1052: } {
                   1053:   execsql $sql
                   1054: 
                   1055:   execsql {PRAGMA foreign_keys = OFF}
                   1056:   set delete [concat \
                   1057:       [eqp "DELETE FROM parent WHERE 1"] \
                   1058:       [eqp "SELECT rowid FROM child WHERE a = ? AND b = ?"]
                   1059:   ]
                   1060:   set update [concat \
                   1061:       [eqp "UPDATE parent SET x=?, y=?"] \
                   1062:       [eqp "SELECT rowid FROM child WHERE a = ? AND b = ?"] \
                   1063:       [eqp "SELECT rowid FROM child WHERE a = ? AND b = ?"]
                   1064:   ]
                   1065:   execsql {PRAGMA foreign_keys = ON}
                   1066: 
                   1067:   do_test e_fkey-26.$tn.1 { eqp "DELETE FROM parent WHERE 1" } $delete
                   1068:   do_test e_fkey-26.$tn.2 { eqp "UPDATE parent set x=?, y=?" } $update
                   1069: 
                   1070:   execsql {DROP TABLE child}
                   1071: }
                   1072: 
                   1073: #-------------------------------------------------------------------------
                   1074: # EVIDENCE-OF: R-14553-34013
                   1075: #
                   1076: # Test the example schema at the end of section 3. Also test that is
                   1077: # is "efficient". In this case "efficient" means that foreign key
                   1078: # related operations on the parent table do not provoke linear scans.
                   1079: #
                   1080: drop_all_tables
                   1081: do_test e_fkey-27.1 {
                   1082:   execsql {
                   1083:     CREATE TABLE artist(
                   1084:       artistid    INTEGER PRIMARY KEY, 
                   1085:       artistname  TEXT
                   1086:     );
                   1087:     CREATE TABLE track(
                   1088:       trackid     INTEGER,
                   1089:       trackname   TEXT, 
                   1090:       trackartist INTEGER REFERENCES artist
                   1091:     );
                   1092:     CREATE INDEX trackindex ON track(trackartist);
                   1093:   }
                   1094: } {}
                   1095: do_test e_fkey-27.2 {
                   1096:   eqp { INSERT INTO artist VALUES(?, ?) }
                   1097: } {}
                   1098: do_execsql_test e_fkey-27.3 {
                   1099:   EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ?
                   1100: } {
                   1101:   0 0 0 {SCAN TABLE artist (~1000000 rows)} 
                   1102:   0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?) (~10 rows)} 
                   1103:   0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?) (~10 rows)}
                   1104: }
                   1105: do_execsql_test e_fkey-27.4 {
                   1106:   EXPLAIN QUERY PLAN DELETE FROM artist
                   1107: } {
                   1108:   0 0 0 {SCAN TABLE artist (~1000000 rows)} 
                   1109:   0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?) (~10 rows)}
                   1110: }
                   1111: 
                   1112: 
                   1113: ###########################################################################
                   1114: ### SECTION 4.1: Composite Foreign Key Constraints
                   1115: ###########################################################################
                   1116: 
                   1117: #-------------------------------------------------------------------------
                   1118: # Check that parent and child keys must have the same number of columns.
                   1119: #
                   1120: # EVIDENCE-OF: R-41062-34431 Parent and child keys must have the same
                   1121: # cardinality.
                   1122: #
                   1123: foreach {tn sql err} {
                   1124:   1 "CREATE TABLE c(jj REFERENCES p(x, y))" 
                   1125:     {foreign key on jj should reference only one column of table p}
                   1126: 
                   1127:   2 "CREATE TABLE c(jj REFERENCES p())" {near ")": syntax error}
                   1128: 
                   1129:   3 "CREATE TABLE c(jj, FOREIGN KEY(jj) REFERENCES p(x, y))" 
                   1130:     {number of columns in foreign key does not match the number of columns in the referenced table}
                   1131: 
                   1132:   4 "CREATE TABLE c(jj, FOREIGN KEY(jj) REFERENCES p())" 
                   1133:     {near ")": syntax error}
                   1134: 
                   1135:   5 "CREATE TABLE c(ii, jj, FOREIGN KEY(jj, ii) REFERENCES p())" 
                   1136:     {near ")": syntax error}
                   1137: 
                   1138:   6 "CREATE TABLE c(ii, jj, FOREIGN KEY(jj, ii) REFERENCES p(x))" 
                   1139:     {number of columns in foreign key does not match the number of columns in the referenced table}
                   1140: 
                   1141:   7 "CREATE TABLE c(ii, jj, FOREIGN KEY(jj, ii) REFERENCES p(x,y,z))" 
                   1142:     {number of columns in foreign key does not match the number of columns in the referenced table}
                   1143: } {
                   1144:   drop_all_tables
                   1145:   do_test e_fkey-28.$tn [list catchsql $sql] [list 1 $err]
                   1146: }
                   1147: do_test e_fkey-28.8 {
                   1148:   drop_all_tables
                   1149:   execsql {
                   1150:     CREATE TABLE p(x PRIMARY KEY);
                   1151:     CREATE TABLE c(a, b, FOREIGN KEY(a,b) REFERENCES p);
                   1152:   }
                   1153:   catchsql {DELETE FROM p}
                   1154: } {1 {foreign key mismatch}}
                   1155: do_test e_fkey-28.9 {
                   1156:   drop_all_tables
                   1157:   execsql {
                   1158:     CREATE TABLE p(x, y, PRIMARY KEY(x,y));
                   1159:     CREATE TABLE c(a REFERENCES p);
                   1160:   }
                   1161:   catchsql {DELETE FROM p}
                   1162: } {1 {foreign key mismatch}}
                   1163: 
                   1164: 
                   1165: #-------------------------------------------------------------------------
                   1166: # EVIDENCE-OF: R-24676-09859
                   1167: #
                   1168: # Test the example schema in the "Composite Foreign Key Constraints" 
                   1169: # section.
                   1170: #
                   1171: do_test e_fkey-29.1 {
                   1172:   execsql {
                   1173:     CREATE TABLE album(
                   1174:       albumartist TEXT,
                   1175:       albumname TEXT,
                   1176:       albumcover BINARY,
                   1177:       PRIMARY KEY(albumartist, albumname)
                   1178:     );
                   1179:     CREATE TABLE song(
                   1180:       songid INTEGER,
                   1181:       songartist TEXT,
                   1182:       songalbum TEXT,
                   1183:       songname TEXT,
                   1184:       FOREIGN KEY(songartist, songalbum) REFERENCES album(albumartist,albumname)
                   1185:     );
                   1186:   }
                   1187: } {}
                   1188: 
                   1189: do_test e_fkey-29.2 {
                   1190:   execsql {
                   1191:     INSERT INTO album VALUES('Elvis Presley', 'Elvis'' Christmas Album', NULL);
                   1192:     INSERT INTO song VALUES(
                   1193:       1, 'Elvis Presley', 'Elvis'' Christmas Album', 'Here Comes Santa Clause'
                   1194:     );
                   1195:   }
                   1196: } {}
                   1197: do_test e_fkey-29.3 {
                   1198:   catchsql {
                   1199:     INSERT INTO song VALUES(2, 'Elvis Presley', 'Elvis Is Back!', 'Fever');
                   1200:   }
                   1201: } {1 {foreign key constraint failed}}
                   1202: 
                   1203: 
                   1204: #-------------------------------------------------------------------------
                   1205: # EVIDENCE-OF: R-33626-48418 In SQLite, if any of the child key columns
                   1206: # (in this case songartist and songalbum) are NULL, then there is no
                   1207: # requirement for a corresponding row in the parent table.
                   1208: #
                   1209: do_test e_fkey-30.1 {
                   1210:   execsql {
                   1211:     INSERT INTO song VALUES(2, 'Elvis Presley', NULL, 'Fever');
                   1212:     INSERT INTO song VALUES(3, NULL, 'Elvis Is Back', 'Soldier Boy');
                   1213:   }
                   1214: } {}
                   1215: 
                   1216: ###########################################################################
                   1217: ### SECTION 4.2: Deferred Foreign Key Constraints
                   1218: ###########################################################################
                   1219: 
                   1220: #-------------------------------------------------------------------------
                   1221: # Test that if a statement violates an immediate FK constraint, and the
                   1222: # database does not satisfy the FK constraint once all effects of the
                   1223: # statement have been applied, an error is reported and the effects of
                   1224: # the statement rolled back.
                   1225: #
                   1226: # EVIDENCE-OF: R-09323-30470 If a statement modifies the contents of the
                   1227: # database so that an immediate foreign key constraint is in violation
                   1228: # at the conclusion the statement, an exception is thrown and the
                   1229: # effects of the statement are reverted.
                   1230: #
                   1231: drop_all_tables
                   1232: do_test e_fkey-31.1 {
                   1233:   execsql {
                   1234:     CREATE TABLE king(a, b, PRIMARY KEY(a));
                   1235:     CREATE TABLE prince(c REFERENCES king, d);
                   1236:   }
                   1237: } {}
                   1238: 
                   1239: do_test e_fkey-31.2 {
                   1240:   # Execute a statement that violates the immediate FK constraint.
                   1241:   catchsql { INSERT INTO prince VALUES(1, 2) }
                   1242: } {1 {foreign key constraint failed}}
                   1243: 
                   1244: do_test e_fkey-31.3 {
                   1245:   # This time, use a trigger to fix the constraint violation before the
                   1246:   # statement has finished executing. Then execute the same statement as
                   1247:   # in the previous test case. This time, no error.
                   1248:   execsql {
                   1249:     CREATE TRIGGER kt AFTER INSERT ON prince WHEN
                   1250:       NOT EXISTS (SELECT a FROM king WHERE a = new.c)
                   1251:     BEGIN
                   1252:       INSERT INTO king VALUES(new.c, NULL);
                   1253:     END
                   1254:   }
                   1255:   execsql { INSERT INTO prince VALUES(1, 2) }
                   1256: } {}
                   1257: 
                   1258: # Test that operating inside a transaction makes no difference to 
                   1259: # immediate constraint violation handling.
                   1260: do_test e_fkey-31.4 {
                   1261:   execsql {
                   1262:     BEGIN;
                   1263:     INSERT INTO prince VALUES(2, 3);
                   1264:     DROP TRIGGER kt;
                   1265:   }
                   1266:   catchsql { INSERT INTO prince VALUES(3, 4) }
                   1267: } {1 {foreign key constraint failed}}
                   1268: do_test e_fkey-31.5 {
                   1269:   execsql {
                   1270:     COMMIT;
                   1271:     SELECT * FROM king;
                   1272:   }
                   1273: } {1 {} 2 {}}
                   1274: 
                   1275: #-------------------------------------------------------------------------
                   1276: # Test that if a deferred constraint is violated within a transaction,
                   1277: # nothing happens immediately and the database is allowed to persist
                   1278: # in a state that does not satisfy the FK constraint. However attempts
                   1279: # to COMMIT the transaction fail until the FK constraint is satisfied.
                   1280: #
                   1281: # EVIDENCE-OF: R-49178-21358 By contrast, if a statement modifies the
                   1282: # contents of the database such that a deferred foreign key constraint
                   1283: # is violated, the violation is not reported immediately.
                   1284: #
                   1285: # EVIDENCE-OF: R-39692-12488 Deferred foreign key constraints are not
                   1286: # checked until the transaction tries to COMMIT.
                   1287: #
                   1288: # EVIDENCE-OF: R-55147-47664 For as long as the user has an open
                   1289: # transaction, the database is allowed to exist in a state that violates
                   1290: # any number of deferred foreign key constraints.
                   1291: #
                   1292: # EVIDENCE-OF: R-29604-30395 However, COMMIT will fail as long as
                   1293: # foreign key constraints remain in violation.
                   1294: #
                   1295: proc test_efkey_34 {tn isError sql} {
                   1296:   do_test e_fkey-32.$tn "
                   1297:     catchsql {$sql}
                   1298:   " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError]
                   1299: }
                   1300: drop_all_tables
                   1301: 
                   1302: test_efkey_34  1 0 {
                   1303:   CREATE TABLE ll(k PRIMARY KEY);
                   1304:   CREATE TABLE kk(c REFERENCES ll DEFERRABLE INITIALLY DEFERRED);
                   1305: }
                   1306: test_efkey_34  2 0 "BEGIN"
                   1307: test_efkey_34  3 0   "INSERT INTO kk VALUES(5)"
                   1308: test_efkey_34  4 0   "INSERT INTO kk VALUES(10)"
                   1309: test_efkey_34  5 1 "COMMIT"
                   1310: test_efkey_34  6 0   "INSERT INTO ll VALUES(10)"
                   1311: test_efkey_34  7 1 "COMMIT"
                   1312: test_efkey_34  8 0   "INSERT INTO ll VALUES(5)"
                   1313: test_efkey_34  9 0 "COMMIT"
                   1314: 
                   1315: #-------------------------------------------------------------------------
                   1316: # When not running inside a transaction, a deferred constraint is similar
                   1317: # to an immediate constraint (violations are reported immediately).
                   1318: #
                   1319: # EVIDENCE-OF: R-56844-61705 If the current statement is not inside an
                   1320: # explicit transaction (a BEGIN/COMMIT/ROLLBACK block), then an implicit
                   1321: # transaction is committed as soon as the statement has finished
                   1322: # executing. In this case deferred constraints behave the same as
                   1323: # immediate constraints.
                   1324: #
                   1325: drop_all_tables
                   1326: proc test_efkey_35 {tn isError sql} {
                   1327:   do_test e_fkey-33.$tn "
                   1328:     catchsql {$sql}
                   1329:   " [lindex {{0 {}} {1 {foreign key constraint failed}}} $isError]
                   1330: }
                   1331: do_test e_fkey-33.1 {
                   1332:   execsql {
                   1333:     CREATE TABLE parent(x, y);
                   1334:     CREATE UNIQUE INDEX pi ON parent(x, y);
                   1335:     CREATE TABLE child(a, b,
                   1336:       FOREIGN KEY(a, b) REFERENCES parent(x, y) DEFERRABLE INITIALLY DEFERRED
                   1337:     );
                   1338:   }
                   1339: } {}
                   1340: test_efkey_35 2 1 "INSERT INTO child  VALUES('x', 'y')"
                   1341: test_efkey_35 3 0 "INSERT INTO parent VALUES('x', 'y')"
                   1342: test_efkey_35 4 0 "INSERT INTO child  VALUES('x', 'y')"
                   1343: 
                   1344: 
                   1345: #-------------------------------------------------------------------------
                   1346: # EVIDENCE-OF: R-12782-61841
                   1347: #
                   1348: # Test that an FK constraint is made deferred by adding the following
                   1349: # to the definition:
                   1350: #
                   1351: #   DEFERRABLE INITIALLY DEFERRED
                   1352: #
                   1353: # EVIDENCE-OF: R-09005-28791
                   1354: #
                   1355: # Also test that adding any of the following to a foreign key definition 
                   1356: # makes the constraint IMMEDIATE:
                   1357: #
                   1358: #   NOT DEFERRABLE INITIALLY DEFERRED
                   1359: #   NOT DEFERRABLE INITIALLY IMMEDIATE
                   1360: #   NOT DEFERRABLE
                   1361: #   DEFERRABLE INITIALLY IMMEDIATE
                   1362: #   DEFERRABLE
                   1363: #
                   1364: # Foreign keys are IMMEDIATE by default (if there is no DEFERRABLE or NOT
                   1365: # DEFERRABLE clause).
                   1366: #
                   1367: # EVIDENCE-OF: R-35290-16460 Foreign key constraints are immediate by
                   1368: # default.
                   1369: #
                   1370: # EVIDENCE-OF: R-30323-21917 Each foreign key constraint in SQLite is
                   1371: # classified as either immediate or deferred.
                   1372: #
                   1373: drop_all_tables
                   1374: do_test e_fkey-34.1 {
                   1375:   execsql {
                   1376:     CREATE TABLE parent(x, y, z, PRIMARY KEY(x,y,z));
                   1377:     CREATE TABLE c1(a, b, c,
                   1378:       FOREIGN KEY(a, b, c) REFERENCES parent NOT DEFERRABLE INITIALLY DEFERRED
                   1379:     );
                   1380:     CREATE TABLE c2(a, b, c,
                   1381:       FOREIGN KEY(a, b, c) REFERENCES parent NOT DEFERRABLE INITIALLY IMMEDIATE
                   1382:     );
                   1383:     CREATE TABLE c3(a, b, c,
                   1384:       FOREIGN KEY(a, b, c) REFERENCES parent NOT DEFERRABLE
                   1385:     );
                   1386:     CREATE TABLE c4(a, b, c,
                   1387:       FOREIGN KEY(a, b, c) REFERENCES parent DEFERRABLE INITIALLY IMMEDIATE
                   1388:     );
                   1389:     CREATE TABLE c5(a, b, c,
                   1390:       FOREIGN KEY(a, b, c) REFERENCES parent DEFERRABLE
                   1391:     );
                   1392:     CREATE TABLE c6(a, b, c, FOREIGN KEY(a, b, c) REFERENCES parent);
                   1393: 
                   1394:     -- This FK constraint is the only deferrable one.
                   1395:     CREATE TABLE c7(a, b, c,
                   1396:       FOREIGN KEY(a, b, c) REFERENCES parent DEFERRABLE INITIALLY DEFERRED
                   1397:     );
                   1398: 
                   1399:     INSERT INTO parent VALUES('a', 'b', 'c');
                   1400:     INSERT INTO parent VALUES('d', 'e', 'f');
                   1401:     INSERT INTO parent VALUES('g', 'h', 'i');
                   1402:     INSERT INTO parent VALUES('j', 'k', 'l');
                   1403:     INSERT INTO parent VALUES('m', 'n', 'o');
                   1404:     INSERT INTO parent VALUES('p', 'q', 'r');
                   1405:     INSERT INTO parent VALUES('s', 't', 'u');
                   1406: 
                   1407:     INSERT INTO c1 VALUES('a', 'b', 'c');
                   1408:     INSERT INTO c2 VALUES('d', 'e', 'f');
                   1409:     INSERT INTO c3 VALUES('g', 'h', 'i');
                   1410:     INSERT INTO c4 VALUES('j', 'k', 'l');
                   1411:     INSERT INTO c5 VALUES('m', 'n', 'o');
                   1412:     INSERT INTO c6 VALUES('p', 'q', 'r');
                   1413:     INSERT INTO c7 VALUES('s', 't', 'u');
                   1414:   }
                   1415: } {}
                   1416: 
                   1417: proc test_efkey_29 {tn sql isError} {
                   1418:   do_test e_fkey-34.$tn "catchsql {$sql}" [
                   1419:     lindex {{0 {}} {1 {foreign key constraint failed}}} $isError
                   1420:   ]
                   1421: }
                   1422: test_efkey_29  2 "BEGIN"                                   0
                   1423: test_efkey_29  3 "DELETE FROM parent WHERE x = 'a'"        1
                   1424: test_efkey_29  4 "DELETE FROM parent WHERE x = 'd'"        1
                   1425: test_efkey_29  5 "DELETE FROM parent WHERE x = 'g'"        1
                   1426: test_efkey_29  6 "DELETE FROM parent WHERE x = 'j'"        1
                   1427: test_efkey_29  7 "DELETE FROM parent WHERE x = 'm'"        1
                   1428: test_efkey_29  8 "DELETE FROM parent WHERE x = 'p'"        1
                   1429: test_efkey_29  9 "DELETE FROM parent WHERE x = 's'"        0
                   1430: test_efkey_29 10 "COMMIT"                                  1
                   1431: test_efkey_29 11 "ROLLBACK"                                0
                   1432: 
                   1433: test_efkey_29  9 "BEGIN"                                   0
                   1434: test_efkey_29 10 "UPDATE parent SET z = 'z' WHERE z = 'c'" 1
                   1435: test_efkey_29 11 "UPDATE parent SET z = 'z' WHERE z = 'f'" 1
                   1436: test_efkey_29 12 "UPDATE parent SET z = 'z' WHERE z = 'i'" 1
                   1437: test_efkey_29 13 "UPDATE parent SET z = 'z' WHERE z = 'l'" 1
                   1438: test_efkey_29 14 "UPDATE parent SET z = 'z' WHERE z = 'o'" 1
                   1439: test_efkey_29 15 "UPDATE parent SET z = 'z' WHERE z = 'r'" 1
                   1440: test_efkey_29 16 "UPDATE parent SET z = 'z' WHERE z = 'u'" 0
                   1441: test_efkey_29 17 "COMMIT"                                  1
                   1442: test_efkey_29 18 "ROLLBACK"                                0
                   1443: 
                   1444: test_efkey_29 17 "BEGIN"                                   0
                   1445: test_efkey_29 18 "INSERT INTO c1 VALUES(1, 2, 3)"          1
                   1446: test_efkey_29 19 "INSERT INTO c2 VALUES(1, 2, 3)"          1
                   1447: test_efkey_29 20 "INSERT INTO c3 VALUES(1, 2, 3)"          1
                   1448: test_efkey_29 21 "INSERT INTO c4 VALUES(1, 2, 3)"          1
                   1449: test_efkey_29 22 "INSERT INTO c5 VALUES(1, 2, 3)"          1
                   1450: test_efkey_29 22 "INSERT INTO c6 VALUES(1, 2, 3)"          1
                   1451: test_efkey_29 22 "INSERT INTO c7 VALUES(1, 2, 3)"          0
                   1452: test_efkey_29 23 "COMMIT"                                  1
                   1453: test_efkey_29 24 "INSERT INTO parent VALUES(1, 2, 3)"      0
                   1454: test_efkey_29 25 "COMMIT"                                  0
                   1455: 
                   1456: test_efkey_29 26 "BEGIN"                                   0
                   1457: test_efkey_29 27 "UPDATE c1 SET a = 10"                    1
                   1458: test_efkey_29 28 "UPDATE c2 SET a = 10"                    1
                   1459: test_efkey_29 29 "UPDATE c3 SET a = 10"                    1
                   1460: test_efkey_29 30 "UPDATE c4 SET a = 10"                    1
                   1461: test_efkey_29 31 "UPDATE c5 SET a = 10"                    1
                   1462: test_efkey_29 31 "UPDATE c6 SET a = 10"                    1
                   1463: test_efkey_29 31 "UPDATE c7 SET a = 10"                    0
                   1464: test_efkey_29 32 "COMMIT"                                  1
                   1465: test_efkey_29 33 "ROLLBACK"                                0
                   1466: 
                   1467: #-------------------------------------------------------------------------
                   1468: # EVIDENCE-OF: R-24499-57071
                   1469: #
                   1470: # Test an example from foreignkeys.html dealing with a deferred foreign 
                   1471: # key constraint.
                   1472: #
                   1473: do_test e_fkey-35.1 {
                   1474:   drop_all_tables
                   1475:   execsql {
                   1476:     CREATE TABLE artist(
                   1477:       artistid    INTEGER PRIMARY KEY, 
                   1478:       artistname  TEXT
                   1479:     );
                   1480:     CREATE TABLE track(
                   1481:       trackid     INTEGER,
                   1482:       trackname   TEXT, 
                   1483:       trackartist INTEGER REFERENCES artist(artistid) DEFERRABLE INITIALLY DEFERRED
                   1484:     );
                   1485:   }
                   1486: } {}
                   1487: do_test e_fkey-35.2 {
                   1488:   execsql {
                   1489:     BEGIN;
                   1490:       INSERT INTO track VALUES(1, 'White Christmas', 5);
                   1491:   }
                   1492:   catchsql COMMIT
                   1493: } {1 {foreign key constraint failed}}
                   1494: do_test e_fkey-35.3 {
                   1495:   execsql {
                   1496:     INSERT INTO artist VALUES(5, 'Bing Crosby');
                   1497:     COMMIT;
                   1498:   }
                   1499: } {}
                   1500: 
                   1501: #-------------------------------------------------------------------------
                   1502: # Verify that a nested savepoint may be released without satisfying 
                   1503: # deferred foreign key constraints.
                   1504: #
                   1505: # EVIDENCE-OF: R-07223-48323 A nested savepoint transaction may be
                   1506: # RELEASEd while the database is in a state that does not satisfy a
                   1507: # deferred foreign key constraint.
                   1508: #
                   1509: drop_all_tables
                   1510: do_test e_fkey-36.1 {
                   1511:   execsql {
                   1512:     CREATE TABLE t1(a PRIMARY KEY,
                   1513:       b REFERENCES t1 DEFERRABLE INITIALLY DEFERRED
                   1514:     );
                   1515:     INSERT INTO t1 VALUES(1, 1);
                   1516:     INSERT INTO t1 VALUES(2, 2);
                   1517:     INSERT INTO t1 VALUES(3, 3);
                   1518:   }
                   1519: } {}
                   1520: do_test e_fkey-36.2 {
                   1521:   execsql {
                   1522:     BEGIN;
                   1523:       SAVEPOINT one;
                   1524:         INSERT INTO t1 VALUES(4, 5);
                   1525:       RELEASE one;
                   1526:   }
                   1527: } {}
                   1528: do_test e_fkey-36.3 {
                   1529:   catchsql COMMIT
                   1530: } {1 {foreign key constraint failed}}
                   1531: do_test e_fkey-36.4 {
                   1532:   execsql {
                   1533:     UPDATE t1 SET a = 5 WHERE a = 4;
                   1534:     COMMIT;
                   1535:   }
                   1536: } {}
                   1537: 
                   1538: 
                   1539: #-------------------------------------------------------------------------
                   1540: # Check that a transaction savepoint (an outermost savepoint opened when
                   1541: # the database was in auto-commit mode) cannot be released without
                   1542: # satisfying deferred foreign key constraints. It may be rolled back.
                   1543: #
                   1544: # EVIDENCE-OF: R-44295-13823 A transaction savepoint (a non-nested
                   1545: # savepoint that was opened while there was not currently an open
                   1546: # transaction), on the other hand, is subject to the same restrictions
                   1547: # as a COMMIT - attempting to RELEASE it while the database is in such a
                   1548: # state will fail.
                   1549: #
                   1550: do_test e_fkey-37.1 {
                   1551:   execsql {
                   1552:     SAVEPOINT one;
                   1553:       SAVEPOINT two;
                   1554:         INSERT INTO t1 VALUES(6, 7);
                   1555:       RELEASE two;
                   1556:   }
                   1557: } {}
                   1558: do_test e_fkey-37.2 {
                   1559:   catchsql {RELEASE one}
                   1560: } {1 {foreign key constraint failed}}
                   1561: do_test e_fkey-37.3 {
                   1562:   execsql {
                   1563:       UPDATE t1 SET a = 7 WHERE a = 6;
                   1564:     RELEASE one;
                   1565:   }
                   1566: } {}
                   1567: do_test e_fkey-37.4 {
                   1568:   execsql {
                   1569:     SAVEPOINT one;
                   1570:       SAVEPOINT two;
                   1571:         INSERT INTO t1 VALUES(9, 10);
                   1572:       RELEASE two;
                   1573:   }
                   1574: } {}
                   1575: do_test e_fkey-37.5 {
                   1576:   catchsql {RELEASE one}
                   1577: } {1 {foreign key constraint failed}}
                   1578: do_test e_fkey-37.6 {
                   1579:   execsql {ROLLBACK TO one ; RELEASE one}
                   1580: } {}
                   1581: 
                   1582: #-------------------------------------------------------------------------
                   1583: # Test that if a COMMIT operation fails due to deferred foreign key 
                   1584: # constraints, any nested savepoints remain open.
                   1585: #
                   1586: # EVIDENCE-OF: R-37736-42616 If a COMMIT statement (or the RELEASE of a
                   1587: # transaction SAVEPOINT) fails because the database is currently in a
                   1588: # state that violates a deferred foreign key constraint and there are
                   1589: # currently nested savepoints, the nested savepoints remain open.
                   1590: #
                   1591: do_test e_fkey-38.1 {
                   1592:   execsql {
                   1593:     DELETE FROM t1 WHERE a>3;
                   1594:     SELECT * FROM t1;
                   1595:   }
                   1596: } {1 1 2 2 3 3}
                   1597: do_test e_fkey-38.2 {
                   1598:   execsql {
                   1599:     BEGIN;
                   1600:       INSERT INTO t1 VALUES(4, 4);
                   1601:       SAVEPOINT one;
                   1602:         INSERT INTO t1 VALUES(5, 6);
                   1603:         SELECT * FROM t1;
                   1604:   }
                   1605: } {1 1 2 2 3 3 4 4 5 6}
                   1606: do_test e_fkey-38.3 {
                   1607:   catchsql COMMIT
                   1608: } {1 {foreign key constraint failed}}
                   1609: do_test e_fkey-38.4 {
                   1610:   execsql {
                   1611:     ROLLBACK TO one;
                   1612:     COMMIT;
                   1613:     SELECT * FROM t1;
                   1614:   }
                   1615: } {1 1 2 2 3 3 4 4}
                   1616: 
                   1617: do_test e_fkey-38.5 {
                   1618:   execsql {
                   1619:     SAVEPOINT a;
                   1620:       INSERT INTO t1 VALUES(5, 5);
                   1621:       SAVEPOINT b;
                   1622:         INSERT INTO t1 VALUES(6, 7);
                   1623:         SAVEPOINT c;
                   1624:           INSERT INTO t1 VALUES(7, 8);
                   1625:   }
                   1626: } {}
                   1627: do_test e_fkey-38.6 {
                   1628:   catchsql {RELEASE a}
                   1629: } {1 {foreign key constraint failed}}
                   1630: do_test e_fkey-38.7 {
                   1631:   execsql  {ROLLBACK TO c}
                   1632:   catchsql {RELEASE a}
                   1633: } {1 {foreign key constraint failed}}
                   1634: do_test e_fkey-38.8 {
                   1635:   execsql  {
                   1636:     ROLLBACK TO b;
                   1637:     RELEASE a;
                   1638:     SELECT * FROM t1;
                   1639:   }
                   1640: } {1 1 2 2 3 3 4 4 5 5}
                   1641: 
                   1642: ###########################################################################
                   1643: ### SECTION 4.3: ON DELETE and ON UPDATE Actions
                   1644: ###########################################################################
                   1645: 
                   1646: #-------------------------------------------------------------------------
                   1647: # Test that configured ON DELETE and ON UPDATE actions take place when
                   1648: # deleting or modifying rows of the parent table, respectively.
                   1649: #
                   1650: # EVIDENCE-OF: R-48270-44282 Foreign key ON DELETE and ON UPDATE clauses
                   1651: # are used to configure actions that take place when deleting rows from
                   1652: # the parent table (ON DELETE), or modifying the parent key values of
                   1653: # existing rows (ON UPDATE).
                   1654: #
                   1655: # Test that a single FK constraint may have different actions configured
                   1656: # for ON DELETE and ON UPDATE.
                   1657: #
                   1658: # EVIDENCE-OF: R-48124-63225 A single foreign key constraint may have
                   1659: # different actions configured for ON DELETE and ON UPDATE.
                   1660: #
                   1661: do_test e_fkey-39.1 {
                   1662:   execsql {
                   1663:     CREATE TABLE p(a, b PRIMARY KEY, c);
                   1664:     CREATE TABLE c1(d, e, f DEFAULT 'k0' REFERENCES p 
                   1665:       ON UPDATE SET DEFAULT
                   1666:       ON DELETE SET NULL
                   1667:     );
                   1668: 
                   1669:     INSERT INTO p VALUES(0, 'k0', '');
                   1670:     INSERT INTO p VALUES(1, 'k1', 'I');
                   1671:     INSERT INTO p VALUES(2, 'k2', 'II');
                   1672:     INSERT INTO p VALUES(3, 'k3', 'III');
                   1673: 
                   1674:     INSERT INTO c1 VALUES(1, 'xx', 'k1');
                   1675:     INSERT INTO c1 VALUES(2, 'xx', 'k2');
                   1676:     INSERT INTO c1 VALUES(3, 'xx', 'k3');
                   1677:   }
                   1678: } {}
                   1679: do_test e_fkey-39.2 {
                   1680:   execsql {
                   1681:     UPDATE p SET b = 'k4' WHERE a = 1;
                   1682:     SELECT * FROM c1;
                   1683:   }
                   1684: } {1 xx k0 2 xx k2 3 xx k3}
                   1685: do_test e_fkey-39.3 {
                   1686:   execsql {
                   1687:     DELETE FROM p WHERE a = 2;
                   1688:     SELECT * FROM c1;
                   1689:   }
                   1690: } {1 xx k0 2 xx {} 3 xx k3}
                   1691: do_test e_fkey-39.4 {
                   1692:   execsql {
                   1693:     CREATE UNIQUE INDEX pi ON p(c);
                   1694:     REPLACE INTO p VALUES(5, 'k5', 'III');
                   1695:     SELECT * FROM c1;
                   1696:   }
                   1697: } {1 xx k0 2 xx {} 3 xx {}}
                   1698: 
                   1699: #-------------------------------------------------------------------------
                   1700: # Each foreign key in the system has an ON UPDATE and ON DELETE action,
                   1701: # either "NO ACTION", "RESTRICT", "SET NULL", "SET DEFAULT" or "CASCADE".
                   1702: #
                   1703: # EVIDENCE-OF: R-33326-45252 The ON DELETE and ON UPDATE action
                   1704: # associated with each foreign key in an SQLite database is one of "NO
                   1705: # ACTION", "RESTRICT", "SET NULL", "SET DEFAULT" or "CASCADE".
                   1706: #
                   1707: # If none is specified explicitly, "NO ACTION" is the default.
                   1708: #
                   1709: # EVIDENCE-OF: R-19803-45884 If an action is not explicitly specified,
                   1710: # it defaults to "NO ACTION".
                   1711: # 
                   1712: drop_all_tables
                   1713: do_test e_fkey-40.1 {
                   1714:   execsql {
                   1715:     CREATE TABLE parent(x PRIMARY KEY, y);
                   1716:     CREATE TABLE child1(a, 
                   1717:       b REFERENCES parent ON UPDATE NO ACTION ON DELETE RESTRICT
                   1718:     );
                   1719:     CREATE TABLE child2(a, 
                   1720:       b REFERENCES parent ON UPDATE RESTRICT ON DELETE SET NULL
                   1721:     );
                   1722:     CREATE TABLE child3(a, 
                   1723:       b REFERENCES parent ON UPDATE SET NULL ON DELETE SET DEFAULT
                   1724:     );
                   1725:     CREATE TABLE child4(a, 
                   1726:       b REFERENCES parent ON UPDATE SET DEFAULT ON DELETE CASCADE
                   1727:     );
                   1728: 
                   1729:     -- Create some foreign keys that use the default action - "NO ACTION"
                   1730:     CREATE TABLE child5(a, b REFERENCES parent ON UPDATE CASCADE);
                   1731:     CREATE TABLE child6(a, b REFERENCES parent ON DELETE RESTRICT);
                   1732:     CREATE TABLE child7(a, b REFERENCES parent ON DELETE NO ACTION);
                   1733:     CREATE TABLE child8(a, b REFERENCES parent ON UPDATE NO ACTION);
                   1734:   }
                   1735: } {}
                   1736: 
                   1737: foreach {tn zTab lRes} {
                   1738:   2 child1 {0 0 parent b {} {NO ACTION} RESTRICT NONE}
                   1739:   3 child2 {0 0 parent b {} RESTRICT {SET NULL} NONE}
                   1740:   4 child3 {0 0 parent b {} {SET NULL} {SET DEFAULT} NONE}
                   1741:   5 child4 {0 0 parent b {} {SET DEFAULT} CASCADE NONE}
                   1742:   6 child5 {0 0 parent b {} CASCADE {NO ACTION} NONE}
                   1743:   7 child6 {0 0 parent b {} {NO ACTION} RESTRICT NONE}
                   1744:   8 child7 {0 0 parent b {} {NO ACTION} {NO ACTION} NONE}
                   1745:   9 child8 {0 0 parent b {} {NO ACTION} {NO ACTION} NONE}
                   1746: } {
                   1747:   do_test e_fkey-40.$tn { execsql "PRAGMA foreign_key_list($zTab)" } $lRes
                   1748: }
                   1749: 
                   1750: #-------------------------------------------------------------------------
                   1751: # Test that "NO ACTION" means that nothing happens to a child row when
                   1752: # it's parent row is updated or deleted.
                   1753: #
                   1754: # EVIDENCE-OF: R-19971-54976 Configuring "NO ACTION" means just that:
                   1755: # when a parent key is modified or deleted from the database, no special
                   1756: # action is taken.
                   1757: #
                   1758: drop_all_tables
                   1759: do_test e_fkey-41.1 {
                   1760:   execsql {
                   1761:     CREATE TABLE parent(p1, p2, PRIMARY KEY(p1, p2));
                   1762:     CREATE TABLE child(c1, c2, 
                   1763:       FOREIGN KEY(c1, c2) REFERENCES parent
                   1764:       ON UPDATE NO ACTION
                   1765:       ON DELETE NO ACTION
                   1766:       DEFERRABLE INITIALLY DEFERRED
                   1767:     );
                   1768:     INSERT INTO parent VALUES('j', 'k');
                   1769:     INSERT INTO parent VALUES('l', 'm');
                   1770:     INSERT INTO child VALUES('j', 'k');
                   1771:     INSERT INTO child VALUES('l', 'm');
                   1772:   }
                   1773: } {}
                   1774: do_test e_fkey-41.2 {
                   1775:   execsql {
                   1776:     BEGIN;
                   1777:       UPDATE parent SET p1='k' WHERE p1='j';
                   1778:       DELETE FROM parent WHERE p1='l';
                   1779:       SELECT * FROM child;
                   1780:   }
                   1781: } {j k l m}
                   1782: do_test e_fkey-41.3 {
                   1783:   catchsql COMMIT
                   1784: } {1 {foreign key constraint failed}}
                   1785: do_test e_fkey-41.4 {
                   1786:   execsql ROLLBACK
                   1787: } {}
                   1788: 
                   1789: #-------------------------------------------------------------------------
                   1790: # Test that "RESTRICT" means the application is prohibited from deleting
                   1791: # or updating a parent table row when there exists one or more child keys
                   1792: # mapped to it.
                   1793: #
                   1794: # EVIDENCE-OF: R-04272-38653 The "RESTRICT" action means that the
                   1795: # application is prohibited from deleting (for ON DELETE RESTRICT) or
                   1796: # modifying (for ON UPDATE RESTRICT) a parent key when there exists one
                   1797: # or more child keys mapped to it.
                   1798: #
                   1799: drop_all_tables
                   1800: do_test e_fkey-41.1 {
                   1801:   execsql {
                   1802:     CREATE TABLE parent(p1, p2);
                   1803:     CREATE UNIQUE INDEX parent_i ON parent(p1, p2);
                   1804:     CREATE TABLE child1(c1, c2, 
                   1805:       FOREIGN KEY(c2, c1) REFERENCES parent(p1, p2) ON DELETE RESTRICT
                   1806:     );
                   1807:     CREATE TABLE child2(c1, c2, 
                   1808:       FOREIGN KEY(c2, c1) REFERENCES parent(p1, p2) ON UPDATE RESTRICT
                   1809:     );
                   1810:   }
                   1811: } {}
                   1812: do_test e_fkey-41.2 {
                   1813:   execsql {
                   1814:     INSERT INTO parent VALUES('a', 'b');
                   1815:     INSERT INTO parent VALUES('c', 'd');
                   1816:     INSERT INTO child1 VALUES('b', 'a');
                   1817:     INSERT INTO child2 VALUES('d', 'c');
                   1818:   }
                   1819: } {}
                   1820: do_test e_fkey-41.3 {
                   1821:   catchsql { DELETE FROM parent WHERE p1 = 'a' }
                   1822: } {1 {foreign key constraint failed}}
                   1823: do_test e_fkey-41.4 {
                   1824:   catchsql { UPDATE parent SET p2 = 'e' WHERE p1 = 'c' }
                   1825: } {1 {foreign key constraint failed}}
                   1826: 
                   1827: #-------------------------------------------------------------------------
                   1828: # Test that RESTRICT is slightly different from NO ACTION for IMMEDIATE
                   1829: # constraints, in that it is enforced immediately, not at the end of the 
                   1830: # statement.
                   1831: #
                   1832: # EVIDENCE-OF: R-37997-42187 The difference between the effect of a
                   1833: # RESTRICT action and normal foreign key constraint enforcement is that
                   1834: # the RESTRICT action processing happens as soon as the field is updated
                   1835: # - not at the end of the current statement as it would with an
                   1836: # immediate constraint, or at the end of the current transaction as it
                   1837: # would with a deferred constraint.
                   1838: #
                   1839: drop_all_tables
                   1840: do_test e_fkey-42.1 {
                   1841:   execsql {
                   1842:     CREATE TABLE parent(x PRIMARY KEY);
                   1843:     CREATE TABLE child1(c REFERENCES parent ON UPDATE RESTRICT);
                   1844:     CREATE TABLE child2(c REFERENCES parent ON UPDATE NO ACTION);
                   1845: 
                   1846:     INSERT INTO parent VALUES('key1');
                   1847:     INSERT INTO parent VALUES('key2');
                   1848:     INSERT INTO child1 VALUES('key1');
                   1849:     INSERT INTO child2 VALUES('key2');
                   1850: 
                   1851:     CREATE TRIGGER parent_t AFTER UPDATE ON parent BEGIN
                   1852:       UPDATE child1 set c = new.x WHERE c = old.x;
                   1853:       UPDATE child2 set c = new.x WHERE c = old.x;
                   1854:     END;
                   1855:   }
                   1856: } {}
                   1857: do_test e_fkey-42.2 {
                   1858:   catchsql { UPDATE parent SET x = 'key one' WHERE x = 'key1' }
                   1859: } {1 {foreign key constraint failed}}
                   1860: do_test e_fkey-42.3 {
                   1861:   execsql { 
                   1862:     UPDATE parent SET x = 'key two' WHERE x = 'key2';
                   1863:     SELECT * FROM child2;
                   1864:   }
                   1865: } {{key two}}
                   1866: 
                   1867: drop_all_tables
                   1868: do_test e_fkey-42.4 {
                   1869:   execsql {
                   1870:     CREATE TABLE parent(x PRIMARY KEY);
                   1871:     CREATE TABLE child1(c REFERENCES parent ON DELETE RESTRICT);
                   1872:     CREATE TABLE child2(c REFERENCES parent ON DELETE NO ACTION);
                   1873: 
                   1874:     INSERT INTO parent VALUES('key1');
                   1875:     INSERT INTO parent VALUES('key2');
                   1876:     INSERT INTO child1 VALUES('key1');
                   1877:     INSERT INTO child2 VALUES('key2');
                   1878: 
                   1879:     CREATE TRIGGER parent_t AFTER DELETE ON parent BEGIN
                   1880:       UPDATE child1 SET c = NULL WHERE c = old.x;
                   1881:       UPDATE child2 SET c = NULL WHERE c = old.x;
                   1882:     END;
                   1883:   }
                   1884: } {}
                   1885: do_test e_fkey-42.5 {
                   1886:   catchsql { DELETE FROM parent WHERE x = 'key1' }
                   1887: } {1 {foreign key constraint failed}}
                   1888: do_test e_fkey-42.6 {
                   1889:   execsql { 
                   1890:     DELETE FROM parent WHERE x = 'key2';
                   1891:     SELECT * FROM child2;
                   1892:   }
                   1893: } {{}}
                   1894: 
                   1895: drop_all_tables
                   1896: do_test e_fkey-42.7 {
                   1897:   execsql {
                   1898:     CREATE TABLE parent(x PRIMARY KEY);
                   1899:     CREATE TABLE child1(c REFERENCES parent ON DELETE RESTRICT);
                   1900:     CREATE TABLE child2(c REFERENCES parent ON DELETE NO ACTION);
                   1901: 
                   1902:     INSERT INTO parent VALUES('key1');
                   1903:     INSERT INTO parent VALUES('key2');
                   1904:     INSERT INTO child1 VALUES('key1');
                   1905:     INSERT INTO child2 VALUES('key2');
                   1906:   }
                   1907: } {}
                   1908: do_test e_fkey-42.8 {
                   1909:   catchsql { REPLACE INTO parent VALUES('key1') }
                   1910: } {1 {foreign key constraint failed}}
                   1911: do_test e_fkey-42.9 {
                   1912:   execsql { 
                   1913:     REPLACE INTO parent VALUES('key2');
                   1914:     SELECT * FROM child2;
                   1915:   }
                   1916: } {key2}
                   1917: 
                   1918: #-------------------------------------------------------------------------
                   1919: # Test that RESTRICT is enforced immediately, even for a DEFERRED constraint.
                   1920: #
                   1921: # EVIDENCE-OF: R-24179-60523 Even if the foreign key constraint it is
                   1922: # attached to is deferred, configuring a RESTRICT action causes SQLite
                   1923: # to return an error immediately if a parent key with dependent child
                   1924: # keys is deleted or modified.
                   1925: #
                   1926: drop_all_tables
                   1927: do_test e_fkey-43.1 {
                   1928:   execsql {
                   1929:     CREATE TABLE parent(x PRIMARY KEY);
                   1930:     CREATE TABLE child1(c REFERENCES parent ON UPDATE RESTRICT
                   1931:       DEFERRABLE INITIALLY DEFERRED
                   1932:     );
                   1933:     CREATE TABLE child2(c REFERENCES parent ON UPDATE NO ACTION
                   1934:       DEFERRABLE INITIALLY DEFERRED
                   1935:     );
                   1936: 
                   1937:     INSERT INTO parent VALUES('key1');
                   1938:     INSERT INTO parent VALUES('key2');
                   1939:     INSERT INTO child1 VALUES('key1');
                   1940:     INSERT INTO child2 VALUES('key2');
                   1941:     BEGIN;
                   1942:   }
                   1943: } {}
                   1944: do_test e_fkey-43.2 {
                   1945:   catchsql { UPDATE parent SET x = 'key one' WHERE x = 'key1' }
                   1946: } {1 {foreign key constraint failed}}
                   1947: do_test e_fkey-43.3 {
                   1948:   execsql { UPDATE parent SET x = 'key two' WHERE x = 'key2' }
                   1949: } {}
                   1950: do_test e_fkey-43.4 {
                   1951:   catchsql COMMIT
                   1952: } {1 {foreign key constraint failed}}
                   1953: do_test e_fkey-43.5 {
                   1954:   execsql {
                   1955:     UPDATE child2 SET c = 'key two';
                   1956:     COMMIT;
                   1957:   }
                   1958: } {}
                   1959: 
                   1960: drop_all_tables
                   1961: do_test e_fkey-43.6 {
                   1962:   execsql {
                   1963:     CREATE TABLE parent(x PRIMARY KEY);
                   1964:     CREATE TABLE child1(c REFERENCES parent ON DELETE RESTRICT
                   1965:       DEFERRABLE INITIALLY DEFERRED
                   1966:     );
                   1967:     CREATE TABLE child2(c REFERENCES parent ON DELETE NO ACTION
                   1968:       DEFERRABLE INITIALLY DEFERRED
                   1969:     );
                   1970: 
                   1971:     INSERT INTO parent VALUES('key1');
                   1972:     INSERT INTO parent VALUES('key2');
                   1973:     INSERT INTO child1 VALUES('key1');
                   1974:     INSERT INTO child2 VALUES('key2');
                   1975:     BEGIN;
                   1976:   }
                   1977: } {}
                   1978: do_test e_fkey-43.7 {
                   1979:   catchsql { DELETE FROM parent WHERE x = 'key1' }
                   1980: } {1 {foreign key constraint failed}}
                   1981: do_test e_fkey-43.8 {
                   1982:   execsql { DELETE FROM parent WHERE x = 'key2' }
                   1983: } {}
                   1984: do_test e_fkey-43.9 {
                   1985:   catchsql COMMIT
                   1986: } {1 {foreign key constraint failed}}
                   1987: do_test e_fkey-43.10 {
                   1988:   execsql {
                   1989:     UPDATE child2 SET c = NULL;
                   1990:     COMMIT;
                   1991:   }
                   1992: } {}
                   1993: 
                   1994: #-------------------------------------------------------------------------
                   1995: # Test SET NULL actions.
                   1996: #
                   1997: # EVIDENCE-OF: R-03353-05327 If the configured action is "SET NULL",
                   1998: # then when a parent key is deleted (for ON DELETE SET NULL) or modified
                   1999: # (for ON UPDATE SET NULL), the child key columns of all rows in the
                   2000: # child table that mapped to the parent key are set to contain SQL NULL
                   2001: # values.
                   2002: #
                   2003: drop_all_tables
                   2004: do_test e_fkey-44.1 {
                   2005:   execsql {
                   2006:     CREATE TABLE pA(x PRIMARY KEY);
                   2007:     CREATE TABLE cA(c REFERENCES pA ON DELETE SET NULL);
                   2008:     CREATE TABLE cB(c REFERENCES pA ON UPDATE SET NULL);
                   2009: 
                   2010:     INSERT INTO pA VALUES(X'ABCD');
                   2011:     INSERT INTO pA VALUES(X'1234');
                   2012:     INSERT INTO cA VALUES(X'ABCD');
                   2013:     INSERT INTO cB VALUES(X'1234');
                   2014:   }
                   2015: } {}
                   2016: do_test e_fkey-44.2 {
                   2017:   execsql {
                   2018:     DELETE FROM pA WHERE rowid = 1;
                   2019:     SELECT quote(x) FROM pA;
                   2020:   }
                   2021: } {X'1234'}
                   2022: do_test e_fkey-44.3 {
                   2023:   execsql {
                   2024:     SELECT quote(c) FROM cA;
                   2025:   }
                   2026: } {NULL}
                   2027: do_test e_fkey-44.4 {
                   2028:   execsql {
                   2029:     UPDATE pA SET x = X'8765' WHERE rowid = 2;
                   2030:     SELECT quote(x) FROM pA;
                   2031:   }
                   2032: } {X'8765'}
                   2033: do_test e_fkey-44.5 {
                   2034:   execsql { SELECT quote(c) FROM cB }
                   2035: } {NULL}
                   2036: 
                   2037: #-------------------------------------------------------------------------
                   2038: # Test SET DEFAULT actions.
                   2039: #
                   2040: # EVIDENCE-OF: R-43054-54832 The "SET DEFAULT" actions are similar to
                   2041: # "SET NULL", except that each of the child key columns is set to
                   2042: # contain the columns default value instead of NULL.
                   2043: #
                   2044: drop_all_tables
                   2045: do_test e_fkey-45.1 {
                   2046:   execsql {
                   2047:     CREATE TABLE pA(x PRIMARY KEY);
                   2048:     CREATE TABLE cA(c DEFAULT X'0000' REFERENCES pA ON DELETE SET DEFAULT);
                   2049:     CREATE TABLE cB(c DEFAULT X'9999' REFERENCES pA ON UPDATE SET DEFAULT);
                   2050: 
                   2051:     INSERT INTO pA(rowid, x) VALUES(1, X'0000');
                   2052:     INSERT INTO pA(rowid, x) VALUES(2, X'9999');
                   2053:     INSERT INTO pA(rowid, x) VALUES(3, X'ABCD');
                   2054:     INSERT INTO pA(rowid, x) VALUES(4, X'1234');
                   2055: 
                   2056:     INSERT INTO cA VALUES(X'ABCD');
                   2057:     INSERT INTO cB VALUES(X'1234');
                   2058:   }
                   2059: } {}
                   2060: do_test e_fkey-45.2 {
                   2061:   execsql {
                   2062:     DELETE FROM pA WHERE rowid = 3;
                   2063:     SELECT quote(x) FROM pA;
                   2064:   }
                   2065: } {X'0000' X'9999' X'1234'}
                   2066: do_test e_fkey-45.3 {
                   2067:   execsql { SELECT quote(c) FROM cA }
                   2068: } {X'0000'}
                   2069: do_test e_fkey-45.4 {
                   2070:   execsql {
                   2071:     UPDATE pA SET x = X'8765' WHERE rowid = 4;
                   2072:     SELECT quote(x) FROM pA;
                   2073:   }
                   2074: } {X'0000' X'9999' X'8765'}
                   2075: do_test e_fkey-45.5 {
                   2076:   execsql { SELECT quote(c) FROM cB }
                   2077: } {X'9999'}
                   2078: 
                   2079: #-------------------------------------------------------------------------
                   2080: # Test ON DELETE CASCADE actions.
                   2081: #
                   2082: # EVIDENCE-OF: R-61376-57267 A "CASCADE" action propagates the delete or
                   2083: # update operation on the parent key to each dependent child key.
                   2084: #
                   2085: # EVIDENCE-OF: R-61809-62207 For an "ON DELETE CASCADE" action, this
                   2086: # means that each row in the child table that was associated with the
                   2087: # deleted parent row is also deleted.
                   2088: #
                   2089: drop_all_tables
                   2090: do_test e_fkey-46.1 {
                   2091:   execsql {
                   2092:     CREATE TABLE p1(a, b UNIQUE);
                   2093:     CREATE TABLE c1(c REFERENCES p1(b) ON DELETE CASCADE, d);
                   2094:     INSERT INTO p1 VALUES(NULL, NULL);
                   2095:     INSERT INTO p1 VALUES(4, 4);
                   2096:     INSERT INTO p1 VALUES(5, 5);
                   2097:     INSERT INTO c1 VALUES(NULL, NULL);
                   2098:     INSERT INTO c1 VALUES(4, 4);
                   2099:     INSERT INTO c1 VALUES(5, 5);
                   2100:     SELECT count(*) FROM c1;
                   2101:   }
                   2102: } {3}
                   2103: do_test e_fkey-46.2 {
                   2104:   execsql {
                   2105:     DELETE FROM p1 WHERE a = 4;
                   2106:     SELECT d, c FROM c1;
                   2107:   }
                   2108: } {{} {} 5 5}
                   2109: do_test e_fkey-46.3 {
                   2110:   execsql {
                   2111:     DELETE FROM p1;
                   2112:     SELECT d, c FROM c1;
                   2113:   }
                   2114: } {{} {}}
                   2115: do_test e_fkey-46.4 {
                   2116:   execsql { SELECT * FROM p1 }
                   2117: } {}
                   2118: 
                   2119: 
                   2120: #-------------------------------------------------------------------------
                   2121: # Test ON UPDATE CASCADE actions.
                   2122: #
                   2123: # EVIDENCE-OF: R-13877-64542 For an "ON UPDATE CASCADE" action, it means
                   2124: # that the values stored in each dependent child key are modified to
                   2125: # match the new parent key values.
                   2126: #
                   2127: # EVIDENCE-OF: R-61376-57267 A "CASCADE" action propagates the delete or
                   2128: # update operation on the parent key to each dependent child key.
                   2129: #
                   2130: drop_all_tables
                   2131: do_test e_fkey-47.1 {
                   2132:   execsql {
                   2133:     CREATE TABLE p1(a, b UNIQUE);
                   2134:     CREATE TABLE c1(c REFERENCES p1(b) ON UPDATE CASCADE, d);
                   2135:     INSERT INTO p1 VALUES(NULL, NULL);
                   2136:     INSERT INTO p1 VALUES(4, 4);
                   2137:     INSERT INTO p1 VALUES(5, 5);
                   2138:     INSERT INTO c1 VALUES(NULL, NULL);
                   2139:     INSERT INTO c1 VALUES(4, 4);
                   2140:     INSERT INTO c1 VALUES(5, 5);
                   2141:     SELECT count(*) FROM c1;
                   2142:   }
                   2143: } {3}
                   2144: do_test e_fkey-47.2 {
                   2145:   execsql {
                   2146:     UPDATE p1 SET b = 10 WHERE b = 5;
                   2147:     SELECT d, c FROM c1;
                   2148:   }
                   2149: } {{} {} 4 4 5 10}
                   2150: do_test e_fkey-47.3 {
                   2151:   execsql {
                   2152:     UPDATE p1 SET b = 11 WHERE b = 4;
                   2153:     SELECT d, c FROM c1;
                   2154:   }
                   2155: } {{} {} 4 11 5 10}
                   2156: do_test e_fkey-47.4 {
                   2157:   execsql { 
                   2158:     UPDATE p1 SET b = 6 WHERE b IS NULL;
                   2159:     SELECT d, c FROM c1;
                   2160:   }
                   2161: } {{} {} 4 11 5 10}
                   2162: do_test e_fkey-46.5 {
                   2163:   execsql { SELECT * FROM p1 }
                   2164: } {{} 6 4 11 5 10}
                   2165: 
                   2166: #-------------------------------------------------------------------------
                   2167: # EVIDENCE-OF: R-65058-57158
                   2168: #
                   2169: # Test an example from the "ON DELETE and ON UPDATE Actions" section 
                   2170: # of foreignkeys.html.
                   2171: #
                   2172: drop_all_tables
                   2173: do_test e_fkey-48.1 {
                   2174:   execsql {
                   2175:     CREATE TABLE artist(
                   2176:       artistid    INTEGER PRIMARY KEY, 
                   2177:       artistname  TEXT
                   2178:     );
                   2179:     CREATE TABLE track(
                   2180:       trackid     INTEGER,
                   2181:       trackname   TEXT, 
                   2182:       trackartist INTEGER REFERENCES artist(artistid) ON UPDATE CASCADE
                   2183:     );
                   2184: 
                   2185:     INSERT INTO artist VALUES(1, 'Dean Martin');
                   2186:     INSERT INTO artist VALUES(2, 'Frank Sinatra');
                   2187:     INSERT INTO track VALUES(11, 'That''s Amore', 1);
                   2188:     INSERT INTO track VALUES(12, 'Christmas Blues', 1);
                   2189:     INSERT INTO track VALUES(13, 'My Way', 2);
                   2190:   }
                   2191: } {}
                   2192: do_test e_fkey-48.2 {
                   2193:   execsql {
                   2194:     UPDATE artist SET artistid = 100 WHERE artistname = 'Dean Martin';
                   2195:   }
                   2196: } {}
                   2197: do_test e_fkey-48.3 {
                   2198:   execsql { SELECT * FROM artist }
                   2199: } {2 {Frank Sinatra} 100 {Dean Martin}}
                   2200: do_test e_fkey-48.4 {
                   2201:   execsql { SELECT * FROM track }
                   2202: } {11 {That's Amore} 100 12 {Christmas Blues} 100 13 {My Way} 2}
                   2203: 
                   2204: 
                   2205: #-------------------------------------------------------------------------
                   2206: # Verify that adding an FK action does not absolve the user of the 
                   2207: # requirement not to violate the foreign key constraint.
                   2208: #
                   2209: # EVIDENCE-OF: R-53968-51642 Configuring an ON UPDATE or ON DELETE
                   2210: # action does not mean that the foreign key constraint does not need to
                   2211: # be satisfied.
                   2212: #
                   2213: drop_all_tables
                   2214: do_test e_fkey-49.1 {
                   2215:   execsql {
                   2216:     CREATE TABLE parent(a COLLATE nocase, b, c, PRIMARY KEY(c, a));
                   2217:     CREATE TABLE child(d DEFAULT 'a', e, f DEFAULT 'c',
                   2218:       FOREIGN KEY(f, d) REFERENCES parent ON UPDATE SET DEFAULT
                   2219:     );
                   2220: 
                   2221:     INSERT INTO parent VALUES('A', 'b', 'c');
                   2222:     INSERT INTO parent VALUES('ONE', 'two', 'three');
                   2223:     INSERT INTO child VALUES('one', 'two', 'three');
                   2224:   }
                   2225: } {}
                   2226: do_test e_fkey-49.2 {
                   2227:   execsql {
                   2228:     BEGIN;
                   2229:       UPDATE parent SET a = '' WHERE a = 'oNe';
                   2230:       SELECT * FROM child;
                   2231:   }
                   2232: } {a two c}
                   2233: do_test e_fkey-49.3 {
                   2234:   execsql {
                   2235:     ROLLBACK;
                   2236:     DELETE FROM parent WHERE a = 'A';
                   2237:     SELECT * FROM parent;
                   2238:   }
                   2239: } {ONE two three}
                   2240: do_test e_fkey-49.4 {
                   2241:   catchsql { UPDATE parent SET a = '' WHERE a = 'oNe' }
                   2242: } {1 {foreign key constraint failed}}
                   2243: 
                   2244: 
                   2245: #-------------------------------------------------------------------------
                   2246: # EVIDENCE-OF: R-11856-19836
                   2247: #
                   2248: # Test an example from the "ON DELETE and ON UPDATE Actions" section 
                   2249: # of foreignkeys.html. This example shows that adding an "ON DELETE DEFAULT"
                   2250: # clause does not abrogate the need to satisfy the foreign key constraint
                   2251: # (R-28220-46694).
                   2252: #
                   2253: # EVIDENCE-OF: R-28220-46694 For example, if an "ON DELETE SET DEFAULT"
                   2254: # action is configured, but there is no row in the parent table that
                   2255: # corresponds to the default values of the child key columns, deleting a
                   2256: # parent key while dependent child keys exist still causes a foreign key
                   2257: # violation.
                   2258: #
                   2259: drop_all_tables
                   2260: do_test e_fkey-50.1 {
                   2261:   execsql {
                   2262:     CREATE TABLE artist(
                   2263:       artistid    INTEGER PRIMARY KEY, 
                   2264:       artistname  TEXT
                   2265:     );
                   2266:     CREATE TABLE track(
                   2267:       trackid     INTEGER,
                   2268:       trackname   TEXT, 
                   2269:       trackartist INTEGER DEFAULT 0 REFERENCES artist(artistid) ON DELETE SET DEFAULT
                   2270:     );
                   2271:     INSERT INTO artist VALUES(3, 'Sammy Davis Jr.');
                   2272:     INSERT INTO track VALUES(14, 'Mr. Bojangles', 3);
                   2273:   }
                   2274: } {}
                   2275: do_test e_fkey-50.2 {
                   2276:   catchsql { DELETE FROM artist WHERE artistname = 'Sammy Davis Jr.' }
                   2277: } {1 {foreign key constraint failed}}
                   2278: do_test e_fkey-50.3 {
                   2279:   execsql {
                   2280:     INSERT INTO artist VALUES(0, 'Unknown Artist');
                   2281:     DELETE FROM artist WHERE artistname = 'Sammy Davis Jr.';
                   2282:   }
                   2283: } {}
                   2284: do_test e_fkey-50.4 {
                   2285:   execsql { SELECT * FROM artist }
                   2286: } {0 {Unknown Artist}}
                   2287: do_test e_fkey-50.5 {
                   2288:   execsql { SELECT * FROM track }
                   2289: } {14 {Mr. Bojangles} 0}
                   2290: 
                   2291: #-------------------------------------------------------------------------
                   2292: # EVIDENCE-OF: R-09564-22170
                   2293: #
                   2294: # Check that the order of steps in an UPDATE or DELETE on a parent 
                   2295: # table is as follows:
                   2296: #
                   2297: #   1. Execute applicable BEFORE trigger programs,
                   2298: #   2. Check local (non foreign key) constraints,
                   2299: #   3. Update or delete the row in the parent table,
                   2300: #   4. Perform any required foreign key actions,
                   2301: #   5. Execute applicable AFTER trigger programs. 
                   2302: #
                   2303: drop_all_tables
                   2304: do_test e_fkey-51.1 {
                   2305:   proc maxparent {args} { db one {SELECT max(x) FROM parent} }
                   2306:   db func maxparent maxparent
                   2307: 
                   2308:   execsql {
                   2309:     CREATE TABLE parent(x PRIMARY KEY);
                   2310: 
                   2311:     CREATE TRIGGER bu BEFORE UPDATE ON parent BEGIN
                   2312:       INSERT INTO parent VALUES(new.x-old.x);
                   2313:     END;
                   2314:     CREATE TABLE child(
                   2315:       a DEFAULT (maxparent()) REFERENCES parent ON UPDATE SET DEFAULT
                   2316:     );
                   2317:     CREATE TRIGGER au AFTER UPDATE ON parent BEGIN
                   2318:       INSERT INTO parent VALUES(new.x+old.x);
                   2319:     END;
                   2320: 
                   2321:     INSERT INTO parent VALUES(1);
                   2322:     INSERT INTO child VALUES(1);
                   2323:   }
                   2324: } {}
                   2325: do_test e_fkey-51.2 {
                   2326:   execsql {
                   2327:     UPDATE parent SET x = 22;
                   2328:     SELECT * FROM parent UNION ALL SELECT 'xxx' UNION ALL SELECT a FROM child;
                   2329:   }
                   2330: } {22 21 23 xxx 22}
                   2331: do_test e_fkey-51.3 {
                   2332:   execsql {
                   2333:     DELETE FROM child;
                   2334:     DELETE FROM parent;
                   2335:     INSERT INTO parent VALUES(-1);
                   2336:     INSERT INTO child VALUES(-1);
                   2337:     UPDATE parent SET x = 22;
                   2338:     SELECT * FROM parent UNION ALL SELECT 'xxx' UNION ALL SELECT a FROM child;
                   2339:   }
                   2340: } {22 23 21 xxx 23}
                   2341: 
                   2342: 
                   2343: #-------------------------------------------------------------------------
                   2344: # Verify that ON UPDATE actions only actually take place if the parent key
                   2345: # is set to a new value that is distinct from the old value. The default
                   2346: # collation sequence and affinity are used to determine if the new value
                   2347: # is 'distinct' from the old or not.
                   2348: #
                   2349: # EVIDENCE-OF: R-27383-10246 An ON UPDATE action is only taken if the
                   2350: # values of the parent key are modified so that the new parent key
                   2351: # values are not equal to the old.
                   2352: #
                   2353: drop_all_tables
                   2354: do_test e_fkey-52.1 {
                   2355:   execsql {
                   2356:     CREATE TABLE zeus(a INTEGER COLLATE NOCASE, b, PRIMARY KEY(a, b));
                   2357:     CREATE TABLE apollo(c, d, 
                   2358:       FOREIGN KEY(c, d) REFERENCES zeus ON UPDATE CASCADE
                   2359:     );
                   2360:     INSERT INTO zeus VALUES('abc', 'xyz');
                   2361:     INSERT INTO apollo VALUES('ABC', 'xyz');
                   2362:   }
                   2363:   execsql {
                   2364:     UPDATE zeus SET a = 'aBc';
                   2365:     SELECT * FROM apollo;
                   2366:   }
                   2367: } {ABC xyz}
                   2368: do_test e_fkey-52.2 {
                   2369:   execsql {
                   2370:     UPDATE zeus SET a = 1, b = 1;
                   2371:     SELECT * FROM apollo;
                   2372:   }
                   2373: } {1 1}
                   2374: do_test e_fkey-52.3 {
                   2375:   execsql {
                   2376:     UPDATE zeus SET a = 1, b = 1;
                   2377:     SELECT typeof(c), c, typeof(d), d FROM apollo;
                   2378:   }
                   2379: } {integer 1 integer 1}
                   2380: do_test e_fkey-52.4 {
                   2381:   execsql {
                   2382:     UPDATE zeus SET a = '1';
                   2383:     SELECT typeof(c), c, typeof(d), d FROM apollo;
                   2384:   }
                   2385: } {integer 1 integer 1}
                   2386: do_test e_fkey-52.5 {
                   2387:   execsql {
                   2388:     UPDATE zeus SET b = '1';
                   2389:     SELECT typeof(c), c, typeof(d), d FROM apollo;
                   2390:   }
                   2391: } {integer 1 text 1}
                   2392: do_test e_fkey-52.6 {
                   2393:   execsql {
                   2394:     UPDATE zeus SET b = NULL;
                   2395:     SELECT typeof(c), c, typeof(d), d FROM apollo;
                   2396:   }
                   2397: } {integer 1 null {}}
                   2398: 
                   2399: #-------------------------------------------------------------------------
                   2400: # EVIDENCE-OF: R-35129-58141
                   2401: #
                   2402: # Test an example from the "ON DELETE and ON UPDATE Actions" section 
                   2403: # of foreignkeys.html. This example demonstrates that ON UPDATE actions
                   2404: # only take place if at least one parent key column is set to a value 
                   2405: # that is distinct from its previous value.
                   2406: #
                   2407: drop_all_tables
                   2408: do_test e_fkey-53.1 {
                   2409:   execsql {
                   2410:     CREATE TABLE parent(x PRIMARY KEY);
                   2411:     CREATE TABLE child(y REFERENCES parent ON UPDATE SET NULL);
                   2412:     INSERT INTO parent VALUES('key');
                   2413:     INSERT INTO child VALUES('key');
                   2414:   }
                   2415: } {}
                   2416: do_test e_fkey-53.2 {
                   2417:   execsql {
                   2418:     UPDATE parent SET x = 'key';
                   2419:     SELECT IFNULL(y, 'null') FROM child;
                   2420:   }
                   2421: } {key}
                   2422: do_test e_fkey-53.3 {
                   2423:   execsql {
                   2424:     UPDATE parent SET x = 'key2';
                   2425:     SELECT IFNULL(y, 'null') FROM child;
                   2426:   }
                   2427: } {null}
                   2428: 
                   2429: ###########################################################################
                   2430: ### SECTION 5: CREATE, ALTER and DROP TABLE commands
                   2431: ###########################################################################
                   2432: 
                   2433: #-------------------------------------------------------------------------
                   2434: # Test that parent keys are not checked when tables are created.
                   2435: #
                   2436: # EVIDENCE-OF: R-36018-21755 The parent key definitions of foreign key
                   2437: # constraints are not checked when a table is created.
                   2438: #
                   2439: # EVIDENCE-OF: R-25384-39337 There is nothing stopping the user from
                   2440: # creating a foreign key definition that refers to a parent table that
                   2441: # does not exist, or to parent key columns that do not exist or are not
                   2442: # collectively bound by a PRIMARY KEY or UNIQUE constraint.
                   2443: #
                   2444: # Child keys are checked to ensure all component columns exist. If parent
                   2445: # key columns are explicitly specified, SQLite checks to make sure there
                   2446: # are the same number of columns in the child and parent keys. (TODO: This
                   2447: # is tested but does not correspond to any testable statement.)
                   2448: #
                   2449: # Also test that the above statements are true regardless of whether or not
                   2450: # foreign keys are enabled:  "A CREATE TABLE command operates the same whether
                   2451: # or not foreign key constraints are enabled."
                   2452: #
                   2453: # EVIDENCE-OF: R-08908-23439 A CREATE TABLE command operates the same
                   2454: # whether or not foreign key constraints are enabled.
                   2455: # 
                   2456: foreach {tn zCreateTbl lRes} {
                   2457:   1 "CREATE TABLE t1(a, b REFERENCES t1)"                            {0 {}}
                   2458:   2 "CREATE TABLE t1(a, b REFERENCES t2)"                            {0 {}}
                   2459:   3 "CREATE TABLE t1(a, b, FOREIGN KEY(a,b) REFERENCES t1)"          {0 {}}
                   2460:   4 "CREATE TABLE t1(a, b, FOREIGN KEY(a,b) REFERENCES t2)"          {0 {}}
                   2461:   5 "CREATE TABLE t1(a, b, FOREIGN KEY(a,b) REFERENCES t2)"          {0 {}}
                   2462:   6 "CREATE TABLE t1(a, b, FOREIGN KEY(a,b) REFERENCES t2(n,d))"     {0 {}}
                   2463:   7 "CREATE TABLE t1(a, b, FOREIGN KEY(a,b) REFERENCES t1(a,b))"     {0 {}}
                   2464: 
                   2465:   A "CREATE TABLE t1(a, b, FOREIGN KEY(c,b) REFERENCES t2)"          
                   2466:      {1 {unknown column "c" in foreign key definition}}
                   2467:   B "CREATE TABLE t1(a, b, FOREIGN KEY(c,b) REFERENCES t2(d))"          
                   2468:      {1 {number of columns in foreign key does not match the number of columns in the referenced table}}
                   2469: } {
                   2470:   do_test e_fkey-54.$tn.off {
                   2471:     drop_all_tables
                   2472:     execsql {PRAGMA foreign_keys = OFF}
                   2473:     catchsql $zCreateTbl
                   2474:   } $lRes
                   2475:   do_test e_fkey-54.$tn.on {
                   2476:     drop_all_tables
                   2477:     execsql {PRAGMA foreign_keys = ON}
                   2478:     catchsql $zCreateTbl
                   2479:   } $lRes
                   2480: }
                   2481: 
                   2482: #-------------------------------------------------------------------------
                   2483: # EVIDENCE-OF: R-47952-62498 It is not possible to use the "ALTER TABLE
                   2484: # ... ADD COLUMN" syntax to add a column that includes a REFERENCES
                   2485: # clause, unless the default value of the new column is NULL. Attempting
                   2486: # to do so returns an error.
                   2487: #
                   2488: proc test_efkey_6 {tn zAlter isError} {
                   2489:   drop_all_tables 
                   2490: 
                   2491:   do_test e_fkey-56.$tn.1 "
                   2492:     execsql { CREATE TABLE tbl(a, b) }
                   2493:     [list catchsql $zAlter]
                   2494:   " [lindex {{0 {}} {1 {Cannot add a REFERENCES column with non-NULL default value}}} $isError]
                   2495: 
                   2496: }
                   2497: 
                   2498: test_efkey_6 1 "ALTER TABLE tbl ADD COLUMN c REFERENCES xx" 0
                   2499: test_efkey_6 2 "ALTER TABLE tbl ADD COLUMN c DEFAULT NULL REFERENCES xx" 0
                   2500: test_efkey_6 3 "ALTER TABLE tbl ADD COLUMN c DEFAULT 0 REFERENCES xx" 1
                   2501: 
                   2502: #-------------------------------------------------------------------------
                   2503: # Test that ALTER TABLE adjusts REFERENCES clauses when the parent table
                   2504: # is RENAMED.
                   2505: #
                   2506: # EVIDENCE-OF: R-47080-02069 If an "ALTER TABLE ... RENAME TO" command
                   2507: # is used to rename a table that is the parent table of one or more
                   2508: # foreign key constraints, the definitions of the foreign key
                   2509: # constraints are modified to refer to the parent table by its new name
                   2510: #
                   2511: # Test that these adjustments are visible in the sqlite_master table.
                   2512: #
                   2513: # EVIDENCE-OF: R-63827-54774 The text of the child CREATE TABLE
                   2514: # statement or statements stored in the sqlite_master table are modified
                   2515: # to reflect the new parent table name.
                   2516: #
                   2517: do_test e_fkey-56.1 {
                   2518:   drop_all_tables
                   2519:   execsql {
                   2520:     CREATE TABLE 'p 1 "parent one"'(a REFERENCES 'p 1 "parent one"', b, PRIMARY KEY(b));
                   2521: 
                   2522:     CREATE TABLE c1(c, d REFERENCES 'p 1 "parent one"' ON UPDATE CASCADE);
                   2523:     CREATE TABLE c2(e, f, FOREIGN KEY(f) REFERENCES 'p 1 "parent one"' ON UPDATE CASCADE);
                   2524:     CREATE TABLE c3(e, 'f col 2', FOREIGN KEY('f col 2') REFERENCES 'p 1 "parent one"' ON UPDATE CASCADE);
                   2525: 
                   2526:     INSERT INTO 'p 1 "parent one"' VALUES(1, 1);
                   2527:     INSERT INTO c1 VALUES(1, 1);
                   2528:     INSERT INTO c2 VALUES(1, 1);
                   2529:     INSERT INTO c3 VALUES(1, 1);
                   2530: 
                   2531:     -- CREATE TABLE q(a, b, PRIMARY KEY(b));
                   2532:   }
                   2533: } {}
                   2534: do_test e_fkey-56.2 {
                   2535:   execsql { ALTER TABLE 'p 1 "parent one"' RENAME TO p }
                   2536: } {}
                   2537: do_test e_fkey-56.3 {
                   2538:   execsql {
                   2539:     UPDATE p SET a = 'xxx', b = 'xxx';
                   2540:     SELECT * FROM p;
                   2541:     SELECT * FROM c1;
                   2542:     SELECT * FROM c2;
                   2543:     SELECT * FROM c3;
                   2544:   }
                   2545: } {xxx xxx 1 xxx 1 xxx 1 xxx}
                   2546: do_test e_fkey-56.4 {
                   2547:   execsql { SELECT sql FROM sqlite_master WHERE type = 'table'}
                   2548: } [list                                                                     \
                   2549:   {CREATE TABLE "p"(a REFERENCES "p", b, PRIMARY KEY(b))}                   \
                   2550:   {CREATE TABLE c1(c, d REFERENCES "p" ON UPDATE CASCADE)}                  \
                   2551:   {CREATE TABLE c2(e, f, FOREIGN KEY(f) REFERENCES "p" ON UPDATE CASCADE)}  \
                   2552:   {CREATE TABLE c3(e, 'f col 2', FOREIGN KEY('f col 2') REFERENCES "p" ON UPDATE CASCADE)} \
                   2553: ]
                   2554: 
                   2555: #-------------------------------------------------------------------------
                   2556: # Check that a DROP TABLE does an implicit DELETE FROM. Which does not
                   2557: # cause any triggers to fire, but does fire foreign key actions.
                   2558: #
                   2559: # EVIDENCE-OF: R-14208-23986 If foreign key constraints are enabled when
                   2560: # it is prepared, the DROP TABLE command performs an implicit DELETE to
                   2561: # remove all rows from the table before dropping it.
                   2562: #
                   2563: # EVIDENCE-OF: R-11078-03945 The implicit DELETE does not cause any SQL
                   2564: # triggers to fire, but may invoke foreign key actions or constraint
                   2565: # violations.
                   2566: #
                   2567: do_test e_fkey-57.1 {
                   2568:   drop_all_tables
                   2569:   execsql {
                   2570:     CREATE TABLE p(a, b, PRIMARY KEY(a, b));
                   2571: 
                   2572:     CREATE TABLE c1(c, d, FOREIGN KEY(c, d) REFERENCES p ON DELETE SET NULL);
                   2573:     CREATE TABLE c2(c, d, FOREIGN KEY(c, d) REFERENCES p ON DELETE SET DEFAULT);
                   2574:     CREATE TABLE c3(c, d, FOREIGN KEY(c, d) REFERENCES p ON DELETE CASCADE);
                   2575:     CREATE TABLE c4(c, d, FOREIGN KEY(c, d) REFERENCES p ON DELETE RESTRICT);
                   2576:     CREATE TABLE c5(c, d, FOREIGN KEY(c, d) REFERENCES p ON DELETE NO ACTION);
                   2577: 
                   2578:     CREATE TABLE c6(c, d, 
                   2579:       FOREIGN KEY(c, d) REFERENCES p ON DELETE RESTRICT 
                   2580:       DEFERRABLE INITIALLY DEFERRED
                   2581:     );
                   2582:     CREATE TABLE c7(c, d, 
                   2583:       FOREIGN KEY(c, d) REFERENCES p ON DELETE NO ACTION
                   2584:       DEFERRABLE INITIALLY DEFERRED
                   2585:     );
                   2586: 
                   2587:     CREATE TABLE log(msg);
                   2588:     CREATE TRIGGER tt AFTER DELETE ON p BEGIN
                   2589:       INSERT INTO log VALUES('delete ' || old.rowid);
                   2590:     END;
                   2591:   }
                   2592: } {}
                   2593: 
                   2594: do_test e_fkey-57.2 {
                   2595:   execsql {
                   2596:     INSERT INTO p VALUES('a', 'b');
                   2597:     INSERT INTO c1 VALUES('a', 'b');
                   2598:     INSERT INTO c2 VALUES('a', 'b');
                   2599:     INSERT INTO c3 VALUES('a', 'b');
                   2600:     BEGIN;
                   2601:       DROP TABLE p;
                   2602:       SELECT * FROM c1;
                   2603:   }
                   2604: } {{} {}}
                   2605: do_test e_fkey-57.3 {
                   2606:   execsql { SELECT * FROM c2 }
                   2607: } {{} {}}
                   2608: do_test e_fkey-57.4 {
                   2609:   execsql { SELECT * FROM c3 }
                   2610: } {}
                   2611: do_test e_fkey-57.5 {
                   2612:   execsql { SELECT * FROM log }
                   2613: } {}
                   2614: do_test e_fkey-57.6 {
                   2615:   execsql ROLLBACK
                   2616: } {}
                   2617: do_test e_fkey-57.7 {
                   2618:   execsql {
                   2619:     BEGIN;
                   2620:       DELETE FROM p;
                   2621:       SELECT * FROM log;
                   2622:     ROLLBACK;
                   2623:   }
                   2624: } {{delete 1}}
                   2625: 
                   2626: #-------------------------------------------------------------------------
                   2627: # If an IMMEDIATE foreign key fails as a result of a DROP TABLE, the
                   2628: # DROP TABLE command fails.
                   2629: #
                   2630: # EVIDENCE-OF: R-32768-47925 If an immediate foreign key constraint is
                   2631: # violated, the DROP TABLE statement fails and the table is not dropped.
                   2632: #
                   2633: do_test e_fkey-58.1 {
                   2634:   execsql { 
                   2635:     DELETE FROM c1;
                   2636:     DELETE FROM c2;
                   2637:     DELETE FROM c3;
                   2638:   }
                   2639:   execsql { INSERT INTO c5 VALUES('a', 'b') }
                   2640:   catchsql { DROP TABLE p }
                   2641: } {1 {foreign key constraint failed}}
                   2642: do_test e_fkey-58.2 {
                   2643:   execsql { SELECT * FROM p }
                   2644: } {a b}
                   2645: do_test e_fkey-58.3 {
                   2646:   catchsql {
                   2647:     BEGIN;
                   2648:       DROP TABLE p;
                   2649:   }
                   2650: } {1 {foreign key constraint failed}}
                   2651: do_test e_fkey-58.4 {
                   2652:   execsql {
                   2653:     SELECT * FROM p;
                   2654:     SELECT * FROM c5;
                   2655:     ROLLBACK;
                   2656:   }
                   2657: } {a b a b}
                   2658: 
                   2659: #-------------------------------------------------------------------------
                   2660: # If a DEFERRED foreign key fails as a result of a DROP TABLE, attempting
                   2661: # to commit the transaction fails unless the violation is fixed.
                   2662: #
                   2663: # EVIDENCE-OF: R-05903-08460 If a deferred foreign key constraint is
                   2664: # violated, then an error is reported when the user attempts to commit
                   2665: # the transaction if the foreign key constraint violations still exist
                   2666: # at that point.
                   2667: #
                   2668: do_test e_fkey-59.1 {
                   2669:   execsql { 
                   2670:     DELETE FROM c1 ; DELETE FROM c2 ; DELETE FROM c3 ;
                   2671:     DELETE FROM c4 ; DELETE FROM c5 ; DELETE FROM c6 ;
                   2672:     DELETE FROM c7 
                   2673:   }
                   2674: } {}
                   2675: do_test e_fkey-59.2 {
                   2676:   execsql { INSERT INTO c7 VALUES('a', 'b') }
                   2677:   execsql {
                   2678:     BEGIN;
                   2679:       DROP TABLE p;
                   2680:   }
                   2681: } {}
                   2682: do_test e_fkey-59.3 {
                   2683:   catchsql COMMIT
                   2684: } {1 {foreign key constraint failed}}
                   2685: do_test e_fkey-59.4 {
                   2686:   execsql { CREATE TABLE p(a, b, PRIMARY KEY(a, b)) }
                   2687:   catchsql COMMIT
                   2688: } {1 {foreign key constraint failed}}
                   2689: do_test e_fkey-59.5 {
                   2690:   execsql { INSERT INTO p VALUES('a', 'b') }
                   2691:   execsql COMMIT
                   2692: } {}
                   2693: 
                   2694: #-------------------------------------------------------------------------
                   2695: # Any "foreign key mismatch" errors encountered while running an implicit
                   2696: # "DELETE FROM tbl" are ignored.
                   2697: #
                   2698: # EVIDENCE-OF: R-57242-37005 Any "foreign key mismatch" errors
                   2699: # encountered as part of an implicit DELETE are ignored.
                   2700: #
                   2701: drop_all_tables
                   2702: do_test e_fkey-60.1 {
                   2703:   execsql {
                   2704:     PRAGMA foreign_keys = OFF;
                   2705: 
                   2706:     CREATE TABLE p(a PRIMARY KEY, b REFERENCES nosuchtable);
                   2707:     CREATE TABLE c1(c, d, FOREIGN KEY(c, d) REFERENCES a);
                   2708:     CREATE TABLE c2(c REFERENCES p(b), d);
                   2709:     CREATE TABLE c3(c REFERENCES p ON DELETE SET NULL, d);
                   2710: 
                   2711:     INSERT INTO p VALUES(1, 2);
                   2712:     INSERT INTO c1 VALUES(1, 2);
                   2713:     INSERT INTO c2 VALUES(1, 2);
                   2714:     INSERT INTO c3 VALUES(1, 2);
                   2715:   }
                   2716: } {}
                   2717: do_test e_fkey-60.2 {
                   2718:   execsql { PRAGMA foreign_keys = ON }
                   2719:   catchsql { DELETE FROM p }
                   2720: } {1 {no such table: main.nosuchtable}}
                   2721: do_test e_fkey-60.3 {
                   2722:   execsql {
                   2723:     BEGIN;
                   2724:       DROP TABLE p;
                   2725:       SELECT * FROM c3;
                   2726:     ROLLBACK;
                   2727:   }
                   2728: } {{} 2}
                   2729: do_test e_fkey-60.4 {
                   2730:   execsql { CREATE TABLE nosuchtable(x PRIMARY KEY) }
                   2731:   catchsql { DELETE FROM p }
                   2732: } {1 {foreign key mismatch}}
                   2733: do_test e_fkey-60.5 {
                   2734:   execsql { DROP TABLE c1 }
                   2735:   catchsql { DELETE FROM p }
                   2736: } {1 {foreign key mismatch}}
                   2737: do_test e_fkey-60.6 {
                   2738:   execsql { DROP TABLE c2 }
                   2739:   execsql { DELETE FROM p }
                   2740: } {}
                   2741: 
                   2742: #-------------------------------------------------------------------------
                   2743: # Test that the special behaviours of ALTER and DROP TABLE are only
                   2744: # activated when foreign keys are enabled. Special behaviours are:
                   2745: #
                   2746: #   1. ADD COLUMN not allowing a REFERENCES clause with a non-NULL 
                   2747: #      default value.
                   2748: #   2. Modifying foreign key definitions when a parent table is RENAMEd.
                   2749: #   3. Running an implicit DELETE FROM command as part of DROP TABLE.
                   2750: #
                   2751: # EVIDENCE-OF: R-54142-41346 The properties of the DROP TABLE and ALTER
                   2752: # TABLE commands described above only apply if foreign keys are enabled.
                   2753: #
                   2754: do_test e_fkey-61.1.1 {
                   2755:   drop_all_tables
                   2756:   execsql { CREATE TABLE t1(a, b) }
                   2757:   catchsql { ALTER TABLE t1 ADD COLUMN c DEFAULT 'xxx' REFERENCES t2 }
                   2758: } {1 {Cannot add a REFERENCES column with non-NULL default value}}
                   2759: do_test e_fkey-61.1.2 {
                   2760:   execsql { PRAGMA foreign_keys = OFF }
                   2761:   execsql { ALTER TABLE t1 ADD COLUMN c DEFAULT 'xxx' REFERENCES t2 }
                   2762:   execsql { SELECT sql FROM sqlite_master WHERE name = 't1' }
                   2763: } {{CREATE TABLE t1(a, b, c DEFAULT 'xxx' REFERENCES t2)}}
                   2764: do_test e_fkey-61.1.3 {
                   2765:   execsql { PRAGMA foreign_keys = ON }
                   2766: } {}
                   2767: 
                   2768: do_test e_fkey-61.2.1 {
                   2769:   drop_all_tables
                   2770:   execsql {
                   2771:     CREATE TABLE p(a UNIQUE);
                   2772:     CREATE TABLE c(b REFERENCES p(a));
                   2773:     BEGIN;
                   2774:       ALTER TABLE p RENAME TO parent;
                   2775:       SELECT sql FROM sqlite_master WHERE name = 'c';
                   2776:     ROLLBACK;
                   2777:   }
                   2778: } {{CREATE TABLE c(b REFERENCES "parent"(a))}}
                   2779: do_test e_fkey-61.2.2 {
                   2780:   execsql {
                   2781:     PRAGMA foreign_keys = OFF;
                   2782:     ALTER TABLE p RENAME TO parent;
                   2783:     SELECT sql FROM sqlite_master WHERE name = 'c';
                   2784:   }
                   2785: } {{CREATE TABLE c(b REFERENCES p(a))}}
                   2786: do_test e_fkey-61.2.3 {
                   2787:   execsql { PRAGMA foreign_keys = ON }
                   2788: } {}
                   2789: 
                   2790: do_test e_fkey-61.3.1 {
                   2791:   drop_all_tables
                   2792:   execsql {
                   2793:     CREATE TABLE p(a UNIQUE);
                   2794:     CREATE TABLE c(b REFERENCES p(a) ON DELETE SET NULL);
                   2795:     INSERT INTO p VALUES('x');
                   2796:     INSERT INTO c VALUES('x');
                   2797:     BEGIN;
                   2798:       DROP TABLE p;
                   2799:       SELECT * FROM c;
                   2800:     ROLLBACK;
                   2801:   }
                   2802: } {{}}
                   2803: do_test e_fkey-61.3.2 {
                   2804:   execsql {
                   2805:     PRAGMA foreign_keys = OFF;
                   2806:     DROP TABLE p;
                   2807:     SELECT * FROM c;
                   2808:   }
                   2809: } {x}
                   2810: do_test e_fkey-61.3.3 {
                   2811:   execsql { PRAGMA foreign_keys = ON }
                   2812: } {}
                   2813: 
                   2814: ###########################################################################
                   2815: ### SECTION 6: Limits and Unsupported Features
                   2816: ###########################################################################
                   2817: 
                   2818: #-------------------------------------------------------------------------
                   2819: # Test that MATCH clauses are parsed, but SQLite treats every foreign key
                   2820: # constraint as if it were "MATCH SIMPLE".
                   2821: #
                   2822: # EVIDENCE-OF: R-24728-13230 SQLite parses MATCH clauses (i.e. does not
                   2823: # report a syntax error if you specify one), but does not enforce them.
                   2824: #
                   2825: # EVIDENCE-OF: R-24450-46174 All foreign key constraints in SQLite are
                   2826: # handled as if MATCH SIMPLE were specified.
                   2827: #
                   2828: foreach zMatch [list SIMPLE PARTIAL FULL Simple parTIAL FuLL ] {
                   2829:   drop_all_tables
                   2830:   do_test e_fkey-62.$zMatch.1 {
                   2831:     execsql "
                   2832:       CREATE TABLE p(a, b, c, PRIMARY KEY(b, c));
                   2833:       CREATE TABLE c(d, e, f, FOREIGN KEY(e, f) REFERENCES p MATCH $zMatch);
                   2834:     "
                   2835:   } {}
                   2836:   do_test e_fkey-62.$zMatch.2 {
                   2837:     execsql { INSERT INTO p VALUES(1, 2, 3)         }
                   2838: 
                   2839:     # MATCH SIMPLE behaviour: Allow any child key that contains one or more
                   2840:     # NULL value to be inserted. Non-NULL values do not have to map to any
                   2841:     # parent key values, so long as at least one field of the child key is
                   2842:     # NULL.
                   2843:     execsql { INSERT INTO c VALUES('w', 2, 3)       }
                   2844:     execsql { INSERT INTO c VALUES('x', 'x', NULL)  }
                   2845:     execsql { INSERT INTO c VALUES('y', NULL, 'x')  }
                   2846:     execsql { INSERT INTO c VALUES('z', NULL, NULL) }
                   2847: 
                   2848:     # Check that the FK is enforced properly if there are no NULL values 
                   2849:     # in the child key columns.
                   2850:     catchsql { INSERT INTO c VALUES('a', 2, 4) }
                   2851:   } {1 {foreign key constraint failed}}
                   2852: }
                   2853: 
                   2854: #-------------------------------------------------------------------------
                   2855: # Test that SQLite does not support the SET CONSTRAINT statement. And
                   2856: # that it is possible to create both immediate and deferred constraints.
                   2857: #
                   2858: # EVIDENCE-OF: R-21599-16038 In SQLite, a foreign key constraint is
                   2859: # permanently marked as deferred or immediate when it is created.
                   2860: #
                   2861: drop_all_tables
                   2862: do_test e_fkey-62.1 {
                   2863:   catchsql { SET CONSTRAINTS ALL IMMEDIATE }
                   2864: } {1 {near "SET": syntax error}}
                   2865: do_test e_fkey-62.2 {
                   2866:   catchsql { SET CONSTRAINTS ALL DEFERRED }
                   2867: } {1 {near "SET": syntax error}}
                   2868: 
                   2869: do_test e_fkey-62.3 {
                   2870:   execsql {
                   2871:     CREATE TABLE p(a, b, PRIMARY KEY(a, b));
                   2872:     CREATE TABLE cd(c, d, 
                   2873:       FOREIGN KEY(c, d) REFERENCES p DEFERRABLE INITIALLY DEFERRED);
                   2874:     CREATE TABLE ci(c, d, 
                   2875:       FOREIGN KEY(c, d) REFERENCES p DEFERRABLE INITIALLY IMMEDIATE);
                   2876:     BEGIN;
                   2877:   }
                   2878: } {}
                   2879: do_test e_fkey-62.4 {
                   2880:   catchsql { INSERT INTO ci VALUES('x', 'y') }
                   2881: } {1 {foreign key constraint failed}}
                   2882: do_test e_fkey-62.5 {
                   2883:   catchsql { INSERT INTO cd VALUES('x', 'y') }
                   2884: } {0 {}}
                   2885: do_test e_fkey-62.6 {
                   2886:   catchsql { COMMIT }
                   2887: } {1 {foreign key constraint failed}}
                   2888: do_test e_fkey-62.7 {
                   2889:   execsql { 
                   2890:     DELETE FROM cd;
                   2891:     COMMIT;
                   2892:   }
                   2893: } {}
                   2894: 
                   2895: #-------------------------------------------------------------------------
                   2896: # Test that the maximum recursion depth of foreign key action programs is
                   2897: # governed by the SQLITE_MAX_TRIGGER_DEPTH and SQLITE_LIMIT_TRIGGER_DEPTH
                   2898: # settings.
                   2899: #
                   2900: # EVIDENCE-OF: R-42264-30503 The SQLITE_MAX_TRIGGER_DEPTH and
                   2901: # SQLITE_LIMIT_TRIGGER_DEPTH settings determine the maximum allowable
                   2902: # depth of trigger program recursion. For the purposes of these limits,
                   2903: # foreign key actions are considered trigger programs.
                   2904: #
                   2905: proc test_on_delete_recursion {limit} {
                   2906:   drop_all_tables
                   2907:   execsql { 
                   2908:     BEGIN;
                   2909:     CREATE TABLE t0(a PRIMARY KEY, b);
                   2910:     INSERT INTO t0 VALUES('x0', NULL);
                   2911:   }
                   2912:   for {set i 1} {$i <= $limit} {incr i} {
                   2913:     execsql "
                   2914:       CREATE TABLE t$i (
                   2915:         a PRIMARY KEY, b REFERENCES t[expr $i-1] ON DELETE CASCADE
                   2916:       );
                   2917:       INSERT INTO t$i VALUES('x$i', 'x[expr $i-1]');
                   2918:     "
                   2919:   }
                   2920:   execsql COMMIT
                   2921:   catchsql "
                   2922:     DELETE FROM t0;
                   2923:     SELECT count(*) FROM t$limit;
                   2924:   "
                   2925: }
                   2926: proc test_on_update_recursion {limit} {
                   2927:   drop_all_tables
                   2928:   execsql { 
                   2929:     BEGIN;
                   2930:     CREATE TABLE t0(a PRIMARY KEY);
                   2931:     INSERT INTO t0 VALUES('xxx');
                   2932:   }
                   2933:   for {set i 1} {$i <= $limit} {incr i} {
                   2934:     set j [expr $i-1]
                   2935: 
                   2936:     execsql "
                   2937:       CREATE TABLE t$i (a PRIMARY KEY REFERENCES t$j ON UPDATE CASCADE);
                   2938:       INSERT INTO t$i VALUES('xxx');
                   2939:     "
                   2940:   }
                   2941:   execsql COMMIT
                   2942:   catchsql "
                   2943:     UPDATE t0 SET a = 'yyy';
                   2944:     SELECT NOT (a='yyy') FROM t$limit;
                   2945:   "
                   2946: }
                   2947: 
                   2948: do_test e_fkey-63.1.1 {
                   2949:   test_on_delete_recursion $SQLITE_MAX_TRIGGER_DEPTH
                   2950: } {0 0}
                   2951: do_test e_fkey-63.1.2 {
                   2952:   test_on_delete_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
                   2953: } {1 {too many levels of trigger recursion}}
                   2954: do_test e_fkey-63.1.3 {
                   2955:   sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
                   2956:   test_on_delete_recursion 5
                   2957: } {0 0}
                   2958: do_test e_fkey-63.1.4 {
                   2959:   test_on_delete_recursion 6
                   2960: } {1 {too many levels of trigger recursion}}
                   2961: do_test e_fkey-63.1.5 {
                   2962:   sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
                   2963: } {5}
                   2964: do_test e_fkey-63.2.1 {
                   2965:   test_on_update_recursion $SQLITE_MAX_TRIGGER_DEPTH
                   2966: } {0 0}
                   2967: do_test e_fkey-63.2.2 {
                   2968:   test_on_update_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
                   2969: } {1 {too many levels of trigger recursion}}
                   2970: do_test e_fkey-63.2.3 {
                   2971:   sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
                   2972:   test_on_update_recursion 5
                   2973: } {0 0}
                   2974: do_test e_fkey-63.2.4 {
                   2975:   test_on_update_recursion 6
                   2976: } {1 {too many levels of trigger recursion}}
                   2977: do_test e_fkey-63.2.5 {
                   2978:   sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
                   2979: } {5}
                   2980: 
                   2981: #-------------------------------------------------------------------------
                   2982: # The setting of the recursive_triggers pragma does not affect foreign
                   2983: # key actions.
                   2984: #
                   2985: # EVIDENCE-OF: R-51769-32730 The PRAGMA recursive_triggers setting does
                   2986: # not not affect the operation of foreign key actions.
                   2987: #
                   2988: foreach recursive_triggers_setting [list 0 1 ON OFF] {
                   2989:   drop_all_tables
                   2990:   execsql "PRAGMA recursive_triggers = $recursive_triggers_setting"
                   2991: 
                   2992:   do_test e_fkey-64.$recursive_triggers_setting.1 {
                   2993:     execsql {
                   2994:       CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1 ON DELETE CASCADE);
                   2995:       INSERT INTO t1 VALUES(1, NULL);
                   2996:       INSERT INTO t1 VALUES(2, 1);
                   2997:       INSERT INTO t1 VALUES(3, 2);
                   2998:       INSERT INTO t1 VALUES(4, 3);
                   2999:       INSERT INTO t1 VALUES(5, 4);
                   3000:       SELECT count(*) FROM t1;
                   3001:     }
                   3002:   } {5}
                   3003:   do_test e_fkey-64.$recursive_triggers_setting.2 {
                   3004:     execsql { SELECT count(*) FROM t1 WHERE a = 1 }
                   3005:   } {1}
                   3006:   do_test e_fkey-64.$recursive_triggers_setting.3 {
                   3007:     execsql { 
                   3008:       DELETE FROM t1 WHERE a = 1;
                   3009:       SELECT count(*) FROM t1;
                   3010:     }
                   3011:   } {0}
                   3012: }
                   3013: 
                   3014: finish_test

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>