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 tests the PRAGMA defer_foreign_keys and
14 # SQLITE_DBSTATUS_DEFERRED_FKS
16 # EVIDENCE-OF: R-18981-16292 When the defer_foreign_keys PRAGMA is on,
17 # enforcement of all foreign key constraints is delayed until the
18 # outermost transaction is committed.
20 # EVIDENCE-OF: R-28911-57501 The defer_foreign_keys pragma defaults to
21 # OFF so that foreign key constraints are only deferred if they are
22 # created as "DEFERRABLE INITIALLY DEFERRED".
24 set testdir [file dirname $argv0]
25 source $testdir/tester.tcl
28 ifcapable {!foreignkey} {
33 do_execsql_test fkey6-1.0 {
34 PRAGMA defer_foreign_keys;
37 do_execsql_test fkey6-1.1 {
38 PRAGMA foreign_keys=ON;
39 CREATE TABLE t1(x INTEGER PRIMARY KEY);
40 CREATE TABLE t2(y INTEGER PRIMARY KEY,
41 z INTEGER REFERENCES t1(x) DEFERRABLE INITIALLY DEFERRED);
42 CREATE INDEX t2z ON t2(z);
43 CREATE TABLE t3(u INTEGER PRIMARY KEY, v INTEGER REFERENCES t1(x));
44 CREATE INDEX t3v ON t3(v);
45 INSERT INTO t1 VALUES(1),(2),(3),(4),(5);
46 INSERT INTO t2 VALUES(1,1),(2,2);
47 INSERT INTO t3 VALUES(3,3),(4,4);
50 catchsql {DELETE FROM t1 WHERE x=2;}
51 } {1 {FOREIGN KEY constraint failed}}
53 sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
58 DELETE FROM t1 WHERE x=1;
62 sqlite3_db_status db DBSTATUS_DEFERRED_FKS 1
65 sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
73 sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
77 PRAGMA defer_foreign_keys=ON;
79 DELETE FROM t1 WHERE x=3;
83 sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
86 # EVIDENCE-OF: R-21752-26913 The defer_foreign_keys pragma is
87 # automatically switched off at each COMMIT or ROLLBACK. Hence, the
88 # defer_foreign_keys pragma must be separately enabled for each
90 do_execsql_test fkey6-1.10.1 {
91 PRAGMA defer_foreign_keys;
93 PRAGMA defer_foreign_keys;
95 PRAGMA defer_foreign_keys=ON;
96 PRAGMA defer_foreign_keys;
98 PRAGMA defer_foreign_keys;
101 do_test fkey6-1.10.2 {
102 catchsql {DELETE FROM t1 WHERE x=3}
103 } {1 {FOREIGN KEY constraint failed}}
109 DELETE FROM t1 WHERE x=1;
111 sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
115 DELETE FROM t2 WHERE y=1;
117 sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
125 do_execsql_test fkey6-2.1 {
126 CREATE TABLE p1(a PRIMARY KEY);
127 INSERT INTO p1 VALUES('one'), ('two');
128 CREATE TABLE c1(x REFERENCES p1);
129 INSERT INTO c1 VALUES('two'), ('one');
132 do_execsql_test fkey6-2.2 {
134 PRAGMA defer_foreign_keys = 1;
137 PRAGMA defer_foreign_keys;
140 do_execsql_test fkey6-2.3 {
142 PRAGMA defer_foreign_keys = 1;
144 PRAGMA vdbe_trace = 0;
146 PRAGMA defer_foreign_keys;
149 do_execsql_test fkey6-2.4 {
151 PRAGMA defer_foreign_keys = 1;
155 PRAGMA defer_foreign_keys;
158 do_execsql_test fkey6-2.5 {
160 CREATE TABLE p1(a PRIMARY KEY);
161 INSERT INTO p1 VALUES('one'), ('two');
162 CREATE TABLE c1(x REFERENCES p1);
163 INSERT INTO c1 VALUES('two'), ('one');
166 do_execsql_test fkey6-2.6 {
168 PRAGMA defer_foreign_keys = 1;
169 INSERT INTO c1 VALUES('three');
172 PRAGMA defer_foreign_keys;
175 #--------------------------------------------------------------------------
176 # Test that defer_foreign_keys disables RESTRICT.
178 do_execsql_test 3.1 {
179 CREATE TABLE p2(a PRIMARY KEY, b);
180 CREATE TABLE c2(x, y REFERENCES p2 ON DELETE RESTRICT ON UPDATE RESTRICT);
181 INSERT INTO p2 VALUES(1, 'one');
182 INSERT INTO p2 VALUES(2, 'two');
183 INSERT INTO c2 VALUES('i', 1);
186 do_catchsql_test 3.2.1 {
189 } {1 {FOREIGN KEY constraint failed}}
190 do_execsql_test 3.2.2 { COMMIT }
192 do_execsql_test 3.2.3 {
194 PRAGMA defer_foreign_keys = 1;
199 do_execsql_test 3.2.4 {
201 PRAGMA defer_foreign_keys = 1;
204 do_catchsql_test 3.2.5 {
206 } {1 {FOREIGN KEY constraint failed}}
207 do_execsql_test 3.2.6 { ROLLBACK }
209 do_execsql_test 3.3.1 {
210 CREATE TRIGGER p2t AFTER DELETE ON p2 BEGIN
211 INSERT INTO p2 VALUES(old.a, 'deleted!');
214 do_catchsql_test 3.3.2 {
216 DELETE FROM p2 WHERE a=1;
217 } {1 {FOREIGN KEY constraint failed}}
218 do_execsql_test 3.3.3 { COMMIT }
220 do_execsql_test 3.3.4 {
222 PRAGMA defer_foreign_keys = 1;
223 DELETE FROM p2 WHERE a=1;