xref: /sqlite-3.40.0/test/fkey6.test (revision aa9ffaba)
1b1eaa718Sdrh# 2012 December 17
2648e2643Sdrh#
3648e2643Sdrh# The author disclaims copyright to this source code.  In place of
4648e2643Sdrh# a legal notice, here is a blessing:
5648e2643Sdrh#
6648e2643Sdrh#    May you do good and not evil.
7648e2643Sdrh#    May you find forgiveness for yourself and forgive others.
8648e2643Sdrh#    May you share freely, never taking more than you give.
9648e2643Sdrh#
10648e2643Sdrh#***********************************************************************
11648e2643Sdrh# This file implements regression tests for SQLite library.
12648e2643Sdrh#
13648e2643Sdrh# This file tests the PRAGMA defer_foreign_keys and
14648e2643Sdrh# SQLITE_DBSTATUS_DEFERRED_FKS
15648e2643Sdrh#
16e4bf4f08Sdrh# EVIDENCE-OF: R-18981-16292 When the defer_foreign_keys PRAGMA is on,
17e4bf4f08Sdrh# enforcement of all foreign key constraints is delayed until the
18e4bf4f08Sdrh# outermost transaction is committed.
19e4bf4f08Sdrh#
20e4bf4f08Sdrh# EVIDENCE-OF: R-28911-57501 The defer_foreign_keys pragma defaults to
21e4bf4f08Sdrh# OFF so that foreign key constraints are only deferred if they are
22e4bf4f08Sdrh# created as "DEFERRABLE INITIALLY DEFERRED".
23648e2643Sdrh
24648e2643Sdrhset testdir [file dirname $argv0]
25648e2643Sdrhsource $testdir/tester.tcl
26*aa9ffabaSdanset testprefix fkey6
27648e2643Sdrh
28648e2643Sdrhifcapable {!foreignkey} {
29648e2643Sdrh  finish_test
30648e2643Sdrh  return
31648e2643Sdrh}
32648e2643Sdrh
33e4bf4f08Sdrhdo_execsql_test fkey6-1.0 {
34e4bf4f08Sdrh  PRAGMA defer_foreign_keys;
35e4bf4f08Sdrh} {0}
36e4bf4f08Sdrh
37648e2643Sdrhdo_execsql_test fkey6-1.1 {
38648e2643Sdrh  PRAGMA foreign_keys=ON;
39648e2643Sdrh  CREATE TABLE t1(x INTEGER PRIMARY KEY);
40648e2643Sdrh  CREATE TABLE t2(y INTEGER PRIMARY KEY,
41648e2643Sdrh          z INTEGER REFERENCES t1(x) DEFERRABLE INITIALLY DEFERRED);
42648e2643Sdrh  CREATE INDEX t2z ON t2(z);
43648e2643Sdrh  CREATE TABLE t3(u INTEGER PRIMARY KEY, v INTEGER REFERENCES t1(x));
44648e2643Sdrh  CREATE INDEX t3v ON t3(v);
45648e2643Sdrh  INSERT INTO t1 VALUES(1),(2),(3),(4),(5);
46648e2643Sdrh  INSERT INTO t2 VALUES(1,1),(2,2);
47648e2643Sdrh  INSERT INTO t3 VALUES(3,3),(4,4);
48648e2643Sdrh} {}
49648e2643Sdrhdo_test fkey6-1.2 {
50648e2643Sdrh  catchsql {DELETE FROM t1 WHERE x=2;}
51f9c8ce3cSdrh} {1 {FOREIGN KEY constraint failed}}
52648e2643Sdrhdo_test fkey6-1.3 {
53648e2643Sdrh  sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
54648e2643Sdrh} {0 0 0}
55648e2643Sdrhdo_test fkey6-1.4 {
56648e2643Sdrh  execsql {
57648e2643Sdrh    BEGIN;
58648e2643Sdrh    DELETE FROM t1 WHERE x=1;
59648e2643Sdrh  }
60648e2643Sdrh} {}
61648e2643Sdrhdo_test fkey6-1.5.1 {
62648e2643Sdrh  sqlite3_db_status db DBSTATUS_DEFERRED_FKS 1
63648e2643Sdrh} {0 1 0}
64648e2643Sdrhdo_test fkey6-1.5.2 {
65648e2643Sdrh  sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
66648e2643Sdrh} {0 1 0}
67648e2643Sdrhdo_test fkey6-1.6 {
68648e2643Sdrh  execsql {
69648e2643Sdrh    ROLLBACK;
70648e2643Sdrh  }
71648e2643Sdrh} {}
72648e2643Sdrhdo_test fkey6-1.7 {
73648e2643Sdrh  sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
74648e2643Sdrh} {0 0 0}
75648e2643Sdrhdo_test fkey6-1.8 {
76648e2643Sdrh  execsql {
77648e2643Sdrh    PRAGMA defer_foreign_keys=ON;
78648e2643Sdrh    BEGIN;
79648e2643Sdrh    DELETE FROM t1 WHERE x=3;
80648e2643Sdrh  }
81648e2643Sdrh} {}
82648e2643Sdrhdo_test fkey6-1.9 {
83648e2643Sdrh  sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
84648e2643Sdrh} {0 1 0}
855dbb7cc2Sdrh
865dbb7cc2Sdrh# EVIDENCE-OF: R-21752-26913 The defer_foreign_keys pragma is
875dbb7cc2Sdrh# automatically switched off at each COMMIT or ROLLBACK. Hence, the
885dbb7cc2Sdrh# defer_foreign_keys pragma must be separately enabled for each
895dbb7cc2Sdrh# transaction.
905dbb7cc2Sdrhdo_execsql_test fkey6-1.10.1 {
915dbb7cc2Sdrh  PRAGMA defer_foreign_keys;
92648e2643Sdrh  ROLLBACK;
935dbb7cc2Sdrh  PRAGMA defer_foreign_keys;
94648e2643Sdrh  BEGIN;
955dbb7cc2Sdrh  PRAGMA defer_foreign_keys=ON;
965dbb7cc2Sdrh  PRAGMA defer_foreign_keys;
975dbb7cc2Sdrh  COMMIT;
985dbb7cc2Sdrh  PRAGMA defer_foreign_keys;
995dbb7cc2Sdrh  BEGIN;
1005dbb7cc2Sdrh} {1 0 1 0}
1015dbb7cc2Sdrhdo_test fkey6-1.10.2 {
102648e2643Sdrh  catchsql {DELETE FROM t1 WHERE x=3}
103f9c8ce3cSdrh} {1 {FOREIGN KEY constraint failed}}
104648e2643Sdrhdb eval {ROLLBACK}
105648e2643Sdrh
106648e2643Sdrhdo_test fkey6-1.20 {
107648e2643Sdrh  execsql {
108648e2643Sdrh    BEGIN;
109648e2643Sdrh    DELETE FROM t1 WHERE x=1;
110648e2643Sdrh  }
111648e2643Sdrh  sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
112648e2643Sdrh} {0 1 0}
113648e2643Sdrhdo_test fkey6-1.21 {
114648e2643Sdrh  execsql {
115648e2643Sdrh    DELETE FROM t2 WHERE y=1;
116648e2643Sdrh  }
117648e2643Sdrh  sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
118648e2643Sdrh} {0 0 0}
119648e2643Sdrhdo_test fkey6-1.22 {
120648e2643Sdrh  execsql {
121648e2643Sdrh    COMMIT;
122648e2643Sdrh  }
123648e2643Sdrh} {}
124648e2643Sdrh
125a8dbadacSdando_execsql_test fkey6-2.1 {
126a8dbadacSdan  CREATE TABLE p1(a PRIMARY KEY);
127a8dbadacSdan  INSERT INTO p1 VALUES('one'), ('two');
128a8dbadacSdan  CREATE TABLE c1(x REFERENCES p1);
129a8dbadacSdan  INSERT INTO c1 VALUES('two'), ('one');
130a8dbadacSdan}
131a8dbadacSdan
132a8dbadacSdando_execsql_test fkey6-2.2 {
133a8dbadacSdan  BEGIN;
134a8dbadacSdan    PRAGMA defer_foreign_keys = 1;
135a8dbadacSdan    DELETE FROM p1;
136a8dbadacSdan  ROLLBACK;
137a8dbadacSdan  PRAGMA defer_foreign_keys;
138a8dbadacSdan} {0}
139a8dbadacSdan
140a8dbadacSdando_execsql_test fkey6-2.3 {
141a8dbadacSdan  BEGIN;
142a8dbadacSdan    PRAGMA defer_foreign_keys = 1;
143a8dbadacSdan    DROP TABLE p1;
144a8dbadacSdan    PRAGMA vdbe_trace = 0;
145a8dbadacSdan  ROLLBACK;
146a8dbadacSdan  PRAGMA defer_foreign_keys;
147a8dbadacSdan} {0}
148a8dbadacSdan
149a8dbadacSdando_execsql_test fkey6-2.4 {
150a8dbadacSdan  BEGIN;
151a8dbadacSdan    PRAGMA defer_foreign_keys = 1;
152a8dbadacSdan    DELETE FROM p1;
153a8dbadacSdan    DROP TABLE c1;
154a8dbadacSdan  COMMIT;
155a8dbadacSdan  PRAGMA defer_foreign_keys;
156a8dbadacSdan} {0}
157a8dbadacSdan
158a8dbadacSdando_execsql_test fkey6-2.5 {
159a8dbadacSdan  DROP TABLE p1;
160a8dbadacSdan  CREATE TABLE p1(a PRIMARY KEY);
161a8dbadacSdan  INSERT INTO p1 VALUES('one'), ('two');
162a8dbadacSdan  CREATE TABLE c1(x REFERENCES p1);
163a8dbadacSdan  INSERT INTO c1 VALUES('two'), ('one');
164a8dbadacSdan}
165a8dbadacSdan
166a8dbadacSdando_execsql_test fkey6-2.6 {
167a8dbadacSdan  BEGIN;
168a8dbadacSdan    PRAGMA defer_foreign_keys = 1;
169a8dbadacSdan    INSERT INTO c1 VALUES('three');
170a8dbadacSdan    DROP TABLE c1;
171a8dbadacSdan  COMMIT;
172a8dbadacSdan  PRAGMA defer_foreign_keys;
173a8dbadacSdan} {0}
174a8dbadacSdan
175*aa9ffabaSdan#--------------------------------------------------------------------------
176*aa9ffabaSdan# Test that defer_foreign_keys disables RESTRICT.
177*aa9ffabaSdan#
178*aa9ffabaSdando_execsql_test 3.1 {
179*aa9ffabaSdan  CREATE TABLE p2(a PRIMARY KEY, b);
180*aa9ffabaSdan  CREATE TABLE c2(x, y REFERENCES p2 ON DELETE RESTRICT ON UPDATE RESTRICT);
181*aa9ffabaSdan  INSERT INTO p2 VALUES(1, 'one');
182*aa9ffabaSdan  INSERT INTO p2 VALUES(2, 'two');
183*aa9ffabaSdan  INSERT INTO c2 VALUES('i', 1);
184*aa9ffabaSdan}
185*aa9ffabaSdan
186*aa9ffabaSdando_catchsql_test 3.2.1 {
187*aa9ffabaSdan  BEGIN;
188*aa9ffabaSdan    UPDATE p2 SET a=a-1;
189*aa9ffabaSdan} {1 {FOREIGN KEY constraint failed}}
190*aa9ffabaSdando_execsql_test 3.2.2 { COMMIT }
191*aa9ffabaSdan
192*aa9ffabaSdando_execsql_test 3.2.3 {
193*aa9ffabaSdan  BEGIN;
194*aa9ffabaSdan    PRAGMA defer_foreign_keys = 1;
195*aa9ffabaSdan    UPDATE p2 SET a=a-1;
196*aa9ffabaSdan  COMMIT;
197*aa9ffabaSdan}
198*aa9ffabaSdan
199*aa9ffabaSdando_execsql_test 3.2.4 {
200*aa9ffabaSdan  BEGIN;
201*aa9ffabaSdan    PRAGMA defer_foreign_keys = 1;
202*aa9ffabaSdan    UPDATE p2 SET a=a-1;
203*aa9ffabaSdan}
204*aa9ffabaSdando_catchsql_test 3.2.5 {
205*aa9ffabaSdan  COMMIT;
206*aa9ffabaSdan} {1 {FOREIGN KEY constraint failed}}
207*aa9ffabaSdando_execsql_test 3.2.6 { ROLLBACK }
208*aa9ffabaSdan
209*aa9ffabaSdando_execsql_test 3.3.1 {
210*aa9ffabaSdan  CREATE TRIGGER p2t AFTER DELETE ON p2 BEGIN
211*aa9ffabaSdan    INSERT INTO p2 VALUES(old.a, 'deleted!');
212*aa9ffabaSdan  END;
213*aa9ffabaSdan}
214*aa9ffabaSdando_catchsql_test 3.3.2 {
215*aa9ffabaSdan  BEGIN;
216*aa9ffabaSdan    DELETE FROM p2 WHERE a=1;
217*aa9ffabaSdan} {1 {FOREIGN KEY constraint failed}}
218*aa9ffabaSdando_execsql_test 3.3.3 { COMMIT }
219*aa9ffabaSdan
220*aa9ffabaSdando_execsql_test 3.3.4 {
221*aa9ffabaSdan  BEGIN;
222*aa9ffabaSdan    PRAGMA defer_foreign_keys = 1;
223*aa9ffabaSdan    DELETE FROM p2 WHERE a=1;
224*aa9ffabaSdan  COMMIT;
225*aa9ffabaSdan  SELECT * FROM p2;
226*aa9ffabaSdan} {0 one 1 deleted!}
227*aa9ffabaSdan
228648e2643Sdrh
229648e2643Sdrhfinish_test
230