Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Side by Side Diff: third_party/sqlite/sqlite-src-3080704/test/e_fkey.test

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

Powered by Google App Engine
This is Rietveld 408576698