xref: /sqlite-3.40.0/test/fkey8.test (revision b1929708)
104668833Sdan# 2001 September 15
204668833Sdan#
304668833Sdan# The author disclaims copyright to this source code.  In place of
404668833Sdan# a legal notice, here is a blessing:
504668833Sdan#
604668833Sdan#    May you do good and not evil.
704668833Sdan#    May you find forgiveness for yourself and forgive others.
804668833Sdan#    May you share freely, never taking more than you give.
904668833Sdan#
1004668833Sdan#***********************************************************************
1104668833Sdan# This file implements regression tests for SQLite library.
1204668833Sdan#
1304668833Sdan# This file implements tests for foreign keys.
1404668833Sdan#
1504668833Sdan
1604668833Sdanset testdir [file dirname $argv0]
1704668833Sdansource $testdir/tester.tcl
1804668833Sdanset testprefix fkey8
1904668833Sdan
2004668833Sdanifcapable {!foreignkey} {
2104668833Sdan  finish_test
2204668833Sdan  return
2304668833Sdan}
2404668833Sdando_execsql_test 1.0 { PRAGMA foreign_keys = 1; }
2504668833Sdan
2604668833Sdan
2704668833Sdanforeach {tn use_stmt sql schema} {
2804668833Sdan  1   1 "DELETE FROM p1" {
2904668833Sdan    CREATE TABLE p1(a PRIMARY KEY);
3004668833Sdan    CREATE TABLE c1(b REFERENCES p1);
3104668833Sdan  }
3204668833Sdan
3304668833Sdan  2.1     0 "DELETE FROM p1" {
3404668833Sdan    CREATE TABLE p1(a PRIMARY KEY);
3504668833Sdan    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE);
3604668833Sdan  }
3704668833Sdan  2.2   0 "DELETE FROM p1" {
3804668833Sdan    CREATE TABLE p1(a PRIMARY KEY);
3904668833Sdan    CREATE TABLE c1(b REFERENCES p1 ON DELETE SET NULL);
4004668833Sdan  }
4104668833Sdan  2.3   1 "DELETE FROM p1" {
4204668833Sdan    CREATE TABLE p1(a PRIMARY KEY);
4304668833Sdan    CREATE TABLE c1(b REFERENCES p1 ON DELETE SET DEFAULT);
4404668833Sdan  }
4504668833Sdan
4604668833Sdan  3   1 "DELETE FROM p1" {
4704668833Sdan    CREATE TABLE p1(a PRIMARY KEY);
4804668833Sdan    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE);
4904668833Sdan    CREATE TRIGGER ct1 AFTER DELETE ON c1 BEGIN
5004668833Sdan      INSERT INTO p1 VALUES('x');
5104668833Sdan    END;
5204668833Sdan  }
5304668833Sdan
5404668833Sdan  4   1 "DELETE FROM p1" {
5504668833Sdan    CREATE TABLE p1(a PRIMARY KEY);
5604668833Sdan    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
5704668833Sdan    CREATE TABLE cc1(d REFERENCES c1);
5804668833Sdan  }
5904668833Sdan
6004668833Sdan  5.1   0 "DELETE FROM p1" {
6104668833Sdan    CREATE TABLE p1(a PRIMARY KEY);
6204668833Sdan    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
6304668833Sdan    CREATE TABLE cc1(d REFERENCES c1 ON DELETE CASCADE);
6404668833Sdan  }
6504668833Sdan  5.2   0 "DELETE FROM p1" {
6604668833Sdan    CREATE TABLE p1(a PRIMARY KEY);
6704668833Sdan    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
6804668833Sdan    CREATE TABLE cc1(d REFERENCES c1 ON DELETE SET NULL);
6904668833Sdan  }
70d4572711Sdan  5.3   1 "DELETE FROM p1" {
71d4572711Sdan    CREATE TABLE p1(a PRIMARY KEY);
72d4572711Sdan    CREATE TABLE c1(b REFERENCES p1 ON DELETE CASCADE, c PRIMARY KEY);
73d4572711Sdan    CREATE TABLE cc1(d REFERENCES c1 ON DELETE SET DEFAULT);
74d4572711Sdan  }
75d4572711Sdan
76d4572711Sdan  6.1   1 "UPDATE p1 SET a = ?" {
77d4572711Sdan    CREATE TABLE p1(a PRIMARY KEY);
78d4572711Sdan    CREATE TABLE c1(b REFERENCES p1 ON UPDATE SET NULL, c);
79d4572711Sdan  }
80d4572711Sdan  6.2   0 "UPDATE OR IGNORE p1 SET a = ?" {
81d4572711Sdan    CREATE TABLE p1(a PRIMARY KEY);
82d4572711Sdan    CREATE TABLE c1(b REFERENCES p1 ON UPDATE SET NULL, c);
83d4572711Sdan  }
84d4572711Sdan  6.3   1 "UPDATE OR IGNORE p1 SET a = ?" {
85d4572711Sdan    CREATE TABLE p1(a PRIMARY KEY);
86d4572711Sdan    CREATE TABLE c1(b REFERENCES p1 ON UPDATE CASCADE, c);
87d4572711Sdan  }
88d4572711Sdan  6.4   1 "UPDATE OR IGNORE p1 SET a = ?" {
89d4572711Sdan    CREATE TABLE p1(a PRIMARY KEY);
90d4572711Sdan    CREATE TABLE c1(b NOT NULL REFERENCES p1 ON UPDATE SET NULL, c);
91d4572711Sdan  }
9204668833Sdan
9304668833Sdan} {
9404668833Sdan  drop_all_tables
9504668833Sdan  do_test 1.$tn {
9604668833Sdan    execsql $schema
9704668833Sdan    set stmt [sqlite3_prepare_v2 db $sql -1 dummy]
9804668833Sdan    set ret [uses_stmt_journal $stmt]
9904668833Sdan    sqlite3_finalize $stmt
10004668833Sdan    set ret
10104668833Sdan  } $use_stmt
10204668833Sdan}
10304668833Sdan
104f9a12a10Sdan#-------------------------------------------------------------------------
105f9a12a10Sdan# The following tests check that foreign key constaint counters are
106f9a12a10Sdan# correctly updated for any implicit DELETE operations that occur
107f9a12a10Sdan# when a REPLACE command is executed against a WITHOUT ROWID table
108f9a12a10Sdan# that has no triggers or auxiliary indexes.
109f9a12a10Sdan#
110f9a12a10Sdanreset_db
111f9a12a10Sdando_execsql_test 2.1.0 {
112f9a12a10Sdan  PRAGMA foreign_keys = on;
113f9a12a10Sdan  CREATE TABLE p1(a PRIMARY KEY, b) WITHOUT ROWID;
114f9a12a10Sdan  CREATE TABLE c1(x REFERENCES p1 DEFERRABLE INITIALLY DEFERRED);
115f9a12a10Sdan
116f9a12a10Sdan  INSERT INTO p1 VALUES(1, 'one');
117f9a12a10Sdan  INSERT INTO p1 VALUES(2, 'two');
118f9a12a10Sdan  INSERT INTO c1 VALUES(1);
119f9a12a10Sdan  INSERT INTO c1 VALUES(2);
120f9a12a10Sdan}
121f9a12a10Sdan
122f9a12a10Sdando_catchsql_test 2.1.2 {
123f9a12a10Sdan  BEGIN;
124f9a12a10Sdan    DELETE FROM p1 WHERE a=1;
125f9a12a10Sdan    INSERT OR REPLACE INTO p1 VALUES(2, 'two');
126f9a12a10Sdan  COMMIT;
127f9a12a10Sdan} {1 {FOREIGN KEY constraint failed}}
128f9a12a10Sdan
129f9a12a10Sdanreset_db
130f9a12a10Sdando_execsql_test 2.2.0 {
131f9a12a10Sdan  PRAGMA foreign_keys = on;
132f9a12a10Sdan  CREATE TABLE p2(a PRIMARY KEY, b);
133f9a12a10Sdan  CREATE TABLE c2(
134f9a12a10Sdan    x PRIMARY KEY,
135f9a12a10Sdan    y REFERENCES p2 DEFERRABLE INITIALLY DEFERRED
136f9a12a10Sdan  ) WITHOUT ROWID;
137f9a12a10Sdan}
138f9a12a10Sdan
139f9a12a10Sdando_catchsql_test 2.2.1 {
140f9a12a10Sdan  BEGIN;
141f9a12a10Sdan    INSERT INTO c2 VALUES(13, 13);
142f9a12a10Sdan    INSERT OR REPLACE INTO c2 VALUES(13, 13);
143f9a12a10Sdan    DELETE FROM c2;
144f9a12a10Sdan  COMMIT;
145f9a12a10Sdan} {0 {}}
146f9a12a10Sdan
147f9a12a10Sdanreset_db
148f9a12a10Sdando_execsql_test 2.3.0 {
149f9a12a10Sdan  PRAGMA foreign_keys = on;
150f9a12a10Sdan  CREATE TABLE p3(a PRIMARY KEY, b) WITHOUT ROWID;
151f9a12a10Sdan  CREATE TABLE c3(x REFERENCES p3);
152f9a12a10Sdan
153f9a12a10Sdan  INSERT INTO p3 VALUES(1, 'one');
154f9a12a10Sdan  INSERT INTO p3 VALUES(2, 'two');
155f9a12a10Sdan  INSERT INTO c3 VALUES(1);
156f9a12a10Sdan  INSERT INTO c3 VALUES(2);
157f9a12a10Sdan
158f9a12a10Sdan  CREATE TRIGGER p3d AFTER DELETE ON p3 WHEN old.a=1 BEGIN
159f9a12a10Sdan    INSERT OR REPLACE INTO p3 VALUES(2, 'three');
160f9a12a10Sdan  END;
161f9a12a10Sdan}
162f9a12a10Sdan
163f9a12a10Sdando_catchsql_test 2.3.1 {
164f9a12a10Sdan  DELETE FROM p3 WHERE a=1
165f9a12a10Sdan} {1 {FOREIGN KEY constraint failed}}
16604668833Sdan
167e46201e2Sdan
168e46201e2Sdando_execsql_test 3.0 {
169e46201e2Sdan  PRAGMA foreign_keys=ON;
170e46201e2Sdan  CREATE TABLE t2(
171e46201e2Sdan    a PRIMARY KEY, b, c, d, e,
172e46201e2Sdan      FOREIGN KEY(b, c) REFERENCES t2(d, e)
173e46201e2Sdan  ) WITHOUT ROWID;
174e46201e2Sdan  CREATE UNIQUE INDEX idx ON t2(d, e);
175e46201e2Sdan
176e46201e2Sdan  INSERT INTO t2 VALUES(1, 'one', 'one', 'one', 'one'); -- row is parent of self
177e46201e2Sdan  INSERT INTO t2 VALUES(2, 'one', 'one', 'one', NULL);  -- parent is row 1
178e46201e2Sdan}
179e46201e2Sdan
180e46201e2Sdando_catchsql_test 3.1 {
181e46201e2Sdan  DELETE FROM t2 WHERE a=1;
182e46201e2Sdan} {1 {FOREIGN KEY constraint failed}}
183e46201e2Sdan
184e46201e2Sdando_execsql_test 4.0 {
185e46201e2Sdan  CREATE TABLE t1 (
186e46201e2Sdan      c1 PRIMARY KEY,
187e46201e2Sdan      c2 NUMERIC,
188e46201e2Sdan      FOREIGN KEY(c1) REFERENCES t1(c2)
189e46201e2Sdan      ) WITHOUT ROWID ;
190e46201e2Sdan  CREATE INDEX t1c1 ON t1(c1);
191e46201e2Sdan  CREATE UNIQUE INDEX t1c1unique ON t1(c2);
192e46201e2Sdan}
193e46201e2Sdando_catchsql_test 4.1 {
194e46201e2Sdan  INSERT OR REPLACE INTO t1 VALUES(10000, 20000);
195e46201e2Sdan} {1 {FOREIGN KEY constraint failed}}
196e46201e2Sdando_execsql_test 4.2 {
197e46201e2Sdan  INSERT OR REPLACE INTO t1 VALUES(20000, 20000);
198e46201e2Sdan}
199e46201e2Sdan
200244edd01Sdan#-------------------------------------------------------------------------
201244edd01Sdanreset_db
202244edd01Sdando_execsql_test 5.0 {
203244edd01Sdan  PRAGMA foreign_keys = true;
204244edd01Sdan  CREATE TABLE parent(
205244edd01Sdan    p TEXT PRIMARY KEY
206244edd01Sdan  );
207244edd01Sdan  CREATE TABLE child(
208244edd01Sdan    c INTEGER UNIQUE,
209244edd01Sdan    FOREIGN KEY(c) REFERENCES parent(p) DEFERRABLE INITIALLY DEFERRED
210244edd01Sdan  );
211244edd01Sdan  BEGIN;
212244edd01Sdan    INSERT INTO child VALUES(123);
213244edd01Sdan    INSERT INTO parent VALUES('123');
214244edd01Sdan  COMMIT;
215244edd01Sdan}
216244edd01Sdando_execsql_test 5.1 {
217244edd01Sdan  PRAGMA integrity_check;
218244edd01Sdan} {ok}
219244edd01Sdan
220244edd01Sdando_execsql_test 5.2 {
221244edd01Sdan  INSERT INTO parent VALUES(1200);
222244edd01Sdan  BEGIN;
223244edd01Sdan    INSERT INTO child VALUES(456);
224244edd01Sdan    UPDATE parent SET p = '456' WHERE p=1200;
225244edd01Sdan  COMMIT;
226244edd01Sdan}
227244edd01Sdando_execsql_test 5.3 {
228244edd01Sdan  PRAGMA integrity_check;
229244edd01Sdan} {ok}
230244edd01Sdan
231*b1929708Sdan#-------------------------------------------------------------------------
232*b1929708Sdanreset_db
233*b1929708Sdanforcedelete test.db2
234*b1929708Sdando_execsql_test 6.1 {
235*b1929708Sdan  PRAGMA foreign_keys = on;
236*b1929708Sdan  CREATE TABLE c1(b);
237*b1929708Sdan  INSERT INTO c1 VALUES(123);
238*b1929708Sdan}
239*b1929708Sdan
240*b1929708Sdando_execsql_test 6.2 {
241*b1929708Sdan  ATTACH 'test.db2' AS aux;
242*b1929708Sdan  CREATE TABLE aux.p1(a INTEGER PRIMARY KEY);
243*b1929708Sdan  CREATE TABLE aux.c1(b REFERENCES p1(a) ON DELETE RESTRICT);
244*b1929708Sdan
245*b1929708Sdan  INSERT INTO aux.p1 VALUES(123);
246*b1929708Sdan}
247*b1929708Sdan
248*b1929708Sdando_execsql_test 6.3 {
249*b1929708Sdan  DELETE FROM aux.p1 WHERE a=123;
250*b1929708Sdan}
251*b1929708Sdan
252*b1929708Sdan
25304668833Sdanfinish_test
254