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