Merge latest trunk changes with this branch.
[sqlite.git] / test / fkey6.test
blobb658f20fea19665ef32cf00ea13ab1c9fa4edbdc
1 # 2012 December 17
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
26 set testprefix fkey6
28 ifcapable {!foreignkey} {
29   finish_test
30   return
33 do_execsql_test fkey6-1.0 {
34   PRAGMA defer_foreign_keys;
35 } {0}
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);
48 } {}
49 do_test fkey6-1.2 {
50   catchsql {DELETE FROM t1 WHERE x=2;}
51 } {1 {FOREIGN KEY constraint failed}}
52 do_test fkey6-1.3 {
53   sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
54 } {0 0 0}
55 do_test fkey6-1.4 {
56   execsql {
57     BEGIN;
58     DELETE FROM t1 WHERE x=1;
59   }
60 } {}
61 do_test fkey6-1.5.1 {
62   sqlite3_db_status db DBSTATUS_DEFERRED_FKS 1
63 } {0 1 0}
64 do_test fkey6-1.5.2 {
65   sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
66 } {0 1 0}
67 do_test fkey6-1.6 {
68   execsql {
69     ROLLBACK;
70   }
71 } {}
72 do_test fkey6-1.7 {
73   sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
74 } {0 0 0}
75 do_test fkey6-1.8 {
76   execsql {
77     PRAGMA defer_foreign_keys=ON;
78     BEGIN;
79     DELETE FROM t1 WHERE x=3;
80   }
81 } {}
82 do_test fkey6-1.9 {
83   sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
84 } {0 1 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
89 # transaction.
90 do_execsql_test fkey6-1.10.1 {
91   PRAGMA defer_foreign_keys;
92   ROLLBACK;
93   PRAGMA defer_foreign_keys;
94   BEGIN;
95   PRAGMA defer_foreign_keys=ON;
96   PRAGMA defer_foreign_keys;
97   COMMIT;
98   PRAGMA defer_foreign_keys;
99   BEGIN;
100 } {1 0 1 0}
101 do_test fkey6-1.10.2 {
102   catchsql {DELETE FROM t1 WHERE x=3}
103 } {1 {FOREIGN KEY constraint failed}}
104 db eval {ROLLBACK}
106 do_test fkey6-1.20 {
107   execsql {
108     BEGIN;
109     DELETE FROM t1 WHERE x=1;
110   }
111   sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
112 } {0 1 0}
113 do_test fkey6-1.21 {
114   execsql {
115     DELETE FROM t2 WHERE y=1;
116   }
117   sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
118 } {0 0 0}
119 do_test fkey6-1.22 {
120   execsql {
121     COMMIT;
122   }
123 } {}
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 {
133   BEGIN;
134     PRAGMA defer_foreign_keys = 1;
135     DELETE FROM p1;
136   ROLLBACK;
137   PRAGMA defer_foreign_keys;
138 } {0}
140 do_execsql_test fkey6-2.3 {
141   BEGIN;
142     PRAGMA defer_foreign_keys = 1;
143     DROP TABLE p1;
144     PRAGMA vdbe_trace = 0;
145   ROLLBACK;
146   PRAGMA defer_foreign_keys;
147 } {0}
149 do_execsql_test fkey6-2.4 {
150   BEGIN;
151     PRAGMA defer_foreign_keys = 1;
152     DELETE FROM p1;
153     DROP TABLE c1;
154   COMMIT;
155   PRAGMA defer_foreign_keys;
156 } {0}
158 do_execsql_test fkey6-2.5 {
159   DROP TABLE p1;
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 {
167   BEGIN;
168     PRAGMA defer_foreign_keys = 1;
169     INSERT INTO c1 VALUES('three');
170     DROP TABLE c1;
171   COMMIT;
172   PRAGMA defer_foreign_keys;
173 } {0}
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 {
187   BEGIN;
188     UPDATE p2 SET a=a-1;
189 } {1 {FOREIGN KEY constraint failed}}
190 do_execsql_test 3.2.2 { COMMIT }
192 do_execsql_test 3.2.3 {
193   BEGIN;
194     PRAGMA defer_foreign_keys = 1;
195     UPDATE p2 SET a=a-1;
196   COMMIT;
199 do_execsql_test 3.2.4 {
200   BEGIN;
201     PRAGMA defer_foreign_keys = 1;
202     UPDATE p2 SET a=a-1;
204 do_catchsql_test 3.2.5 {
205   COMMIT;
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!');
212   END;
214 do_catchsql_test 3.3.2 {
215   BEGIN;
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 {
221   BEGIN;
222     PRAGMA defer_foreign_keys = 1;
223     DELETE FROM p2 WHERE a=1;
224   COMMIT;
225   SELECT * FROM p2;
226 } {0 one 1 deleted!}
229 finish_test