3
# The author disclaims copyright to this source code. In place of
4
# a legal notice, here is a blessing:
6
# May you do good and not evil.
7
# May you find forgiveness for yourself and forgive others.
8
# May you share freely, never taking more than you give.
10
#***********************************************************************
11
# This file implements regression tests for SQLite library.
13
# This file implements tests for foreign keys.
16
set testdir [file dirname $argv0]
17
source $testdir/tester.tcl
19
ifcapable {!foreignkey||!trigger} {
24
#-------------------------------------------------------------------------
27
# fkey2-1.*: Simple tests to check that immediate and deferred foreign key
28
# constraints work when not inside a transaction.
30
# fkey2-2.*: Tests to verify that deferred foreign keys work inside
31
# explicit transactions (i.e that processing really is deferred).
33
# fkey2-3.*: Tests that a statement transaction is rolled back if an
34
# immediate foreign key constraint is violated.
36
# fkey2-4.*: Test that FK actions may recurse even when recursive triggers
39
# fkey2-5.*: Check that if foreign-keys are enabled, it is not possible
40
# to write to an FK column using the incremental blob API.
42
# fkey2-6.*: Test that FK processing is automatically disabled when
45
# fkey2-7.*: Test using an IPK as the key in the child (referencing) table.
47
# fkey2-8.*: Test that enabling/disabling foreign key support while a
48
# transaction is active is not possible.
50
# fkey2-9.*: Test SET DEFAULT actions.
52
# fkey2-10.*: Test errors.
54
# fkey2-11.*: Test CASCADE actions.
56
# fkey2-12.*: Test RESTRICT actions.
58
# fkey2-13.*: Test that FK processing is performed when a row is REPLACED by
59
# an UPDATE or INSERT statement.
61
# fkey2-14.*: Test the ALTER TABLE and DROP TABLE commands.
63
# fkey2-15.*: Test that if there are no (known) outstanding foreign key
64
# constraint violations in the database, inserting into a parent
65
# table or deleting from a child table does not cause SQLite
66
# to check if this has repaired an outstanding violation.
68
# fkey2-16.*: Test that rows that refer to themselves may be inserted,
69
# updated and deleted.
71
# fkey2-17.*: Test that the "count_changes" pragma does not interfere with
72
# FK constraint processing.
74
# fkey2-18.*: Test that the authorization callback is invoked when processing
77
# fkey2-genfkey.*: Tests that were used with the shell tool .genfkey
78
# command. Recycled to test the built-in implementation.
82
execsql { PRAGMA foreign_keys = on }
84
set FkeySimpleSchema {
85
PRAGMA foreign_keys = on;
86
CREATE TABLE t1(a PRIMARY KEY, b);
87
CREATE TABLE t2(c REFERENCES t1(a) /D/ , d);
89
CREATE TABLE t3(a PRIMARY KEY, b);
90
CREATE TABLE t4(c REFERENCES t3 /D/, d);
92
CREATE TABLE t7(a, b INTEGER PRIMARY KEY);
93
CREATE TABLE t8(c REFERENCES t7 /D/, d);
95
CREATE TABLE t9(a REFERENCES nosuchtable, b);
96
CREATE TABLE t10(a REFERENCES t9(c) /D/, b);
100
set FkeySimpleTests {
101
1.1 "INSERT INTO t2 VALUES(1, 3)" {1 {foreign key constraint failed}}
102
1.2 "INSERT INTO t1 VALUES(1, 2)" {0 {}}
103
1.3 "INSERT INTO t2 VALUES(1, 3)" {0 {}}
104
1.4 "INSERT INTO t2 VALUES(2, 4)" {1 {foreign key constraint failed}}
105
1.5 "INSERT INTO t2 VALUES(NULL, 4)" {0 {}}
106
1.6 "UPDATE t2 SET c=2 WHERE d=4" {1 {foreign key constraint failed}}
107
1.7 "UPDATE t2 SET c=1 WHERE d=4" {0 {}}
108
1.9 "UPDATE t2 SET c=1 WHERE d=4" {0 {}}
109
1.10 "UPDATE t2 SET c=NULL WHERE d=4" {0 {}}
110
1.11 "DELETE FROM t1 WHERE a=1" {1 {foreign key constraint failed}}
111
1.12 "UPDATE t1 SET a = 2" {1 {foreign key constraint failed}}
112
1.13 "UPDATE t1 SET a = 1" {0 {}}
114
2.1 "INSERT INTO t4 VALUES(1, 3)" {1 {foreign key constraint failed}}
115
2.2 "INSERT INTO t3 VALUES(1, 2)" {0 {}}
116
2.3 "INSERT INTO t4 VALUES(1, 3)" {0 {}}
118
4.1 "INSERT INTO t8 VALUES(1, 3)" {1 {foreign key constraint failed}}
119
4.2 "INSERT INTO t7 VALUES(2, 1)" {0 {}}
120
4.3 "INSERT INTO t8 VALUES(1, 3)" {0 {}}
121
4.4 "INSERT INTO t8 VALUES(2, 4)" {1 {foreign key constraint failed}}
122
4.5 "INSERT INTO t8 VALUES(NULL, 4)" {0 {}}
123
4.6 "UPDATE t8 SET c=2 WHERE d=4" {1 {foreign key constraint failed}}
124
4.7 "UPDATE t8 SET c=1 WHERE d=4" {0 {}}
125
4.9 "UPDATE t8 SET c=1 WHERE d=4" {0 {}}
126
4.10 "UPDATE t8 SET c=NULL WHERE d=4" {0 {}}
127
4.11 "DELETE FROM t7 WHERE b=1" {1 {foreign key constraint failed}}
128
4.12 "UPDATE t7 SET b = 2" {1 {foreign key constraint failed}}
129
4.13 "UPDATE t7 SET b = 1" {0 {}}
130
4.14 "INSERT INTO t8 VALUES('a', 'b')" {1 {foreign key constraint failed}}
131
4.15 "UPDATE t7 SET b = 5" {1 {foreign key constraint failed}}
132
4.16 "UPDATE t7 SET rowid = 5" {1 {foreign key constraint failed}}
133
4.17 "UPDATE t7 SET a = 10" {0 {}}
135
5.1 "INSERT INTO t9 VALUES(1, 3)" {1 {no such table: main.nosuchtable}}
136
5.2 "INSERT INTO t10 VALUES(1, 3)" {1 {foreign key mismatch}}
139
do_test fkey2-1.1.0 {
140
execsql [string map {/D/ {}} $FkeySimpleSchema]
142
foreach {tn zSql res} $FkeySimpleTests {
143
do_test fkey2-1.1.$tn { catchsql $zSql } $res
147
do_test fkey2-1.2.0 {
148
execsql [string map {/D/ {DEFERRABLE INITIALLY DEFERRED}} $FkeySimpleSchema]
150
foreach {tn zSql res} $FkeySimpleTests {
151
do_test fkey2-1.2.$tn { catchsql $zSql } $res
155
do_test fkey2-1.3.0 {
156
execsql [string map {/D/ {}} $FkeySimpleSchema]
157
execsql { PRAGMA count_changes = 1 }
159
foreach {tn zSql res} $FkeySimpleTests {
160
if {$res == "0 {}"} { set res {0 1} }
161
do_test fkey2-1.3.$tn { catchsql $zSql } $res
163
execsql { PRAGMA count_changes = 0 }
166
do_test fkey2-1.4.0 {
167
execsql [string map {/D/ {}} $FkeySimpleSchema]
168
execsql { PRAGMA count_changes = 1 }
170
foreach {tn zSql res} $FkeySimpleTests {
171
if {$res == "0 {}"} { set res {0 1} }
173
do_test fkey2-1.4.$tn { catchsql $zSql } $res
176
execsql { PRAGMA count_changes = 0 }
179
# Special test: When the parent key is an IPK, make sure the affinity of
180
# the IPK is not applied to the child key value before it is inserted
181
# into the child table.
182
do_test fkey2-1.5.1 {
184
CREATE TABLE i(i INTEGER PRIMARY KEY);
185
CREATE TABLE j(j REFERENCES i);
186
INSERT INTO i VALUES(35);
187
INSERT INTO j VALUES('35.0');
188
SELECT j, typeof(j) FROM j;
191
do_test fkey2-1.5.2 {
192
catchsql { DELETE FROM i }
193
} {1 {foreign key constraint failed}}
195
# Same test using a regular primary key with integer affinity.
197
do_test fkey2-1.6.1 {
199
CREATE TABLE i(i INT UNIQUE);
200
CREATE TABLE j(j REFERENCES i(i));
201
INSERT INTO i VALUES('35.0');
202
INSERT INTO j VALUES('35.0');
203
SELECT j, typeof(j) FROM j;
204
SELECT i, typeof(i) FROM i;
206
} {35.0 text 35 integer}
207
do_test fkey2-1.6.2 {
208
catchsql { DELETE FROM i }
209
} {1 {foreign key constraint failed}}
211
# Use a collation sequence on the parent key.
213
do_test fkey2-1.7.1 {
215
CREATE TABLE i(i TEXT COLLATE nocase PRIMARY KEY);
216
CREATE TABLE j(j TEXT COLLATE binary REFERENCES i(i));
217
INSERT INTO i VALUES('SQLite');
218
INSERT INTO j VALUES('sqlite');
220
catchsql { DELETE FROM i }
221
} {1 {foreign key constraint failed}}
223
# Use the parent key collation even if it is default and the child key
224
# has an explicit value.
226
do_test fkey2-1.7.2 {
228
CREATE TABLE i(i TEXT PRIMARY KEY); -- Colseq is "BINARY"
229
CREATE TABLE j(j TEXT COLLATE nocase REFERENCES i(i));
230
INSERT INTO i VALUES('SQLite');
232
catchsql { INSERT INTO j VALUES('sqlite') }
233
} {1 {foreign key constraint failed}}
234
do_test fkey2-1.7.3 {
236
INSERT INTO i VALUES('sqlite');
237
INSERT INTO j VALUES('sqlite');
238
DELETE FROM i WHERE i = 'SQLite';
240
catchsql { DELETE FROM i WHERE i = 'sqlite' }
241
} {1 {foreign key constraint failed}}
243
#-------------------------------------------------------------------------
244
# This section (test cases fkey2-2.*) contains tests to check that the
245
# deferred foreign key constraint logic works.
247
proc fkey2-2-test {tn nocommit sql {res {}}} {
249
set expected {1 {foreign key constraint failed}}
251
set expected [list 0 $res]
253
do_test fkey2-2.$tn [list catchsql $sql] $expected
255
do_test fkey2-2.${tn}c {
257
} {1 {foreign key constraint failed}}
264
parent REFERENCES node DEFERRABLE INITIALLY DEFERRED
268
parent REFERENCES node DEFERRABLE INITIALLY DEFERRED
272
fkey2-2-test 1 0 "INSERT INTO node VALUES(1, 0)" FKV
273
fkey2-2-test 2 0 "BEGIN"
274
fkey2-2-test 3 1 "INSERT INTO node VALUES(1, 0)"
275
fkey2-2-test 4 0 "UPDATE node SET parent = NULL"
276
fkey2-2-test 5 0 "COMMIT"
277
fkey2-2-test 6 0 "SELECT * FROM node" {1 {}}
279
fkey2-2-test 7 0 "BEGIN"
280
fkey2-2-test 8 1 "INSERT INTO leaf VALUES('a', 2)"
281
fkey2-2-test 9 1 "INSERT INTO node VALUES(2, 0)"
282
fkey2-2-test 10 0 "UPDATE node SET parent = 1 WHERE nodeid = 2"
283
fkey2-2-test 11 0 "COMMIT"
284
fkey2-2-test 12 0 "SELECT * FROM node" {1 {} 2 1}
285
fkey2-2-test 13 0 "SELECT * FROM leaf" {a 2}
287
fkey2-2-test 14 0 "BEGIN"
288
fkey2-2-test 15 1 "DELETE FROM node WHERE nodeid = 2"
289
fkey2-2-test 16 0 "INSERT INTO node VALUES(2, NULL)"
290
fkey2-2-test 17 0 "COMMIT"
291
fkey2-2-test 18 0 "SELECT * FROM node" {1 {} 2 {}}
292
fkey2-2-test 19 0 "SELECT * FROM leaf" {a 2}
294
fkey2-2-test 20 0 "BEGIN"
295
fkey2-2-test 21 0 "INSERT INTO leaf VALUES('b', 1)"
296
fkey2-2-test 22 0 "SAVEPOINT save"
297
fkey2-2-test 23 0 "DELETE FROM node WHERE nodeid = 1"
298
fkey2-2-test 24 0 "ROLLBACK TO save"
299
fkey2-2-test 25 0 "COMMIT"
300
fkey2-2-test 26 0 "SELECT * FROM node" {1 {} 2 {}}
301
fkey2-2-test 27 0 "SELECT * FROM leaf" {a 2 b 1}
303
fkey2-2-test 28 0 "BEGIN"
304
fkey2-2-test 29 0 "INSERT INTO leaf VALUES('c', 1)"
305
fkey2-2-test 30 0 "SAVEPOINT save"
306
fkey2-2-test 31 0 "DELETE FROM node WHERE nodeid = 1"
307
fkey2-2-test 32 1 "RELEASE save"
308
fkey2-2-test 33 1 "DELETE FROM leaf WHERE cellid = 'b'"
309
fkey2-2-test 34 0 "DELETE FROM leaf WHERE cellid = 'c'"
310
fkey2-2-test 35 0 "COMMIT"
311
fkey2-2-test 36 0 "SELECT * FROM node" {2 {}}
312
fkey2-2-test 37 0 "SELECT * FROM leaf" {a 2}
314
fkey2-2-test 38 0 "SAVEPOINT outer"
315
fkey2-2-test 39 1 "INSERT INTO leaf VALUES('d', 3)"
316
fkey2-2-test 40 1 "RELEASE outer" FKV
317
fkey2-2-test 41 1 "INSERT INTO leaf VALUES('e', 3)"
318
fkey2-2-test 42 0 "INSERT INTO node VALUES(3, 2)"
319
fkey2-2-test 43 0 "RELEASE outer"
321
fkey2-2-test 44 0 "SAVEPOINT outer"
322
fkey2-2-test 45 1 "DELETE FROM node WHERE nodeid=3"
323
fkey2-2-test 47 0 "INSERT INTO node VALUES(3, 2)"
324
fkey2-2-test 48 0 "ROLLBACK TO outer"
325
fkey2-2-test 49 0 "RELEASE outer"
327
fkey2-2-test 50 0 "SAVEPOINT outer"
328
fkey2-2-test 51 1 "INSERT INTO leaf VALUES('f', 4)"
329
fkey2-2-test 52 1 "SAVEPOINT inner"
330
fkey2-2-test 53 1 "INSERT INTO leaf VALUES('g', 4)"
331
fkey2-2-test 54 1 "RELEASE outer" FKV
332
fkey2-2-test 55 1 "ROLLBACK TO inner"
333
fkey2-2-test 56 0 "COMMIT" FKV
334
fkey2-2-test 57 0 "INSERT INTO node VALUES(4, NULL)"
335
fkey2-2-test 58 0 "RELEASE outer"
336
fkey2-2-test 59 0 "SELECT * FROM node" {2 {} 3 2 4 {}}
337
fkey2-2-test 60 0 "SELECT * FROM leaf" {a 2 d 3 e 3 f 4}
339
# The following set of tests check that if a statement that affects
340
# multiple rows violates some foreign key constraints, then strikes a
341
# constraint that causes the statement-transaction to be rolled back,
342
# the deferred constraint counter is correctly reset to the value it
343
# had before the statement-transaction was opened.
345
fkey2-2-test 61 0 "BEGIN"
346
fkey2-2-test 62 0 "DELETE FROM leaf"
347
fkey2-2-test 63 0 "DELETE FROM node"
348
fkey2-2-test 64 1 "INSERT INTO leaf VALUES('a', 1)"
349
fkey2-2-test 65 1 "INSERT INTO leaf VALUES('b', 2)"
350
fkey2-2-test 66 1 "INSERT INTO leaf VALUES('c', 1)"
351
do_test fkey2-2-test-67 {
352
catchsql "INSERT INTO node SELECT parent, 3 FROM leaf"
353
} {1 {column nodeid is not unique}}
354
fkey2-2-test 68 0 "COMMIT" FKV
355
fkey2-2-test 69 1 "INSERT INTO node VALUES(1, NULL)"
356
fkey2-2-test 70 0 "INSERT INTO node VALUES(2, NULL)"
357
fkey2-2-test 71 0 "COMMIT"
359
fkey2-2-test 72 0 "BEGIN"
360
fkey2-2-test 73 1 "DELETE FROM node"
361
fkey2-2-test 74 0 "INSERT INTO node(nodeid) SELECT DISTINCT parent FROM leaf"
362
fkey2-2-test 75 0 "COMMIT"
364
#-------------------------------------------------------------------------
365
# Test cases fkey2-3.* test that a program that executes foreign key
366
# actions (CASCADE, SET DEFAULT, SET NULL etc.) or tests FK constraints
367
# opens a statement transaction if required.
369
# fkey2-3.1.*: Test UPDATE statements.
370
# fkey2-3.2.*: Test DELETE statements.
373
do_test fkey2-3.1.1 {
375
CREATE TABLE ab(a PRIMARY KEY, b);
377
c PRIMARY KEY REFERENCES ab ON UPDATE CASCADE ON DELETE CASCADE,
381
e REFERENCES cd ON UPDATE CASCADE,
386
do_test fkey2-3.1.2 {
388
INSERT INTO ab VALUES(1, 'b');
389
INSERT INTO cd VALUES(1, 'd');
390
INSERT INTO ef VALUES(1, 'e');
393
do_test fkey2-3.1.3 {
394
catchsql { UPDATE ab SET a = 5 }
395
} {1 {constraint failed}}
396
do_test fkey2-3.1.4 {
397
execsql { SELECT * FROM ab }
399
do_test fkey2-3.1.4 {
401
catchsql { UPDATE ab SET a = 5 }
402
} {1 {constraint failed}}
403
do_test fkey2-3.1.5 {
405
execsql { SELECT * FROM ab; SELECT * FROM cd; SELECT * FROM ef }
408
do_test fkey2-3.2.1 {
410
catchsql { DELETE FROM ab }
411
} {1 {foreign key constraint failed}}
412
do_test fkey2-3.2.2 {
414
execsql { SELECT * FROM ab; SELECT * FROM cd; SELECT * FROM ef }
417
#-------------------------------------------------------------------------
418
# Test cases fkey2-4.* test that recursive foreign key actions
419
# (i.e. CASCADE) are allowed even if recursive triggers are disabled.
426
parent REFERENCES t1 ON DELETE CASCADE
428
CREATE TABLE t2(node PRIMARY KEY, parent);
429
CREATE TRIGGER t2t AFTER DELETE ON t2 BEGIN
430
DELETE FROM t2 WHERE parent = old.node;
432
INSERT INTO t1 VALUES(1, NULL);
433
INSERT INTO t1 VALUES(2, 1);
434
INSERT INTO t1 VALUES(3, 1);
435
INSERT INTO t1 VALUES(4, 2);
436
INSERT INTO t1 VALUES(5, 2);
437
INSERT INTO t1 VALUES(6, 3);
438
INSERT INTO t1 VALUES(7, 3);
439
INSERT INTO t2 SELECT * FROM t1;
443
execsql { PRAGMA recursive_triggers = off }
446
DELETE FROM t1 WHERE node = 1;
452
DELETE FROM t2 WHERE node = 1;
458
execsql { PRAGMA recursive_triggers = on }
461
DELETE FROM t1 WHERE node = 1;
467
DELETE FROM t2 WHERE node = 1;
473
#-------------------------------------------------------------------------
474
# Test cases fkey2-5.* verify that the incremental blob API may not
475
# write to a foreign key column while foreign-keys are enabled.
481
CREATE TABLE t1(a PRIMARY KEY, b);
482
CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1(a));
483
INSERT INTO t1 VALUES('hello', 'world');
484
INSERT INTO t2 VALUES('key', 'hello');
488
set rc [catch { set fd [db incrblob t2 b 1] } msg]
490
} {1 {cannot open foreign key column for writing}}
492
set rc [catch { set fd [db incrblob -readonly t2 b 1] } msg]
497
execsql { PRAGMA foreign_keys = off }
498
set rc [catch { set fd [db incrblob t2 b 1] } msg]
503
execsql { PRAGMA foreign_keys = on }
511
CREATE TABLE t1(a REFERENCES t2(c), b);
512
CREATE TABLE t2(c UNIQUE, b);
513
INSERT INTO t2 VALUES(1, 2);
514
INSERT INTO t1 VALUES(1, 2);
520
#-------------------------------------------------------------------------
521
# Test that it is possible to use an INTEGER PRIMARY KEY as the child key
522
# of a foreign constraint.
527
CREATE TABLE t1(a PRIMARY KEY, b);
528
CREATE TABLE t2(c INTEGER PRIMARY KEY REFERENCES t1, b);
532
catchsql { INSERT INTO t2 VALUES(1, 'A'); }
533
} {1 {foreign key constraint failed}}
536
INSERT INTO t1 VALUES(1, 2);
537
INSERT INTO t1 VALUES(2, 3);
538
INSERT INTO t2 VALUES(1, 'A');
542
execsql { UPDATE t2 SET c = 2 }
545
catchsql { UPDATE t2 SET c = 3 }
546
} {1 {foreign key constraint failed}}
548
catchsql { DELETE FROM t1 WHERE a = 2 }
549
} {1 {foreign key constraint failed}}
551
execsql { DELETE FROM t1 WHERE a = 1 }
554
catchsql { UPDATE t1 SET a = 3 }
555
} {1 {foreign key constraint failed}}
557
catchsql { UPDATE t2 SET rowid = 3 }
558
} {1 {foreign key constraint failed}}
560
#-------------------------------------------------------------------------
561
# Test that it is not possible to enable/disable FK support while a
562
# transaction is open.
565
proc fkey2-8-test {tn zSql value} {
566
do_test fkey-2.8.$tn.1 [list execsql $zSql] {}
567
do_test fkey-2.8.$tn.2 { execsql "PRAGMA foreign_keys" } $value
569
fkey2-8-test 1 { PRAGMA foreign_keys = 0 } 0
570
fkey2-8-test 2 { PRAGMA foreign_keys = 1 } 1
571
fkey2-8-test 3 { BEGIN } 1
572
fkey2-8-test 4 { PRAGMA foreign_keys = 0 } 1
573
fkey2-8-test 5 { COMMIT } 1
574
fkey2-8-test 6 { PRAGMA foreign_keys = 0 } 0
575
fkey2-8-test 7 { BEGIN } 0
576
fkey2-8-test 8 { PRAGMA foreign_keys = 1 } 0
577
fkey2-8-test 9 { COMMIT } 0
578
fkey2-8-test 10 { PRAGMA foreign_keys = 1 } 1
579
fkey2-8-test 11 { PRAGMA foreign_keys = off } 0
580
fkey2-8-test 12 { PRAGMA foreign_keys = on } 1
581
fkey2-8-test 13 { PRAGMA foreign_keys = no } 0
582
fkey2-8-test 14 { PRAGMA foreign_keys = yes } 1
583
fkey2-8-test 15 { PRAGMA foreign_keys = false } 0
584
fkey2-8-test 16 { PRAGMA foreign_keys = true } 1
586
#-------------------------------------------------------------------------
587
# The following tests, fkey2-9.*, test SET DEFAULT actions.
590
do_test fkey2-9.1.1 {
592
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
594
c INTEGER PRIMARY KEY,
595
d INTEGER DEFAULT 1 REFERENCES t1 ON DELETE SET DEFAULT
600
do_test fkey2-9.1.2 {
602
INSERT INTO t1 VALUES(1, 'one');
603
INSERT INTO t1 VALUES(2, 'two');
604
INSERT INTO t2 VALUES(1, 2);
606
DELETE FROM t1 WHERE a = 2;
610
do_test fkey2-9.1.3 {
612
INSERT INTO t1 VALUES(2, 'two');
614
DELETE FROM t1 WHERE a = 1;
618
do_test fkey2-9.1.4 {
619
execsql { SELECT * FROM t1 }
621
do_test fkey2-9.1.5 {
622
catchsql { DELETE FROM t1 }
623
} {1 {foreign key constraint failed}}
625
do_test fkey2-9.2.1 {
627
CREATE TABLE pp(a, b, c, PRIMARY KEY(b, c));
628
CREATE TABLE cc(d DEFAULT 3, e DEFAULT 1, f DEFAULT 2,
629
FOREIGN KEY(f, d) REFERENCES pp
630
ON UPDATE SET DEFAULT
633
INSERT INTO pp VALUES(1, 2, 3);
634
INSERT INTO pp VALUES(4, 5, 6);
635
INSERT INTO pp VALUES(7, 8, 9);
638
do_test fkey2-9.2.2 {
640
INSERT INTO cc VALUES(6, 'A', 5);
641
INSERT INTO cc VALUES(6, 'B', 5);
642
INSERT INTO cc VALUES(9, 'A', 8);
643
INSERT INTO cc VALUES(9, 'B', 8);
644
UPDATE pp SET b = 1 WHERE a = 7;
647
} {6 A 5 6 B 5 3 A 2 3 B 2}
648
do_test fkey2-9.2.3 {
650
DELETE FROM pp WHERE a = 4;
653
} {{} A {} {} B {} 3 A 2 3 B 2}
655
#-------------------------------------------------------------------------
656
# The following tests, fkey2-10.*, test "foreign key mismatch" and
661
CREATE TABLE p(a PRIMARY KEY, b);
662
CREATE TABLE c(x REFERENCES p(c));
664
CREATE TABLE c(x REFERENCES v(y));
665
CREATE VIEW v AS SELECT x AS y FROM c;
667
CREATE TABLE p(a, b, PRIMARY KEY(a, b));
668
CREATE TABLE c(x REFERENCES p);
670
CREATE TABLE p(a COLLATE binary, b);
671
CREATE UNIQUE INDEX i ON p(a COLLATE nocase);
672
CREATE TABLE c(x REFERENCES p(a));
675
do_test fkey2-10.1.[incr tn] {
677
catchsql { INSERT INTO c DEFAULT VALUES }
678
} {1 {foreign key mismatch}}
681
# "rowid" cannot be used as part of a child or parent key definition
682
# unless it happens to be the name of an explicitly declared column.
684
do_test fkey2-10.2.1 {
687
CREATE TABLE t1(a PRIMARY KEY, b);
688
CREATE TABLE t2(c, d, FOREIGN KEY(rowid) REFERENCES t1(a));
690
} {1 {unknown column "rowid" in foreign key definition}}
691
do_test fkey2-10.2.2 {
694
CREATE TABLE t1(a PRIMARY KEY, b);
695
CREATE TABLE t2(rowid, d, FOREIGN KEY(rowid) REFERENCES t1(a));
698
do_test fkey2-10.2.1 {
701
CREATE TABLE t1(a, b);
702
CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(rowid));
703
INSERT INTO t1(rowid, a, b) VALUES(1, 1, 1);
704
INSERT INTO t2 VALUES(1, 1);
706
} {1 {foreign key mismatch}}
707
do_test fkey2-10.2.2 {
710
CREATE TABLE t1(rowid PRIMARY KEY, b);
711
CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(rowid));
712
INSERT INTO t1(rowid, b) VALUES(1, 1);
713
INSERT INTO t2 VALUES(1, 1);
718
#-------------------------------------------------------------------------
719
# The following tests, fkey2-11.*, test CASCADE actions.
722
do_test fkey2-11.1.1 {
724
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
725
CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(a) ON UPDATE CASCADE);
727
INSERT INTO t1 VALUES(10, 100);
728
INSERT INTO t2 VALUES(10, 100);
729
UPDATE t1 SET a = 15;
734
#-------------------------------------------------------------------------
735
# The following tests, fkey2-12.*, test RESTRICT actions.
738
do_test fkey2-12.1.1 {
740
CREATE TABLE t1(a, b PRIMARY KEY);
742
x REFERENCES t1 ON UPDATE RESTRICT DEFERRABLE INITIALLY DEFERRED
744
INSERT INTO t1 VALUES(1, 'one');
745
INSERT INTO t1 VALUES(2, 'two');
746
INSERT INTO t1 VALUES(3, 'three');
749
do_test fkey2-12.1.2 {
751
execsql "INSERT INTO t2 VALUES('two')"
753
do_test fkey2-12.1.3 {
754
execsql "UPDATE t1 SET b = 'four' WHERE b = 'one'"
756
do_test fkey2-12.1.4 {
757
catchsql "UPDATE t1 SET b = 'five' WHERE b = 'two'"
758
} {1 {foreign key constraint failed}}
759
do_test fkey2-12.1.5 {
760
execsql "DELETE FROM t1 WHERE b = 'two'"
762
do_test fkey2-12.1.6 {
764
} {1 {foreign key constraint failed}}
765
do_test fkey2-12.1.7 {
767
INSERT INTO t1 VALUES(2, 'two');
773
do_test fkey2-12.2.1 {
775
CREATE TABLE t1(x COLLATE NOCASE PRIMARY KEY);
776
CREATE TRIGGER tt1 AFTER DELETE ON t1
777
WHEN EXISTS ( SELECT 1 FROM t2 WHERE old.x = y )
779
INSERT INTO t1 VALUES(old.x);
781
CREATE TABLE t2(y REFERENCES t1);
782
INSERT INTO t1 VALUES('A');
783
INSERT INTO t1 VALUES('B');
784
INSERT INTO t2 VALUES('a');
785
INSERT INTO t2 VALUES('b');
791
do_test fkey2-12.2.2 {
792
execsql { DELETE FROM t1 }
798
do_test fkey2-12.2.3 {
801
CREATE TABLE t2(y REFERENCES t1 ON DELETE RESTRICT);
802
INSERT INTO t2 VALUES('a');
803
INSERT INTO t2 VALUES('b');
805
catchsql { DELETE FROM t1 }
806
} {1 {foreign key constraint failed}}
807
do_test fkey2-12.2.4 {
815
do_test fkey2-12.3.1 {
818
c00, c01, c02, c03, c04, c05, c06, c07, c08, c09,
819
c10, c11, c12, c13, c14, c15, c16, c17, c18, c19,
820
c20, c21, c22, c23, c24, c25, c26, c27, c28, c29,
821
c30, c31, c32, c33, c34, c35, c36, c37, c38, c39,
822
PRIMARY KEY(c34, c35)
825
c00, c01, c02, c03, c04, c05, c06, c07, c08, c09,
826
c10, c11, c12, c13, c14, c15, c16, c17, c18, c19,
827
c20, c21, c22, c23, c24, c25, c26, c27, c28, c29,
828
c30, c31, c32, c33, c34, c35, c36, c37, c38, c39,
829
FOREIGN KEY(c39, c38) REFERENCES up ON UPDATE CASCADE
833
do_test fkey2-12.3.2 {
835
INSERT INTO up(c34, c35) VALUES('yes', 'no');
836
INSERT INTO down(c39, c38) VALUES('yes', 'no');
837
UPDATE up SET c34 = 'possibly';
838
SELECT c38, c39 FROM down;
842
do_test fkey2-12.3.3 {
843
catchsql { INSERT INTO down(c39, c38) VALUES('yes', 'no') }
844
} {1 {foreign key constraint failed}}
845
do_test fkey2-12.3.4 {
847
INSERT INTO up(c34, c35) VALUES('yes', 'no');
848
INSERT INTO down(c39, c38) VALUES('yes', 'no');
850
catchsql { DELETE FROM up WHERE c34 = 'yes' }
851
} {1 {foreign key constraint failed}}
852
do_test fkey2-12.3.5 {
854
DELETE FROM up WHERE c34 = 'possibly';
855
SELECT c34, c35 FROM up;
856
SELECT c39, c38 FROM down;
860
#-------------------------------------------------------------------------
861
# The following tests, fkey2-13.*, test that FK processing is performed
862
# when rows are REPLACEd.
865
do_test fkey2-13.1.1 {
867
CREATE TABLE pp(a UNIQUE, b, c, PRIMARY KEY(b, c));
868
CREATE TABLE cc(d, e, f UNIQUE, FOREIGN KEY(d, e) REFERENCES pp);
869
INSERT INTO pp VALUES(1, 2, 3);
870
INSERT INTO cc VALUES(2, 3, 1);
874
1 "REPLACE INTO pp VALUES(1, 4, 5)"
875
2 "REPLACE INTO pp(rowid, a, b, c) VALUES(1, 2, 3, 4)"
877
do_test fkey2-13.1.$tn.1 {
879
} {1 {foreign key constraint failed}}
880
do_test fkey2-13.1.$tn.2 {
886
do_test fkey2-13.1.$tn.3 {
889
} {1 {foreign key constraint failed}}
890
do_test fkey2-13.1.$tn.4 {
898
do_test fkey2-13.1.3 {
900
REPLACE INTO pp(rowid, a, b, c) VALUES(1, 2, 2, 3);
901
SELECT rowid, * FROM pp;
905
do_test fkey2-13.1.4 {
907
REPLACE INTO pp(rowid, a, b, c) VALUES(2, 2, 2, 3);
908
SELECT rowid, * FROM pp;
913
#-------------------------------------------------------------------------
914
# The following tests, fkey2-14.*, test that the "DROP TABLE" and "ALTER
915
# TABLE" commands work as expected wrt foreign key constraints.
917
# fkey2-14.1*: ALTER TABLE ADD COLUMN
918
# fkey2-14.2*: ALTER TABLE RENAME TABLE
919
# fkey2-14.3*: DROP TABLE
922
ifcapable altertable {
923
do_test fkey2-14.1.1 {
924
# Adding a column with a REFERENCES clause is not supported.
926
CREATE TABLE t1(a PRIMARY KEY);
927
CREATE TABLE t2(a, b);
929
catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
931
do_test fkey2-14.1.2 {
932
catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
934
do_test fkey2-14.1.3 {
935
catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
937
do_test fkey2-14.1.4 {
938
catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
939
} {1 {Cannot add a REFERENCES column with non-NULL default value}}
940
do_test fkey2-14.1.5 {
941
catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
942
} {1 {Cannot add a REFERENCES column with non-NULL default value}}
943
do_test fkey2-14.1.6 {
945
PRAGMA foreign_keys = off;
946
ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
947
PRAGMA foreign_keys = on;
948
SELECT sql FROM sqlite_master WHERE name='t2';
950
} {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
953
# Test the sqlite_rename_parent() function directly.
955
proc test_rename_parent {zCreate zOld zNew} {
956
db eval {SELECT sqlite_rename_parent($zCreate, $zOld, $zNew)}
958
do_test fkey2-14.2.1.1 {
959
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
960
} {{CREATE TABLE t1(a REFERENCES "t3")}}
961
do_test fkey2-14.2.1.2 {
962
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
963
} {{CREATE TABLE t1(a REFERENCES t2)}}
964
do_test fkey2-14.2.1.3 {
965
test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
966
} {{CREATE TABLE t1(a REFERENCES "t3")}}
968
# Test ALTER TABLE RENAME TABLE a bit.
970
do_test fkey2-14.2.2.1 {
973
CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1);
974
CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2);
975
CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
977
execsql { SELECT sql FROM sqlite_master WHERE type = 'table'}
979
{CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)} \
980
{CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)} \
981
{CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \
983
do_test fkey2-14.2.2.2 {
984
execsql { ALTER TABLE t1 RENAME TO t4 }
985
execsql { SELECT sql FROM sqlite_master WHERE type = 'table'}
987
{CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")} \
988
{CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)} \
989
{CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
991
do_test fkey2-14.2.2.3 {
992
catchsql { INSERT INTO t3 VALUES(1, 2, 3) }
993
} {1 {foreign key constraint failed}}
994
do_test fkey2-14.2.2.4 {
995
execsql { INSERT INTO t4 VALUES(1, NULL) }
997
do_test fkey2-14.2.2.5 {
998
catchsql { UPDATE t4 SET b = 5 }
999
} {1 {foreign key constraint failed}}
1000
do_test fkey2-14.2.2.6 {
1001
catchsql { UPDATE t4 SET b = 1 }
1003
do_test fkey2-14.2.2.7 {
1004
execsql { INSERT INTO t3 VALUES(1, NULL, 1) }
1008
do_test fkey-2.14.3.1 {
1011
CREATE TABLE t1(a, b REFERENCES nosuchtable);
1015
do_test fkey-2.14.3.2 {
1017
CREATE TABLE t1(a PRIMARY KEY, b);
1018
INSERT INTO t1 VALUES('a', 1);
1019
CREATE TABLE t2(x REFERENCES t1);
1020
INSERT INTO t2 VALUES('a');
1023
do_test fkey-2.14.3.3 {
1024
catchsql { DROP TABLE t1 }
1025
} {1 {foreign key constraint failed}}
1026
do_test fkey-2.14.3.4 {
1032
do_test fkey-2.14.3.4 {
1033
catchsql { INSERT INTO t2 VALUES('x') }
1034
} {1 {no such table: main.t1}}
1035
do_test fkey-2.14.3.5 {
1037
CREATE TABLE t1(x PRIMARY KEY);
1038
INSERT INTO t1 VALUES('x');
1040
execsql { INSERT INTO t2 VALUES('x') }
1042
do_test fkey-2.14.3.6 {
1043
catchsql { DROP TABLE t1 }
1044
} {1 {foreign key constraint failed}}
1045
do_test fkey-2.14.3.7 {
1051
do_test fkey-2.14.3.8 {
1053
CREATE TABLE pp(x, y, PRIMARY KEY(x, y));
1054
CREATE TABLE cc(a, b, FOREIGN KEY(a, b) REFERENCES pp(x, z));
1056
catchsql { INSERT INTO cc VALUES(1, 2) }
1057
} {1 {foreign key mismatch}}
1058
do_test fkey-2.14.3.9 {
1059
execsql { DROP TABLE cc }
1061
do_test fkey-2.14.3.10 {
1063
CREATE TABLE cc(a, b,
1064
FOREIGN KEY(a, b) REFERENCES pp DEFERRABLE INITIALLY DEFERRED
1068
INSERT INTO pp VALUES('a', 'b');
1069
INSERT INTO cc VALUES('a', 'b');
1072
CREATE TABLE pp(a, b, c, PRIMARY KEY(b, c));
1073
INSERT INTO pp VALUES(1, 'a', 'b');
1077
do_test fkey-2.14.3.11 {
1085
do_test fkey-2.14.3.12 {
1087
CREATE TABLE b1(a, b);
1088
CREATE TABLE b2(a, b REFERENCES b1);
1092
do_test fkey-2.14.3.13 {
1094
CREATE TABLE b3(a, b REFERENCES b2 DEFERRABLE INITIALLY DEFERRED);
1099
# Test that nothing goes wrong when dropping a table that refers to a view.
1100
# Or dropping a view that an existing FK (incorrectly) refers to. Or either
1101
# of the above scenarios with a virtual table.
1103
do_test fkey-2.14.4.1 {
1105
CREATE TABLE t1(x REFERENCES v);
1106
CREATE VIEW v AS SELECT * FROM t1;
1109
do_test fkey-2.14.4.2 {
1115
register_echo_module db
1116
do_test fkey-2.14.4.3 {
1117
execsql { CREATE VIRTUAL TABLE v USING echo(t1) }
1119
do_test fkey-2.14.4.2 {
1126
#-------------------------------------------------------------------------
1127
# The following tests, fkey2-15.*, test that unnecessary FK related scans
1128
# and lookups are avoided when the constraint counters are zero.
1131
proc execsqlS {zSql} {
1132
set ::sqlite_search_count 0
1133
set ::sqlite_found_count 0
1134
set res [uplevel [list execsql $zSql]]
1135
concat [expr $::sqlite_found_count + $::sqlite_search_count] $res
1137
do_test fkey2-15.1.1 {
1139
CREATE TABLE pp(a PRIMARY KEY, b);
1140
CREATE TABLE cc(x, y REFERENCES pp DEFERRABLE INITIALLY DEFERRED);
1141
INSERT INTO pp VALUES(1, 'one');
1142
INSERT INTO pp VALUES(2, 'two');
1143
INSERT INTO cc VALUES('neung', 1);
1144
INSERT INTO cc VALUES('song', 2);
1147
do_test fkey2-15.1.2 {
1148
execsqlS { INSERT INTO pp VALUES(3, 'three') }
1150
do_test fkey2-15.1.3 {
1153
INSERT INTO cc VALUES('see', 4); -- Violates deferred constraint
1155
execsqlS { INSERT INTO pp VALUES(5, 'five') }
1157
do_test fkey2-15.1.4 {
1158
execsql { DELETE FROM cc WHERE x = 'see' }
1159
execsqlS { INSERT INTO pp VALUES(6, 'six') }
1161
do_test fkey2-15.1.5 {
1164
do_test fkey2-15.1.6 {
1167
DELETE FROM cc WHERE x = 'neung';
1171
do_test fkey2-15.1.7 {
1174
DELETE FROM pp WHERE a = 2;
1177
DELETE FROM cc WHERE x = 'neung';
1182
#-------------------------------------------------------------------------
1183
# This next block of tests, fkey2-16.*, test that rows that refer to
1184
# themselves may be inserted and deleted.
1186
foreach {tn zSchema} {
1187
1 { CREATE TABLE self(a INTEGER PRIMARY KEY, b REFERENCES self(a)) }
1188
2 { CREATE TABLE self(a PRIMARY KEY, b REFERENCES self(a)) }
1189
3 { CREATE TABLE self(a UNIQUE, b INTEGER PRIMARY KEY REFERENCES self(a)) }
1192
do_test fkey2-16.1.$tn.1 {
1194
execsql { INSERT INTO self VALUES(13, 13) }
1196
do_test fkey2-16.1.$tn.2 {
1197
execsql { UPDATE self SET a = 14, b = 14 }
1200
do_test fkey2-16.1.$tn.3 {
1201
catchsql { UPDATE self SET b = 15 }
1202
} {1 {foreign key constraint failed}}
1204
do_test fkey2-16.1.$tn.4 {
1205
catchsql { UPDATE self SET a = 15 }
1206
} {1 {foreign key constraint failed}}
1208
do_test fkey2-16.1.$tn.5 {
1209
catchsql { UPDATE self SET a = 15, b = 16 }
1210
} {1 {foreign key constraint failed}}
1212
do_test fkey2-16.1.$tn.6 {
1213
catchsql { UPDATE self SET a = 17, b = 17 }
1216
do_test fkey2-16.1.$tn.7 {
1217
execsql { DELETE FROM self }
1219
do_test fkey2-16.1.$tn.8 {
1220
catchsql { INSERT INTO self VALUES(20, 21) }
1221
} {1 {foreign key constraint failed}}
1224
#-------------------------------------------------------------------------
1225
# This next block of tests, fkey2-17.*, tests that if "PRAGMA count_changes"
1226
# is turned on statements that violate immediate FK constraints return
1227
# SQLITE_CONSTRAINT immediately, not after returning a number of rows.
1228
# Whereas statements that violate deferred FK constraints return the number
1229
# of rows before failing.
1231
# Also test that rows modified by FK actions are not counted in either the
1232
# returned row count or the values returned by sqlite3_changes(). Like
1233
# trigger related changes, they are included in sqlite3_total_changes() though.
1236
do_test fkey2-17.1.1 {
1237
execsql { PRAGMA count_changes = 1 }
1239
CREATE TABLE one(a, b, c, UNIQUE(b, c));
1240
CREATE TABLE two(d, e, f, FOREIGN KEY(e, f) REFERENCES one(b, c));
1241
INSERT INTO one VALUES(1, 2, 3);
1244
do_test fkey2-17.1.2 {
1245
set STMT [sqlite3_prepare_v2 db "INSERT INTO two VALUES(4, 5, 6)" -1 dummy]
1247
} {SQLITE_CONSTRAINT}
1248
do_test fkey2-17.1.3 {
1251
do_test fkey2-17.1.4 {
1252
sqlite3_finalize $STMT
1253
} {SQLITE_CONSTRAINT}
1254
do_test fkey2-17.1.5 {
1256
INSERT INTO one VALUES(2, 3, 4);
1257
INSERT INTO one VALUES(3, 4, 5);
1258
INSERT INTO two VALUES(1, 2, 3);
1259
INSERT INTO two VALUES(2, 3, 4);
1260
INSERT INTO two VALUES(3, 4, 5);
1263
do_test fkey2-17.1.6 {
1266
INSERT INTO one VALUES(0, 0, 0);
1267
UPDATE two SET e=e+1, f=f+1;
1269
} {1 {foreign key constraint failed}}
1270
do_test fkey2-17.1.7 {
1271
execsql { SELECT * FROM one }
1272
} {1 2 3 2 3 4 3 4 5 0 0 0}
1273
do_test fkey2-17.1.8 {
1274
execsql { SELECT * FROM two }
1275
} {1 2 3 2 3 4 3 4 5}
1276
do_test fkey2-17.1.9 {
1279
do_test fkey2-17.1.10 {
1283
FOREIGN KEY(h, i) REFERENCES one(b, c) DEFERRABLE INITIALLY DEFERRED
1287
do_test fkey2-17.1.11 {
1288
set STMT [sqlite3_prepare_v2 db "INSERT INTO three VALUES(7, 8, 9)" -1 dummy]
1291
do_test fkey2-17.1.12 {
1292
sqlite3_column_text $STMT 0
1294
do_test fkey2-17.1.13 {
1296
} {SQLITE_CONSTRAINT}
1297
do_test fkey2-17.1.14 {
1298
sqlite3_finalize $STMT
1299
} {SQLITE_CONSTRAINT}
1302
do_test fkey2-17.2.1 {
1304
CREATE TABLE high("a'b!" PRIMARY KEY, b);
1307
"d&6" REFERENCES high ON UPDATE CASCADE ON DELETE CASCADE
1311
do_test fkey2-17.2.2 {
1313
INSERT INTO high VALUES('a', 'b');
1314
INSERT INTO low VALUES('b', 'a');
1318
set nTotal [db total_changes]
1319
do_test fkey2-17.2.3 {
1320
execsql { UPDATE high SET "a'b!" = 'c' }
1322
do_test fkey2-17.2.4 {
1325
do_test fkey2-17.2.5 {
1326
expr [db total_changes] - $nTotal
1328
do_test fkey2-17.2.6 {
1329
execsql { SELECT * FROM high ; SELECT * FROM low }
1331
do_test fkey2-17.2.7 {
1332
execsql { DELETE FROM high }
1334
do_test fkey2-17.2.8 {
1337
do_test fkey2-17.2.9 {
1338
expr [db total_changes] - $nTotal
1340
do_test fkey2-17.2.10 {
1341
execsql { SELECT * FROM high ; SELECT * FROM low }
1343
execsql { PRAGMA count_changes = 0 }
1345
#-------------------------------------------------------------------------
1346
# Test that the authorization callback works.
1350
do_test fkey2-18.1 {
1352
CREATE TABLE long(a, b PRIMARY KEY, c);
1353
CREATE TABLE short(d, e, f REFERENCES long);
1354
CREATE TABLE mid(g, h, i REFERENCES long DEFERRABLE INITIALLY DEFERRED);
1358
proc auth {args} {eval lappend ::authargs $args ; return SQLITE_OK}
1361
# An insert on the parent table must read the child key of any deferred
1362
# foreign key constraints. But not the child key of immediate constraints.
1364
do_test fkey2-18.2 {
1365
execsql { INSERT INTO long VALUES(1, 2, 3) }
1367
} {SQLITE_INSERT long {} main {} SQLITE_READ mid i main {}}
1369
# An insert on the child table of an immediate constraint must read the
1370
# parent key columns (to see if it is a violation or not).
1372
do_test fkey2-18.3 {
1373
execsql { INSERT INTO short VALUES(1, 3, 2) }
1375
} {SQLITE_INSERT short {} main {} SQLITE_READ long b main {}}
1377
# As must an insert on the child table of a deferred constraint.
1379
do_test fkey2-18.4 {
1380
execsql { INSERT INTO mid VALUES(1, 3, 2) }
1382
} {SQLITE_INSERT mid {} main {} SQLITE_READ long b main {}}
1384
do_test fkey2-18.5 {
1386
CREATE TABLE nought(a, b PRIMARY KEY, c);
1387
CREATE TABLE cross(d, e, f,
1388
FOREIGN KEY(e) REFERENCES nought(b) ON UPDATE CASCADE
1391
execsql { INSERT INTO nought VALUES(2, 1, 2) }
1392
execsql { INSERT INTO cross VALUES(0, 1, 0) }
1394
execsql { UPDATE nought SET b = 5 }
1396
} {SQLITE_UPDATE nought b main {} SQLITE_READ cross e main {} SQLITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_UPDATE cross e main {} SQLITE_READ nought b main {} SQLITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {}}
1398
do_test fkey2-18.6 {
1399
execsql {SELECT * FROM cross}
1402
do_test fkey2-18.7 {
1404
CREATE TABLE one(a INTEGER PRIMARY KEY, b);
1405
CREATE TABLE two(b, c REFERENCES one);
1406
INSERT INTO one VALUES(101, 102);
1409
execsql { INSERT INTO two VALUES(100, 101); }
1411
} {SQLITE_INSERT two {} main {} SQLITE_READ one a main {}}
1413
# Return SQLITE_IGNORE to requests to read from the parent table. This
1414
# causes inserts of non-NULL keys into the child table to fail.
1418
if {[lindex $args 1] == "long"} {return SQLITE_IGNORE}
1421
do_test fkey2-18.8 {
1422
catchsql { INSERT INTO short VALUES(1, 3, 2) }
1423
} {1 {foreign key constraint failed}}
1424
do_test fkey2-18.9 {
1425
execsql { INSERT INTO short VALUES(1, 3, NULL) }
1427
do_test fkey2-18.10 {
1428
execsql { SELECT * FROM short }
1430
do_test fkey2-18.11 {
1431
catchsql { UPDATE short SET f = 2 WHERE f IS NULL }
1432
} {1 {foreign key constraint failed}}
1438
#-------------------------------------------------------------------------
1439
# The following block of tests, those prefixed with "fkey2-genfkey.", are
1440
# the same tests that were used to test the ".genfkey" command provided
1441
# by the shell tool. So these tests show that the built-in foreign key
1442
# implementation is more or less compatible with the triggers generated
1446
do_test fkey2-genfkey.1.1 {
1448
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
1449
CREATE TABLE t2(e REFERENCES t1, f);
1450
CREATE TABLE t3(g, h, i, FOREIGN KEY (h, i) REFERENCES t1(b, c));
1453
do_test fkey2-genfkey.1.2 {
1454
catchsql { INSERT INTO t2 VALUES(1, 2) }
1455
} {1 {foreign key constraint failed}}
1456
do_test fkey2-genfkey.1.3 {
1458
INSERT INTO t1 VALUES(1, 2, 3);
1459
INSERT INTO t2 VALUES(1, 2);
1462
do_test fkey2-genfkey.1.4 {
1463
execsql { INSERT INTO t2 VALUES(NULL, 3) }
1465
do_test fkey2-genfkey.1.5 {
1466
catchsql { UPDATE t2 SET e = 5 WHERE e IS NULL }
1467
} {1 {foreign key constraint failed}}
1468
do_test fkey2-genfkey.1.6 {
1469
execsql { UPDATE t2 SET e = 1 WHERE e IS NULL }
1471
do_test fkey2-genfkey.1.7 {
1472
execsql { UPDATE t2 SET e = NULL WHERE f = 3 }
1474
do_test fkey2-genfkey.1.8 {
1475
catchsql { UPDATE t1 SET a = 10 }
1476
} {1 {foreign key constraint failed}}
1477
do_test fkey2-genfkey.1.9 {
1478
catchsql { UPDATE t1 SET a = NULL }
1479
} {1 {datatype mismatch}}
1480
do_test fkey2-genfkey.1.10 {
1481
catchsql { DELETE FROM t1 }
1482
} {1 {foreign key constraint failed}}
1483
do_test fkey2-genfkey.1.11 {
1484
execsql { UPDATE t2 SET e = NULL }
1486
do_test fkey2-genfkey.1.12 {
1488
UPDATE t1 SET a = 10;
1493
do_test fkey2-genfkey.1.13 {
1495
INSERT INTO t3 VALUES(1, NULL, NULL);
1496
INSERT INTO t3 VALUES(1, 2, NULL);
1497
INSERT INTO t3 VALUES(1, NULL, 3);
1500
do_test fkey2-genfkey.1.14 {
1501
catchsql { INSERT INTO t3 VALUES(3, 1, 4) }
1502
} {1 {foreign key constraint failed}}
1503
do_test fkey2-genfkey.1.15 {
1505
INSERT INTO t1 VALUES(1, 1, 4);
1506
INSERT INTO t3 VALUES(3, 1, 4);
1509
do_test fkey2-genfkey.1.16 {
1510
catchsql { DELETE FROM t1 }
1511
} {1 {foreign key constraint failed}}
1512
do_test fkey2-genfkey.1.17 {
1513
catchsql { UPDATE t1 SET b = 10}
1514
} {1 {foreign key constraint failed}}
1515
do_test fkey2-genfkey.1.18 {
1516
execsql { UPDATE t1 SET a = 10}
1518
do_test fkey2-genfkey.1.19 {
1519
catchsql { UPDATE t3 SET h = 'hello' WHERE i = 3}
1520
} {1 {foreign key constraint failed}}
1523
do_test fkey2-genfkey.2.1 {
1525
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
1526
CREATE TABLE t2(e REFERENCES t1 ON UPDATE CASCADE ON DELETE CASCADE, f);
1527
CREATE TABLE t3(g, h, i,
1529
REFERENCES t1(b, c) ON UPDATE CASCADE ON DELETE CASCADE
1533
do_test fkey2-genfkey.2.2 {
1535
INSERT INTO t1 VALUES(1, 2, 3);
1536
INSERT INTO t1 VALUES(4, 5, 6);
1537
INSERT INTO t2 VALUES(1, 'one');
1538
INSERT INTO t2 VALUES(4, 'four');
1541
do_test fkey2-genfkey.2.3 {
1543
UPDATE t1 SET a = 2 WHERE a = 1;
1547
do_test fkey2-genfkey.2.4 {
1549
DELETE FROM t1 WHERE a = 4;
1554
do_test fkey2-genfkey.2.5 {
1556
INSERT INTO t3 VALUES('hello', 2, 3);
1557
UPDATE t1 SET c = 2;
1561
do_test fkey2-genfkey.2.6 {
1569
do_test fkey2-genfkey.3.1 {
1571
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(c, b));
1572
CREATE TABLE t2(e REFERENCES t1 ON UPDATE SET NULL ON DELETE SET NULL, f);
1573
CREATE TABLE t3(g, h, i,
1575
REFERENCES t1(b, c) ON UPDATE SET NULL ON DELETE SET NULL
1579
do_test fkey2-genfkey.3.2 {
1581
INSERT INTO t1 VALUES(1, 2, 3);
1582
INSERT INTO t1 VALUES(4, 5, 6);
1583
INSERT INTO t2 VALUES(1, 'one');
1584
INSERT INTO t2 VALUES(4, 'four');
1587
do_test fkey2-genfkey.3.3 {
1589
UPDATE t1 SET a = 2 WHERE a = 1;
1593
do_test fkey2-genfkey.3.4 {
1595
DELETE FROM t1 WHERE a = 4;
1599
do_test fkey2-genfkey.3.5 {
1601
INSERT INTO t3 VALUES('hello', 2, 3);
1602
UPDATE t1 SET c = 2;
1606
do_test fkey2-genfkey.3.6 {
1608
UPDATE t3 SET h = 2, i = 2;