OLD | NEW |
| (Empty) |
1 # 2013-11-02 | |
2 # | |
3 # The author disclaims copyright to this source code. In place of | |
4 # a legal notice, here is a blessing: | |
5 # | |
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. | |
9 # | |
10 #*********************************************************************** | |
11 # This file implements regression tests for SQLite library. | |
12 # | |
13 # This file implements tests for foreign keys on WITHOUT ROWID | |
14 # tables. | |
15 # | |
16 | |
17 set testdir [file dirname $argv0] | |
18 source $testdir/tester.tcl | |
19 | |
20 ifcapable {!foreignkey||!trigger} { | |
21 finish_test | |
22 return | |
23 } | |
24 | |
25 #------------------------------------------------------------------------- | |
26 # Test structure: | |
27 # | |
28 # without_rowid3-1.*: Simple tests to check that immediate and deferred foreign
key | |
29 # constraints work when not inside a transaction. | |
30 # | |
31 # without_rowid3-2.*: Tests to verify that deferred foreign keys work inside | |
32 # explicit transactions (i.e that processing really is deferred). | |
33 # | |
34 # without_rowid3-3.*: Tests that a statement transaction is rolled back if an | |
35 # immediate foreign key constraint is violated. | |
36 # | |
37 # without_rowid3-4.*: Test that FK actions may recurse even when recursive trigg
ers | |
38 # are disabled. | |
39 # | |
40 # without_rowid3-5.*: Check that if foreign-keys are enabled, it is not possible | |
41 # to write to an FK column using the incremental blob API. | |
42 # | |
43 # without_rowid3-6.*: Test that FK processing is automatically disabled when | |
44 # running VACUUM. | |
45 # | |
46 # without_rowid3-7.*: Test using an IPK as the key in the child (referencing) ta
ble. | |
47 # | |
48 # without_rowid3-8.*: Test that enabling/disabling foreign key support while a | |
49 # transaction is active is not possible. | |
50 # | |
51 # without_rowid3-9.*: Test SET DEFAULT actions. | |
52 # | |
53 # without_rowid3-10.*: Test errors. | |
54 # | |
55 # without_rowid3-11.*: Test CASCADE actions. | |
56 # | |
57 # without_rowid3-12.*: Test RESTRICT actions. | |
58 # | |
59 # without_rowid3-13.*: Test that FK processing is performed when a row is REPLAC
ED by | |
60 # an UPDATE or INSERT statement. | |
61 # | |
62 # without_rowid3-14.*: Test the ALTER TABLE and DROP TABLE commands. | |
63 # | |
64 # without_rowid3-15.*: Test that if there are no (known) outstanding foreign key
| |
65 # constraint violations in the database, inserting into a parent | |
66 # table or deleting from a child table does not cause SQLite | |
67 # to check if this has repaired an outstanding violation. | |
68 # | |
69 # without_rowid3-16.*: Test that rows that refer to themselves may be inserted, | |
70 # updated and deleted. | |
71 # | |
72 # without_rowid3-17.*: Test that the "count_changes" pragma does not interfere w
ith | |
73 # FK constraint processing. | |
74 # | |
75 # without_rowid3-18.*: Test that the authorization callback is invoked when proc
essing | |
76 # FK constraints. | |
77 # | |
78 # without_rowid3-20.*: Test that ON CONFLICT clauses specified as part of statem
ents | |
79 # do not affect the operation of FK constraints. | |
80 # | |
81 # without_rowid3-genfkey.*: Tests that were used with the shell tool .genfkey | |
82 # command. Recycled to test the built-in implementation. | |
83 # | |
84 # without_rowid3-dd08e5.*: Tests to verify that ticket dd08e5a988d00decc4a543da
a8d | |
85 # has been fixed. | |
86 # | |
87 | |
88 | |
89 execsql { PRAGMA foreign_keys = on } | |
90 | |
91 set FkeySimpleSchema { | |
92 PRAGMA foreign_keys = on; | |
93 CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT rowid; | |
94 CREATE TABLE t2(c REFERENCES t1(a) /D/ , d); | |
95 | |
96 CREATE TABLE t3(a PRIMARY KEY, b) WITHOUT rowid; | |
97 CREATE TABLE t4(c REFERENCES t3 /D/, d); | |
98 | |
99 CREATE TABLE t7(a, b INT PRIMARY KEY) WITHOUT rowid; | |
100 CREATE TABLE t8(c REFERENCES t7 /D/, d); | |
101 | |
102 CREATE TABLE t9(a REFERENCES nosuchtable, b); | |
103 CREATE TABLE t10(a REFERENCES t9(c) /D/, b); | |
104 } | |
105 | |
106 | |
107 set FkeySimpleTests { | |
108 1.1 "INSERT INTO t2 VALUES(1, 3)" {1 {FOREIGN KEY constraint failed}} | |
109 1.2 "INSERT INTO t1 VALUES(1, 2)" {0 {}} | |
110 1.3 "INSERT INTO t2 VALUES(1, 3)" {0 {}} | |
111 1.4 "INSERT INTO t2 VALUES(2, 4)" {1 {FOREIGN KEY constraint failed}} | |
112 1.5 "INSERT INTO t2 VALUES(NULL, 4)" {0 {}} | |
113 1.6 "UPDATE t2 SET c=2 WHERE d=4" {1 {FOREIGN KEY constraint failed}} | |
114 1.7 "UPDATE t2 SET c=1 WHERE d=4" {0 {}} | |
115 1.9 "UPDATE t2 SET c=1 WHERE d=4" {0 {}} | |
116 1.10 "UPDATE t2 SET c=NULL WHERE d=4" {0 {}} | |
117 1.11 "DELETE FROM t1 WHERE a=1" {1 {FOREIGN KEY constraint failed}} | |
118 1.12 "UPDATE t1 SET a = 2" {1 {FOREIGN KEY constraint failed}} | |
119 1.13 "UPDATE t1 SET a = 1" {0 {}} | |
120 | |
121 2.1 "INSERT INTO t4 VALUES(1, 3)" {1 {FOREIGN KEY constraint failed}} | |
122 2.2 "INSERT INTO t3 VALUES(1, 2)" {0 {}} | |
123 2.3 "INSERT INTO t4 VALUES(1, 3)" {0 {}} | |
124 | |
125 4.1 "INSERT INTO t8 VALUES(1, 3)" {1 {FOREIGN KEY constraint failed}} | |
126 4.2 "INSERT INTO t7 VALUES(2, 1)" {0 {}} | |
127 4.3 "INSERT INTO t8 VALUES(1, 3)" {0 {}} | |
128 4.4 "INSERT INTO t8 VALUES(2, 4)" {1 {FOREIGN KEY constraint failed}} | |
129 4.5 "INSERT INTO t8 VALUES(NULL, 4)" {0 {}} | |
130 4.6 "UPDATE t8 SET c=2 WHERE d=4" {1 {FOREIGN KEY constraint failed}} | |
131 4.7 "UPDATE t8 SET c=1 WHERE d=4" {0 {}} | |
132 4.9 "UPDATE t8 SET c=1 WHERE d=4" {0 {}} | |
133 4.10 "UPDATE t8 SET c=NULL WHERE d=4" {0 {}} | |
134 4.11 "DELETE FROM t7 WHERE b=1" {1 {FOREIGN KEY constraint failed}} | |
135 4.12 "UPDATE t7 SET b = 2" {1 {FOREIGN KEY constraint failed}} | |
136 4.13 "UPDATE t7 SET b = 1" {0 {}} | |
137 4.14 "INSERT INTO t8 VALUES('a', 'b')" {1 {FOREIGN KEY constraint failed}} | |
138 4.15 "UPDATE t7 SET b = 5" {1 {FOREIGN KEY constraint failed}} | |
139 4.17 "UPDATE t7 SET a = 10" {0 {}} | |
140 | |
141 5.1 "INSERT INTO t9 VALUES(1, 3)" {1 {no such table: main.nosuchtable}} | |
142 5.2 "INSERT INTO t10 VALUES(1, 3)" | |
143 {1 {foreign key mismatch - "t10" referencing "t9"}} | |
144 } | |
145 | |
146 do_test without_rowid3-1.1.0 { | |
147 execsql [string map {/D/ {}} $FkeySimpleSchema] | |
148 } {} | |
149 foreach {tn zSql res} $FkeySimpleTests { | |
150 do_test without_rowid3-1.1.$tn.1 { catchsql $zSql } $res | |
151 do_test without_rowid3-1.1.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {} | |
152 do_test without_rowid3-1.1.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {} | |
153 do_test without_rowid3-1.1.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {} | |
154 do_test without_rowid3-1.1.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {} | |
155 do_test without_rowid3-1.1.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {} | |
156 do_test without_rowid3-1.1.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {} | |
157 } | |
158 drop_all_tables | |
159 | |
160 do_test without_rowid3-1.2.0 { | |
161 execsql [string map {/D/ {DEFERRABLE INITIALLY DEFERRED}} $FkeySimpleSchema] | |
162 } {} | |
163 foreach {tn zSql res} $FkeySimpleTests { | |
164 do_test without_rowid3-1.2.$tn { catchsql $zSql } $res | |
165 do_test without_rowid3-1.2.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {} | |
166 do_test without_rowid3-1.2.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {} | |
167 do_test without_rowid3-1.2.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {} | |
168 do_test without_rowid3-1.2.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {} | |
169 do_test without_rowid3-1.2.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {} | |
170 do_test without_rowid3-1.2.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {} | |
171 } | |
172 drop_all_tables | |
173 | |
174 do_test without_rowid3-1.3.0 { | |
175 execsql [string map {/D/ {}} $FkeySimpleSchema] | |
176 execsql { PRAGMA count_changes = 1 } | |
177 } {} | |
178 foreach {tn zSql res} $FkeySimpleTests { | |
179 if {$res == "0 {}"} { set res {0 1} } | |
180 do_test without_rowid3-1.3.$tn { catchsql $zSql } $res | |
181 do_test without_rowid3-1.3.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {} | |
182 do_test without_rowid3-1.3.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {} | |
183 do_test without_rowid3-1.3.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {} | |
184 do_test without_rowid3-1.3.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {} | |
185 do_test without_rowid3-1.3.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {} | |
186 do_test without_rowid3-1.3.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {} | |
187 } | |
188 execsql { PRAGMA count_changes = 0 } | |
189 drop_all_tables | |
190 | |
191 do_test without_rowid3-1.4.0 { | |
192 execsql [string map {/D/ {}} $FkeySimpleSchema] | |
193 execsql { PRAGMA count_changes = 1 } | |
194 } {} | |
195 foreach {tn zSql res} $FkeySimpleTests { | |
196 if {$res == "0 {}"} { set res {0 1} } | |
197 execsql BEGIN | |
198 do_test without_rowid3-1.4.$tn { catchsql $zSql } $res | |
199 execsql COMMIT | |
200 } | |
201 execsql { PRAGMA count_changes = 0 } | |
202 drop_all_tables | |
203 | |
204 # Special test: When the parent key is an IPK, make sure the affinity of | |
205 # the IPK is not applied to the child key value before it is inserted | |
206 # into the child table. | |
207 do_test without_rowid3-1.5.1 { | |
208 execsql { | |
209 CREATE TABLE i(i INT PRIMARY KEY) WITHOUT rowid; | |
210 CREATE TABLE j(j REFERENCES i); | |
211 INSERT INTO i VALUES(35); | |
212 INSERT INTO j VALUES('35.0'); | |
213 SELECT j, typeof(j) FROM j; | |
214 } | |
215 } {35.0 text} | |
216 do_test without_rowid3-1.5.2 { | |
217 catchsql { DELETE FROM i } | |
218 } {1 {FOREIGN KEY constraint failed}} | |
219 | |
220 # Same test using a regular primary key with integer affinity. | |
221 drop_all_tables | |
222 do_test without_rowid3-1.6.1 { | |
223 execsql { | |
224 CREATE TABLE i(i INT UNIQUE); | |
225 CREATE TABLE j(j REFERENCES i(i)); | |
226 INSERT INTO i VALUES('35.0'); | |
227 INSERT INTO j VALUES('35.0'); | |
228 SELECT j, typeof(j) FROM j; | |
229 SELECT i, typeof(i) FROM i; | |
230 } | |
231 } {35.0 text 35 integer} | |
232 do_test without_rowid3-1.6.2 { | |
233 catchsql { DELETE FROM i } | |
234 } {1 {FOREIGN KEY constraint failed}} | |
235 | |
236 # Use a collation sequence on the parent key. | |
237 drop_all_tables | |
238 do_test without_rowid3-1.7.1 { | |
239 execsql { | |
240 CREATE TABLE i(i TEXT COLLATE nocase PRIMARY KEY) WITHOUT rowid; | |
241 CREATE TABLE j(j TEXT COLLATE binary REFERENCES i(i)); | |
242 INSERT INTO i VALUES('SQLite'); | |
243 INSERT INTO j VALUES('sqlite'); | |
244 } | |
245 catchsql { DELETE FROM i } | |
246 } {1 {FOREIGN KEY constraint failed}} | |
247 | |
248 # Use the parent key collation even if it is default and the child key | |
249 # has an explicit value. | |
250 drop_all_tables | |
251 do_test without_rowid3-1.7.2 { | |
252 execsql { | |
253 CREATE TABLE i(i TEXT PRIMARY KEY) WITHOUT rowid; -- Colseq is "BINARY" | |
254 CREATE TABLE j(j TEXT COLLATE nocase REFERENCES i(i)); | |
255 INSERT INTO i VALUES('SQLite'); | |
256 } | |
257 catchsql { INSERT INTO j VALUES('sqlite') } | |
258 } {1 {FOREIGN KEY constraint failed}} | |
259 do_test without_rowid3-1.7.3 { | |
260 execsql { | |
261 INSERT INTO i VALUES('sqlite'); | |
262 INSERT INTO j VALUES('sqlite'); | |
263 DELETE FROM i WHERE i = 'SQLite'; | |
264 } | |
265 catchsql { DELETE FROM i WHERE i = 'sqlite' } | |
266 } {1 {FOREIGN KEY constraint failed}} | |
267 | |
268 #------------------------------------------------------------------------- | |
269 # This section (test cases without_rowid3-2.*) contains tests to check that the | |
270 # deferred foreign key constraint logic works. | |
271 # | |
272 proc without_rowid3-2-test {tn nocommit sql {res {}}} { | |
273 if {$res eq "FKV"} { | |
274 set expected {1 {FOREIGN KEY constraint failed}} | |
275 } else { | |
276 set expected [list 0 $res] | |
277 } | |
278 do_test without_rowid3-2.$tn [list catchsql $sql] $expected | |
279 if {$nocommit} { | |
280 do_test without_rowid3-2.${tn}c { | |
281 catchsql COMMIT | |
282 } {1 {FOREIGN KEY constraint failed}} | |
283 } | |
284 } | |
285 | |
286 without_rowid3-2-test 1 0 { | |
287 CREATE TABLE node( | |
288 nodeid PRIMARY KEY, | |
289 parent REFERENCES node DEFERRABLE INITIALLY DEFERRED | |
290 ) WITHOUT rowid; | |
291 CREATE TABLE leaf( | |
292 cellid PRIMARY KEY, | |
293 parent REFERENCES node DEFERRABLE INITIALLY DEFERRED | |
294 ) WITHOUT rowid; | |
295 } | |
296 | |
297 without_rowid3-2-test 1 0 "INSERT INTO node VALUES(1, 0)" FKV | |
298 without_rowid3-2-test 2 0 "BEGIN" | |
299 without_rowid3-2-test 3 1 "INSERT INTO node VALUES(1, 0)" | |
300 without_rowid3-2-test 4 0 "UPDATE node SET parent = NULL" | |
301 without_rowid3-2-test 5 0 "COMMIT" | |
302 without_rowid3-2-test 6 0 "SELECT * FROM node" {1 {}} | |
303 | |
304 without_rowid3-2-test 7 0 "BEGIN" | |
305 without_rowid3-2-test 8 1 "INSERT INTO leaf VALUES('a', 2)" | |
306 without_rowid3-2-test 9 1 "INSERT INTO node VALUES(2, 0)" | |
307 without_rowid3-2-test 10 0 "UPDATE node SET parent = 1 WHERE nodeid = 2" | |
308 without_rowid3-2-test 11 0 "COMMIT" | |
309 without_rowid3-2-test 12 0 "SELECT * FROM node" {1 {} 2 1} | |
310 without_rowid3-2-test 13 0 "SELECT * FROM leaf" {a 2} | |
311 | |
312 without_rowid3-2-test 14 0 "BEGIN" | |
313 without_rowid3-2-test 15 1 "DELETE FROM node WHERE nodeid = 2" | |
314 without_rowid3-2-test 16 0 "INSERT INTO node VALUES(2, NULL)" | |
315 without_rowid3-2-test 17 0 "COMMIT" | |
316 without_rowid3-2-test 18 0 "SELECT * FROM node" {1 {} 2 {}} | |
317 without_rowid3-2-test 19 0 "SELECT * FROM leaf" {a 2} | |
318 | |
319 without_rowid3-2-test 20 0 "BEGIN" | |
320 without_rowid3-2-test 21 0 "INSERT INTO leaf VALUES('b', 1)" | |
321 without_rowid3-2-test 22 0 "SAVEPOINT save" | |
322 without_rowid3-2-test 23 0 "DELETE FROM node WHERE nodeid = 1" | |
323 without_rowid3-2-test 24 0 "ROLLBACK TO save" | |
324 without_rowid3-2-test 25 0 "COMMIT" | |
325 without_rowid3-2-test 26 0 "SELECT * FROM node" {1 {} 2 {}} | |
326 without_rowid3-2-test 27 0 "SELECT * FROM leaf" {a 2 b 1} | |
327 | |
328 without_rowid3-2-test 28 0 "BEGIN" | |
329 without_rowid3-2-test 29 0 "INSERT INTO leaf VALUES('c', 1)" | |
330 without_rowid3-2-test 30 0 "SAVEPOINT save" | |
331 without_rowid3-2-test 31 0 "DELETE FROM node WHERE nodeid = 1" | |
332 without_rowid3-2-test 32 1 "RELEASE save" | |
333 without_rowid3-2-test 33 1 "DELETE FROM leaf WHERE cellid = 'b'" | |
334 without_rowid3-2-test 34 0 "DELETE FROM leaf WHERE cellid = 'c'" | |
335 without_rowid3-2-test 35 0 "COMMIT" | |
336 without_rowid3-2-test 36 0 "SELECT * FROM node" {2 {}} | |
337 without_rowid3-2-test 37 0 "SELECT * FROM leaf" {a 2} | |
338 | |
339 without_rowid3-2-test 38 0 "SAVEPOINT outer" | |
340 without_rowid3-2-test 39 1 "INSERT INTO leaf VALUES('d', 3)" | |
341 without_rowid3-2-test 40 1 "RELEASE outer" FKV | |
342 without_rowid3-2-test 41 1 "INSERT INTO leaf VALUES('e', 3)" | |
343 without_rowid3-2-test 42 0 "INSERT INTO node VALUES(3, 2)" | |
344 without_rowid3-2-test 43 0 "RELEASE outer" | |
345 | |
346 without_rowid3-2-test 44 0 "SAVEPOINT outer" | |
347 without_rowid3-2-test 45 1 "DELETE FROM node WHERE nodeid=3" | |
348 without_rowid3-2-test 47 0 "INSERT INTO node VALUES(3, 2)" | |
349 without_rowid3-2-test 48 0 "ROLLBACK TO outer" | |
350 without_rowid3-2-test 49 0 "RELEASE outer" | |
351 | |
352 without_rowid3-2-test 50 0 "SAVEPOINT outer" | |
353 without_rowid3-2-test 51 1 "INSERT INTO leaf VALUES('f', 4)" | |
354 without_rowid3-2-test 52 1 "SAVEPOINT inner" | |
355 without_rowid3-2-test 53 1 "INSERT INTO leaf VALUES('g', 4)" | |
356 without_rowid3-2-test 54 1 "RELEASE outer" FKV | |
357 without_rowid3-2-test 55 1 "ROLLBACK TO inner" | |
358 without_rowid3-2-test 56 0 "COMMIT" FKV | |
359 without_rowid3-2-test 57 0 "INSERT INTO node VALUES(4, NULL)" | |
360 without_rowid3-2-test 58 0 "RELEASE outer" | |
361 without_rowid3-2-test 59 0 "SELECT * FROM node" {2 {} 3 2 4 {}} | |
362 without_rowid3-2-test 60 0 "SELECT * FROM leaf" {a 2 d 3 e 3 f 4} | |
363 | |
364 # The following set of tests check that if a statement that affects | |
365 # multiple rows violates some foreign key constraints, then strikes a | |
366 # constraint that causes the statement-transaction to be rolled back, | |
367 # the deferred constraint counter is correctly reset to the value it | |
368 # had before the statement-transaction was opened. | |
369 # | |
370 without_rowid3-2-test 61 0 "BEGIN" | |
371 without_rowid3-2-test 62 0 "DELETE FROM leaf" | |
372 without_rowid3-2-test 63 0 "DELETE FROM node" | |
373 without_rowid3-2-test 64 1 "INSERT INTO leaf VALUES('a', 1)" | |
374 without_rowid3-2-test 65 1 "INSERT INTO leaf VALUES('b', 2)" | |
375 without_rowid3-2-test 66 1 "INSERT INTO leaf VALUES('c', 1)" | |
376 do_test without_rowid3-2-test-67 { | |
377 catchsql "INSERT INTO node SELECT parent, 3 FROM leaf" | |
378 } {1 {UNIQUE constraint failed: node.nodeid}} | |
379 without_rowid3-2-test 68 0 "COMMIT" FKV | |
380 without_rowid3-2-test 69 1 "INSERT INTO node VALUES(1, NULL)" | |
381 without_rowid3-2-test 70 0 "INSERT INTO node VALUES(2, NULL)" | |
382 without_rowid3-2-test 71 0 "COMMIT" | |
383 | |
384 without_rowid3-2-test 72 0 "BEGIN" | |
385 without_rowid3-2-test 73 1 "DELETE FROM node" | |
386 without_rowid3-2-test 74 0 "INSERT INTO node(nodeid) SELECT DISTINCT parent FR
OM leaf" | |
387 without_rowid3-2-test 75 0 "COMMIT" | |
388 | |
389 #------------------------------------------------------------------------- | |
390 # Test cases without_rowid3-3.* test that a program that executes foreign key | |
391 # actions (CASCADE, SET DEFAULT, SET NULL etc.) or tests FK constraints | |
392 # opens a statement transaction if required. | |
393 # | |
394 # without_rowid3-3.1.*: Test UPDATE statements. | |
395 # without_rowid3-3.2.*: Test DELETE statements. | |
396 # | |
397 drop_all_tables | |
398 do_test without_rowid3-3.1.1 { | |
399 execsql { | |
400 CREATE TABLE ab(a PRIMARY KEY, b) WITHOUT rowid; | |
401 CREATE TABLE cd( | |
402 c PRIMARY KEY REFERENCES ab ON UPDATE CASCADE ON DELETE CASCADE, | |
403 d | |
404 ) WITHOUT rowid; | |
405 CREATE TABLE ef( | |
406 e REFERENCES cd ON UPDATE CASCADE, | |
407 f, CHECK (e!=5) | |
408 ); | |
409 } | |
410 } {} | |
411 do_test without_rowid3-3.1.2 { | |
412 execsql { | |
413 INSERT INTO ab VALUES(1, 'b'); | |
414 INSERT INTO cd VALUES(1, 'd'); | |
415 INSERT INTO ef VALUES(1, 'e'); | |
416 } | |
417 } {} | |
418 do_test without_rowid3-3.1.3 { | |
419 catchsql { UPDATE ab SET a = 5 } | |
420 } {1 {CHECK constraint failed: ef}} | |
421 do_test without_rowid3-3.1.4 { | |
422 execsql { SELECT * FROM ab } | |
423 } {1 b} | |
424 do_test without_rowid3-3.1.4 { | |
425 execsql BEGIN; | |
426 catchsql { UPDATE ab SET a = 5 } | |
427 } {1 {CHECK constraint failed: ef}} | |
428 do_test without_rowid3-3.1.5 { | |
429 execsql COMMIT; | |
430 execsql { SELECT * FROM ab; SELECT * FROM cd; SELECT * FROM ef } | |
431 } {1 b 1 d 1 e} | |
432 | |
433 do_test without_rowid3-3.2.1 { | |
434 execsql BEGIN; | |
435 catchsql { DELETE FROM ab } | |
436 } {1 {FOREIGN KEY constraint failed}} | |
437 do_test without_rowid3-3.2.2 { | |
438 execsql COMMIT | |
439 execsql { SELECT * FROM ab; SELECT * FROM cd; SELECT * FROM ef } | |
440 } {1 b 1 d 1 e} | |
441 | |
442 #------------------------------------------------------------------------- | |
443 # Test cases without_rowid3-4.* test that recursive foreign key actions | |
444 # (i.e. CASCADE) are allowed even if recursive triggers are disabled. | |
445 # | |
446 drop_all_tables | |
447 do_test without_rowid3-4.1 { | |
448 execsql { | |
449 CREATE TABLE t1( | |
450 node PRIMARY KEY, | |
451 parent REFERENCES t1 ON DELETE CASCADE | |
452 ) WITHOUT rowid; | |
453 CREATE TABLE t2(node PRIMARY KEY, parent) WITHOUT rowid; | |
454 CREATE TRIGGER t2t AFTER DELETE ON t2 BEGIN | |
455 DELETE FROM t2 WHERE parent = old.node; | |
456 END; | |
457 INSERT INTO t1 VALUES(1, NULL); | |
458 INSERT INTO t1 VALUES(2, 1); | |
459 INSERT INTO t1 VALUES(3, 1); | |
460 INSERT INTO t1 VALUES(4, 2); | |
461 INSERT INTO t1 VALUES(5, 2); | |
462 INSERT INTO t1 VALUES(6, 3); | |
463 INSERT INTO t1 VALUES(7, 3); | |
464 INSERT INTO t2 SELECT * FROM t1; | |
465 } | |
466 } {} | |
467 do_test without_rowid3-4.2 { | |
468 execsql { PRAGMA recursive_triggers = off } | |
469 execsql { | |
470 BEGIN; | |
471 DELETE FROM t1 WHERE node = 1; | |
472 SELECT node FROM t1; | |
473 } | |
474 } {} | |
475 do_test without_rowid3-4.3 { | |
476 execsql { | |
477 DELETE FROM t2 WHERE node = 1; | |
478 SELECT node FROM t2; | |
479 ROLLBACK; | |
480 } | |
481 } {4 5 6 7} | |
482 do_test without_rowid3-4.4 { | |
483 execsql { PRAGMA recursive_triggers = on } | |
484 execsql { | |
485 BEGIN; | |
486 DELETE FROM t1 WHERE node = 1; | |
487 SELECT node FROM t1; | |
488 } | |
489 } {} | |
490 do_test without_rowid3-4.3 { | |
491 execsql { | |
492 DELETE FROM t2 WHERE node = 1; | |
493 SELECT node FROM t2; | |
494 ROLLBACK; | |
495 } | |
496 } {} | |
497 | |
498 #------------------------------------------------------------------------- | |
499 # Test cases without_rowid3-5.* verify that the incremental blob API may not | |
500 # write to a foreign key column while foreign-keys are enabled. | |
501 # | |
502 drop_all_tables | |
503 ifcapable incrblob { | |
504 do_test without_rowid3-5.1 { | |
505 execsql { | |
506 CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT rowid; | |
507 CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1(a)) WITHOUT rowid; | |
508 INSERT INTO t1 VALUES('hello', 'world'); | |
509 INSERT INTO t2 VALUES('key', 'hello'); | |
510 } | |
511 } {} | |
512 do_test without_rowid3-5.2 { | |
513 set rc [catch { set fd [db incrblob t2 b 1] } msg] | |
514 list $rc $msg | |
515 } {1 {cannot open table without rowid: t2}} | |
516 do_test without_rowid3-5.5 { | |
517 execsql { PRAGMA foreign_keys = on } | |
518 } {} | |
519 } | |
520 | |
521 drop_all_tables | |
522 ifcapable vacuum { | |
523 do_test without_rowid3-6.1 { | |
524 execsql { | |
525 CREATE TABLE t1(a REFERENCES t2(c), b); | |
526 CREATE TABLE t2(c UNIQUE, b); | |
527 INSERT INTO t2 VALUES(1, 2); | |
528 INSERT INTO t1 VALUES(1, 2); | |
529 VACUUM; | |
530 } | |
531 } {} | |
532 } | |
533 | |
534 #------------------------------------------------------------------------- | |
535 # Test that it is possible to use an INT PRIMARY KEY as the child key | |
536 # of a foreign constraint. | |
537 # | |
538 drop_all_tables | |
539 do_test without_rowid3-7.1 { | |
540 execsql { | |
541 CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT rowid; | |
542 CREATE TABLE t2(c INT PRIMARY KEY REFERENCES t1, b) WITHOUT rowid; | |
543 } | |
544 } {} | |
545 do_test without_rowid3-7.2 { | |
546 catchsql { INSERT INTO t2 VALUES(1, 'A'); } | |
547 } {1 {FOREIGN KEY constraint failed}} | |
548 do_test without_rowid3-7.3 { | |
549 execsql { | |
550 INSERT INTO t1 VALUES(1, 2); | |
551 INSERT INTO t1 VALUES(2, 3); | |
552 INSERT INTO t2 VALUES(1, 'A'); | |
553 } | |
554 } {} | |
555 do_test without_rowid3-7.4 { | |
556 execsql { UPDATE t2 SET c = 2 } | |
557 } {} | |
558 do_test without_rowid3-7.5 { | |
559 catchsql { UPDATE t2 SET c = 3 } | |
560 } {1 {FOREIGN KEY constraint failed}} | |
561 do_test without_rowid3-7.6 { | |
562 catchsql { DELETE FROM t1 WHERE a = 2 } | |
563 } {1 {FOREIGN KEY constraint failed}} | |
564 do_test without_rowid3-7.7 { | |
565 execsql { DELETE FROM t1 WHERE a = 1 } | |
566 } {} | |
567 do_test without_rowid3-7.8 { | |
568 catchsql { UPDATE t1 SET a = 3 } | |
569 } {1 {FOREIGN KEY constraint failed}} | |
570 | |
571 #------------------------------------------------------------------------- | |
572 # Test that it is not possible to enable/disable FK support while a | |
573 # transaction is open. | |
574 # | |
575 drop_all_tables | |
576 proc without_rowid3-8-test {tn zSql value} { | |
577 do_test without_rowid3-2.8.$tn.1 [list execsql $zSql] {} | |
578 do_test without_rowid3-2.8.$tn.2 { execsql "PRAGMA foreign_keys" } $value | |
579 } | |
580 without_rowid3-8-test 1 { PRAGMA foreign_keys = 0 } 0 | |
581 without_rowid3-8-test 2 { PRAGMA foreign_keys = 1 } 1 | |
582 without_rowid3-8-test 3 { BEGIN } 1 | |
583 without_rowid3-8-test 4 { PRAGMA foreign_keys = 0 } 1 | |
584 without_rowid3-8-test 5 { COMMIT } 1 | |
585 without_rowid3-8-test 6 { PRAGMA foreign_keys = 0 } 0 | |
586 without_rowid3-8-test 7 { BEGIN } 0 | |
587 without_rowid3-8-test 8 { PRAGMA foreign_keys = 1 } 0 | |
588 without_rowid3-8-test 9 { COMMIT } 0 | |
589 without_rowid3-8-test 10 { PRAGMA foreign_keys = 1 } 1 | |
590 without_rowid3-8-test 11 { PRAGMA foreign_keys = off } 0 | |
591 without_rowid3-8-test 12 { PRAGMA foreign_keys = on } 1 | |
592 without_rowid3-8-test 13 { PRAGMA foreign_keys = no } 0 | |
593 without_rowid3-8-test 14 { PRAGMA foreign_keys = yes } 1 | |
594 without_rowid3-8-test 15 { PRAGMA foreign_keys = false } 0 | |
595 without_rowid3-8-test 16 { PRAGMA foreign_keys = true } 1 | |
596 | |
597 #------------------------------------------------------------------------- | |
598 # The following tests, without_rowid3-9.*, test SET DEFAULT actions. | |
599 # | |
600 drop_all_tables | |
601 do_test without_rowid3-9.1.1 { | |
602 execsql { | |
603 CREATE TABLE t1(a INT PRIMARY KEY, b) WITHOUT rowid; | |
604 CREATE TABLE t2( | |
605 c INT PRIMARY KEY, | |
606 d INTEGER DEFAULT 1 REFERENCES t1 ON DELETE SET DEFAULT | |
607 ) WITHOUT rowid; | |
608 DELETE FROM t1; | |
609 } | |
610 } {} | |
611 do_test without_rowid3-9.1.2 { | |
612 execsql { | |
613 INSERT INTO t1 VALUES(1, 'one'); | |
614 INSERT INTO t1 VALUES(2, 'two'); | |
615 INSERT INTO t2 VALUES(1, 2); | |
616 SELECT * FROM t2; | |
617 DELETE FROM t1 WHERE a = 2; | |
618 SELECT * FROM t2; | |
619 } | |
620 } {1 2 1 1} | |
621 do_test without_rowid3-9.1.3 { | |
622 execsql { | |
623 INSERT INTO t1 VALUES(2, 'two'); | |
624 UPDATE t2 SET d = 2; | |
625 DELETE FROM t1 WHERE a = 1; | |
626 SELECT * FROM t2; | |
627 } | |
628 } {1 2} | |
629 do_test without_rowid3-9.1.4 { | |
630 execsql { SELECT * FROM t1 } | |
631 } {2 two} | |
632 do_test without_rowid3-9.1.5 { | |
633 catchsql { DELETE FROM t1 } | |
634 } {1 {FOREIGN KEY constraint failed}} | |
635 | |
636 do_test without_rowid3-9.2.1 { | |
637 execsql { | |
638 CREATE TABLE pp(a, b, c, PRIMARY KEY(b, c)) WITHOUT rowid; | |
639 CREATE TABLE cc(d DEFAULT 3, e DEFAULT 1, f DEFAULT 2, | |
640 FOREIGN KEY(f, d) REFERENCES pp | |
641 ON UPDATE SET DEFAULT | |
642 ON DELETE SET NULL | |
643 ); | |
644 INSERT INTO pp VALUES(1, 2, 3); | |
645 INSERT INTO pp VALUES(4, 5, 6); | |
646 INSERT INTO pp VALUES(7, 8, 9); | |
647 } | |
648 } {} | |
649 do_test without_rowid3-9.2.2 { | |
650 execsql { | |
651 INSERT INTO cc VALUES(6, 'A', 5); | |
652 INSERT INTO cc VALUES(6, 'B', 5); | |
653 INSERT INTO cc VALUES(9, 'A', 8); | |
654 INSERT INTO cc VALUES(9, 'B', 8); | |
655 UPDATE pp SET b = 1 WHERE a = 7; | |
656 SELECT * FROM cc; | |
657 } | |
658 } {6 A 5 6 B 5 3 A 2 3 B 2} | |
659 do_test without_rowid3-9.2.3 { | |
660 execsql { | |
661 DELETE FROM pp WHERE a = 4; | |
662 SELECT * FROM cc; | |
663 } | |
664 } {{} A {} {} B {} 3 A 2 3 B 2} | |
665 | |
666 #------------------------------------------------------------------------- | |
667 # The following tests, without_rowid3-10.*, test "foreign key mismatch" and | |
668 # other errors. | |
669 # | |
670 set tn 0 | |
671 foreach zSql [list { | |
672 CREATE TABLE p(a PRIMARY KEY, b) WITHOUT rowid; | |
673 CREATE TABLE c(x REFERENCES p(c)); | |
674 } { | |
675 CREATE TABLE c(x REFERENCES v(y)); | |
676 CREATE VIEW v AS SELECT x AS y FROM c; | |
677 } { | |
678 CREATE TABLE p(a, b, PRIMARY KEY(a, b)) WITHOUT rowid; | |
679 CREATE TABLE c(x REFERENCES p); | |
680 } { | |
681 CREATE TABLE p(a COLLATE binary, b); | |
682 CREATE UNIQUE INDEX i ON p(a COLLATE nocase); | |
683 CREATE TABLE c(x REFERENCES p(a)); | |
684 }] { | |
685 drop_all_tables | |
686 do_test without_rowid3-10.1.[incr tn] { | |
687 execsql $zSql | |
688 catchsql { INSERT INTO c DEFAULT VALUES } | |
689 } {/1 {foreign key mismatch - "c" referencing "."}/} | |
690 } | |
691 | |
692 # "rowid" cannot be used as part of a child or parent key definition | |
693 # unless it happens to be the name of an explicitly declared column. | |
694 # | |
695 do_test without_rowid3-10.2.1 { | |
696 drop_all_tables | |
697 catchsql { | |
698 CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT rowid; | |
699 CREATE TABLE t2(c, d, FOREIGN KEY(rowid) REFERENCES t1(a)); | |
700 } | |
701 } {1 {unknown column "rowid" in foreign key definition}} | |
702 do_test without_rowid3-10.2.2 { | |
703 drop_all_tables | |
704 catchsql { | |
705 CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT rowid; | |
706 CREATE TABLE t2(rowid, d, FOREIGN KEY(rowid) REFERENCES t1(a)); | |
707 } | |
708 } {0 {}} | |
709 do_test without_rowid3-10.2.1 { | |
710 drop_all_tables | |
711 catchsql { | |
712 CREATE TABLE t1(a, b); | |
713 CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(rowid)); | |
714 INSERT INTO t1(rowid, a, b) VALUES(1, 1, 1); | |
715 INSERT INTO t2 VALUES(1, 1); | |
716 } | |
717 } {1 {foreign key mismatch - "t2" referencing "t1"}} | |
718 do_test without_rowid3-10.2.2 { | |
719 drop_all_tables | |
720 catchsql { | |
721 CREATE TABLE t1(rowid PRIMARY KEY, b) WITHOUT rowid; | |
722 CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(rowid)); | |
723 INSERT INTO t1(rowid, b) VALUES(1, 1); | |
724 INSERT INTO t2 VALUES(1, 1); | |
725 } | |
726 } {0 {}} | |
727 | |
728 | |
729 #------------------------------------------------------------------------- | |
730 # The following tests, without_rowid3-11.*, test CASCADE actions. | |
731 # | |
732 drop_all_tables | |
733 do_test without_rowid3-11.1.1 { | |
734 execsql { | |
735 CREATE TABLE t1(a INT PRIMARY KEY, b) WITHOUT rowid; | |
736 CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(a) ON UPDATE CASCADE); | |
737 | |
738 INSERT INTO t1 VALUES(10, 100); | |
739 INSERT INTO t2 VALUES(10, 100); | |
740 UPDATE t1 SET a = 15; | |
741 SELECT * FROM t2; | |
742 } | |
743 } {15 100} | |
744 | |
745 #------------------------------------------------------------------------- | |
746 # The following tests, without_rowid3-12.*, test RESTRICT actions. | |
747 # | |
748 drop_all_tables | |
749 do_test without_rowid3-12.1.1 { | |
750 execsql { | |
751 CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT rowid; | |
752 CREATE TABLE t2( | |
753 x REFERENCES t1 ON UPDATE RESTRICT DEFERRABLE INITIALLY DEFERRED | |
754 ); | |
755 INSERT INTO t1 VALUES(1, 'one'); | |
756 INSERT INTO t1 VALUES(2, 'two'); | |
757 INSERT INTO t1 VALUES(3, 'three'); | |
758 } | |
759 } {} | |
760 do_test without_rowid3-12.1.2 { | |
761 execsql "BEGIN" | |
762 execsql "INSERT INTO t2 VALUES('two')" | |
763 } {} | |
764 do_test without_rowid3-12.1.3 { | |
765 execsql "UPDATE t1 SET b = 'four' WHERE b = 'one'" | |
766 } {} | |
767 do_test without_rowid3-12.1.4 { | |
768 catchsql "UPDATE t1 SET b = 'five' WHERE b = 'two'" | |
769 } {1 {FOREIGN KEY constraint failed}} | |
770 do_test without_rowid3-12.1.5 { | |
771 execsql "DELETE FROM t1 WHERE b = 'two'" | |
772 } {} | |
773 do_test without_rowid3-12.1.6 { | |
774 catchsql "COMMIT" | |
775 } {1 {FOREIGN KEY constraint failed}} | |
776 do_test without_rowid3-12.1.7 { | |
777 execsql { | |
778 INSERT INTO t1 VALUES(2, 'two'); | |
779 COMMIT; | |
780 } | |
781 } {} | |
782 | |
783 drop_all_tables | |
784 do_test without_rowid3-12.2.1 { | |
785 execsql { | |
786 CREATE TABLE t1(x COLLATE NOCASE PRIMARY KEY) WITHOUT rowid; | |
787 CREATE TRIGGER tt1 AFTER DELETE ON t1 | |
788 WHEN EXISTS ( SELECT 1 FROM t2 WHERE old.x = y ) | |
789 BEGIN | |
790 INSERT INTO t1 VALUES(old.x); | |
791 END; | |
792 CREATE TABLE t2(y REFERENCES t1); | |
793 INSERT INTO t1 VALUES('A'); | |
794 INSERT INTO t1 VALUES('B'); | |
795 INSERT INTO t2 VALUES('a'); | |
796 INSERT INTO t2 VALUES('b'); | |
797 | |
798 SELECT * FROM t1; | |
799 SELECT * FROM t2; | |
800 } | |
801 } {A B a b} | |
802 do_test without_rowid3-12.2.2 { | |
803 execsql { DELETE FROM t1 } | |
804 execsql { | |
805 SELECT * FROM t1; | |
806 SELECT * FROM t2; | |
807 } | |
808 } {A B a b} | |
809 do_test without_rowid3-12.2.3 { | |
810 execsql { | |
811 DROP TABLE t2; | |
812 CREATE TABLE t2(y REFERENCES t1 ON DELETE RESTRICT); | |
813 INSERT INTO t2 VALUES('a'); | |
814 INSERT INTO t2 VALUES('b'); | |
815 } | |
816 catchsql { DELETE FROM t1 } | |
817 } {1 {FOREIGN KEY constraint failed}} | |
818 do_test without_rowid3-12.2.4 { | |
819 execsql { | |
820 SELECT * FROM t1; | |
821 SELECT * FROM t2; | |
822 } | |
823 } {A B a b} | |
824 | |
825 drop_all_tables | |
826 do_test without_rowid3-12.3.1 { | |
827 execsql { | |
828 CREATE TABLE up( | |
829 c00, c01, c02, c03, c04, c05, c06, c07, c08, c09, | |
830 c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, | |
831 c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, | |
832 c30, c31, c32, c33, c34, c35, c36, c37, c38, c39, | |
833 PRIMARY KEY(c34, c35) | |
834 ) WITHOUT rowid; | |
835 CREATE TABLE down( | |
836 c00, c01, c02, c03, c04, c05, c06, c07, c08, c09, | |
837 c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, | |
838 c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, | |
839 c30, c31, c32, c33, c34, c35, c36, c37, c38, c39, | |
840 FOREIGN KEY(c39, c38) REFERENCES up ON UPDATE CASCADE | |
841 ); | |
842 } | |
843 } {} | |
844 do_test without_rowid3-12.3.2 { | |
845 execsql { | |
846 INSERT INTO up(c34, c35) VALUES('yes', 'no'); | |
847 INSERT INTO down(c39, c38) VALUES('yes', 'no'); | |
848 UPDATE up SET c34 = 'possibly'; | |
849 SELECT c38, c39 FROM down; | |
850 DELETE FROM down; | |
851 } | |
852 } {no possibly} | |
853 do_test without_rowid3-12.3.3 { | |
854 catchsql { INSERT INTO down(c39, c38) VALUES('yes', 'no') } | |
855 } {1 {FOREIGN KEY constraint failed}} | |
856 do_test without_rowid3-12.3.4 { | |
857 execsql { | |
858 INSERT INTO up(c34, c35) VALUES('yes', 'no'); | |
859 INSERT INTO down(c39, c38) VALUES('yes', 'no'); | |
860 } | |
861 catchsql { DELETE FROM up WHERE c34 = 'yes' } | |
862 } {1 {FOREIGN KEY constraint failed}} | |
863 do_test without_rowid3-12.3.5 { | |
864 execsql { | |
865 DELETE FROM up WHERE c34 = 'possibly'; | |
866 SELECT c34, c35 FROM up; | |
867 SELECT c39, c38 FROM down; | |
868 } | |
869 } {yes no yes no} | |
870 | |
871 #------------------------------------------------------------------------- | |
872 # The following tests, without_rowid3-13.*, test that FK processing is performed | |
873 # when rows are REPLACEd. | |
874 # | |
875 drop_all_tables | |
876 do_test without_rowid3-13.1.1 { | |
877 execsql { | |
878 CREATE TABLE pp(a UNIQUE, b, c, PRIMARY KEY(b, c)) WITHOUT rowid; | |
879 CREATE TABLE cc(d, e, f UNIQUE, FOREIGN KEY(d, e) REFERENCES pp); | |
880 INSERT INTO pp VALUES(1, 2, 3); | |
881 INSERT INTO cc VALUES(2, 3, 1); | |
882 } | |
883 } {} | |
884 foreach {tn stmt} { | |
885 1 "REPLACE INTO pp VALUES(1, 4, 5)" | |
886 } { | |
887 do_test without_rowid3-13.1.$tn.1 { | |
888 catchsql $stmt | |
889 } {1 {FOREIGN KEY constraint failed}} | |
890 do_test without_rowid3-13.1.$tn.2 { | |
891 execsql { | |
892 SELECT * FROM pp; | |
893 SELECT * FROM cc; | |
894 } | |
895 } {1 2 3 2 3 1} | |
896 do_test without_rowid3-13.1.$tn.3 { | |
897 execsql BEGIN; | |
898 catchsql $stmt | |
899 } {1 {FOREIGN KEY constraint failed}} | |
900 do_test without_rowid3-13.1.$tn.4 { | |
901 execsql { | |
902 COMMIT; | |
903 SELECT * FROM pp; | |
904 SELECT * FROM cc; | |
905 } | |
906 } {1 2 3 2 3 1} | |
907 } | |
908 | |
909 #------------------------------------------------------------------------- | |
910 # The following tests, without_rowid3-14.*, test that the "DROP TABLE" and "ALTE
R | |
911 # TABLE" commands work as expected wrt foreign key constraints. | |
912 # | |
913 # without_rowid3-14.1*: ALTER TABLE ADD COLUMN | |
914 # without_rowid3-14.2*: ALTER TABLE RENAME TABLE | |
915 # without_rowid3-14.3*: DROP TABLE | |
916 # | |
917 drop_all_tables | |
918 ifcapable altertable { | |
919 do_test without_rowid3-14.1.1 { | |
920 # Adding a column with a REFERENCES clause is not supported. | |
921 execsql { | |
922 CREATE TABLE t1(a PRIMARY KEY) WITHOUT rowid; | |
923 CREATE TABLE t2(a, b); | |
924 } | |
925 catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } | |
926 } {0 {}} | |
927 do_test without_rowid3-14.1.2 { | |
928 catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 } | |
929 } {0 {}} | |
930 do_test without_rowid3-14.1.3 { | |
931 catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL} | |
932 } {0 {}} | |
933 do_test without_rowid3-14.1.4 { | |
934 catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'} | |
935 } {1 {Cannot add a REFERENCES column with non-NULL default value}} | |
936 do_test without_rowid3-14.1.5 { | |
937 catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 } | |
938 } {1 {Cannot add a REFERENCES column with non-NULL default value}} | |
939 do_test without_rowid3-14.1.6 { | |
940 execsql { | |
941 PRAGMA foreign_keys = off; | |
942 ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1; | |
943 PRAGMA foreign_keys = on; | |
944 SELECT sql FROM sqlite_master WHERE name='t2'; | |
945 } | |
946 } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REF
ERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} | |
947 | |
948 | |
949 # Test the sqlite_rename_parent() function directly. | |
950 # | |
951 proc test_rename_parent {zCreate zOld zNew} { | |
952 db eval {SELECT sqlite_rename_parent($zCreate, $zOld, $zNew)} | |
953 } | |
954 do_test without_rowid3-14.2.1.1 { | |
955 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 | |
956 } {{CREATE TABLE t1(a REFERENCES "t3")}} | |
957 do_test without_rowid3-14.2.1.2 { | |
958 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 | |
959 } {{CREATE TABLE t1(a REFERENCES t2)}} | |
960 do_test without_rowid3-14.2.1.3 { | |
961 test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 | |
962 } {{CREATE TABLE t1(a REFERENCES "t3")}} | |
963 | |
964 # Test ALTER TABLE RENAME TABLE a bit. | |
965 # | |
966 do_test without_rowid3-14.2.2.1 { | |
967 drop_all_tables | |
968 execsql { | |
969 CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid; | |
970 CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2) | |
971 WITHOUT rowid; | |
972 CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1); | |
973 } | |
974 execsql { SELECT sql FROM sqlite_master WHERE type = 'table'} | |
975 } [list \ | |
976 {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid} \ | |
977 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2) | |
978 WITHOUT rowid} \ | |
979 {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \ | |
980 ] | |
981 do_test without_rowid3-14.2.2.2 { | |
982 execsql { ALTER TABLE t1 RENAME TO t4 } | |
983 execsql { SELECT sql FROM sqlite_master WHERE type = 'table'} | |
984 } [list \ | |
985 {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid} \ | |
986 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2) | |
987 WITHOUT rowid} \ | |
988 {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \ | |
989 ] | |
990 do_test without_rowid3-14.2.2.3 { | |
991 catchsql { INSERT INTO t3 VALUES(1, 2, 3) } | |
992 } {1 {FOREIGN KEY constraint failed}} | |
993 do_test without_rowid3-14.2.2.4 { | |
994 execsql { INSERT INTO t4 VALUES(1, NULL) } | |
995 } {} | |
996 do_test without_rowid3-14.2.2.5 { | |
997 catchsql { UPDATE t4 SET b = 5 } | |
998 } {1 {FOREIGN KEY constraint failed}} | |
999 do_test without_rowid3-14.2.2.6 { | |
1000 catchsql { UPDATE t4 SET b = 1 } | |
1001 } {0 {}} | |
1002 do_test without_rowid3-14.2.2.7 { | |
1003 execsql { INSERT INTO t3 VALUES(1, NULL, 1) } | |
1004 } {} | |
1005 | |
1006 # Repeat for TEMP tables | |
1007 # | |
1008 drop_all_tables | |
1009 do_test without_rowid3-14.1tmp.1 { | |
1010 # Adding a column with a REFERENCES clause is not supported. | |
1011 execsql { | |
1012 CREATE TEMP TABLE t1(a PRIMARY KEY) WITHOUT rowid; | |
1013 CREATE TEMP TABLE t2(a, b); | |
1014 } | |
1015 catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } | |
1016 } {0 {}} | |
1017 do_test without_rowid3-14.1tmp.2 { | |
1018 catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 } | |
1019 } {0 {}} | |
1020 do_test without_rowid3-14.1tmp.3 { | |
1021 catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL} | |
1022 } {0 {}} | |
1023 do_test without_rowid3-14.1tmp.4 { | |
1024 catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'} | |
1025 } {1 {Cannot add a REFERENCES column with non-NULL default value}} | |
1026 do_test without_rowid3-14.1tmp.5 { | |
1027 catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 } | |
1028 } {1 {Cannot add a REFERENCES column with non-NULL default value}} | |
1029 do_test without_rowid3-14.1tmp.6 { | |
1030 execsql { | |
1031 PRAGMA foreign_keys = off; | |
1032 ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1; | |
1033 PRAGMA foreign_keys = on; | |
1034 SELECT sql FROM sqlite_temp_master WHERE name='t2'; | |
1035 } | |
1036 } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REF
ERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} | |
1037 | |
1038 do_test without_rowid3-14.2tmp.1.1 { | |
1039 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 | |
1040 } {{CREATE TABLE t1(a REFERENCES "t3")}} | |
1041 do_test without_rowid3-14.2tmp.1.2 { | |
1042 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 | |
1043 } {{CREATE TABLE t1(a REFERENCES t2)}} | |
1044 do_test without_rowid3-14.2tmp.1.3 { | |
1045 test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 | |
1046 } {{CREATE TABLE t1(a REFERENCES "t3")}} | |
1047 | |
1048 # Test ALTER TABLE RENAME TABLE a bit. | |
1049 # | |
1050 do_test without_rowid3-14.2tmp.2.1 { | |
1051 drop_all_tables | |
1052 execsql { | |
1053 CREATE TEMP TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid; | |
1054 CREATE TEMP TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2) | |
1055 WITHOUT rowid; | |
1056 CREATE TEMP TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1); | |
1057 } | |
1058 execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'} | |
1059 } [list \ | |
1060 {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid} \ | |
1061 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2) | |
1062 WITHOUT rowid} \ | |
1063 {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \ | |
1064 ] | |
1065 do_test without_rowid3-14.2tmp.2.2 { | |
1066 execsql { ALTER TABLE t1 RENAME TO t4 } | |
1067 execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'} | |
1068 } [list \ | |
1069 {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid} \ | |
1070 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2) | |
1071 WITHOUT rowid} \ | |
1072 {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \ | |
1073 ] | |
1074 do_test without_rowid3-14.2tmp.2.3 { | |
1075 catchsql { INSERT INTO t3 VALUES(1, 2, 3) } | |
1076 } {1 {FOREIGN KEY constraint failed}} | |
1077 do_test without_rowid3-14.2tmp.2.4 { | |
1078 execsql { INSERT INTO t4 VALUES(1, NULL) } | |
1079 } {} | |
1080 do_test without_rowid3-14.2tmp.2.5 { | |
1081 catchsql { UPDATE t4 SET b = 5 } | |
1082 } {1 {FOREIGN KEY constraint failed}} | |
1083 do_test without_rowid3-14.2tmp.2.6 { | |
1084 catchsql { UPDATE t4 SET b = 1 } | |
1085 } {0 {}} | |
1086 do_test without_rowid3-14.2tmp.2.7 { | |
1087 execsql { INSERT INTO t3 VALUES(1, NULL, 1) } | |
1088 } {} | |
1089 | |
1090 # Repeat for ATTACH-ed tables | |
1091 # | |
1092 drop_all_tables | |
1093 do_test without_rowid3-14.1aux.1 { | |
1094 # Adding a column with a REFERENCES clause is not supported. | |
1095 execsql { | |
1096 ATTACH ':memory:' AS aux; | |
1097 CREATE TABLE aux.t1(a PRIMARY KEY) WITHOUT rowid; | |
1098 CREATE TABLE aux.t2(a, b); | |
1099 } | |
1100 catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } | |
1101 } {0 {}} | |
1102 do_test without_rowid3-14.1aux.2 { | |
1103 catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 } | |
1104 } {0 {}} | |
1105 do_test without_rowid3-14.1aux.3 { | |
1106 catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL} | |
1107 } {0 {}} | |
1108 do_test without_rowid3-14.1aux.4 { | |
1109 catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'} | |
1110 } {1 {Cannot add a REFERENCES column with non-NULL default value}} | |
1111 do_test without_rowid3-14.1aux.5 { | |
1112 catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 } | |
1113 } {1 {Cannot add a REFERENCES column with non-NULL default value}} | |
1114 do_test without_rowid3-14.1aux.6 { | |
1115 execsql { | |
1116 PRAGMA foreign_keys = off; | |
1117 ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1; | |
1118 PRAGMA foreign_keys = on; | |
1119 SELECT sql FROM aux.sqlite_master WHERE name='t2'; | |
1120 } | |
1121 } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REF
ERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} | |
1122 | |
1123 do_test without_rowid3-14.2aux.1.1 { | |
1124 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 | |
1125 } {{CREATE TABLE t1(a REFERENCES "t3")}} | |
1126 do_test without_rowid3-14.2aux.1.2 { | |
1127 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 | |
1128 } {{CREATE TABLE t1(a REFERENCES t2)}} | |
1129 do_test without_rowid3-14.2aux.1.3 { | |
1130 test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 | |
1131 } {{CREATE TABLE t1(a REFERENCES "t3")}} | |
1132 | |
1133 # Test ALTER TABLE RENAME TABLE a bit. | |
1134 # | |
1135 do_test without_rowid3-14.2aux.2.1 { | |
1136 drop_all_tables | |
1137 execsql { | |
1138 CREATE TABLE aux.t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid; | |
1139 CREATE TABLE aux.t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2) | |
1140 WITHOUT rowid; | |
1141 CREATE TABLE aux.t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1); | |
1142 } | |
1143 execsql { SELECT sql FROM aux.sqlite_master WHERE type = 'table'} | |
1144 } [list \ | |
1145 {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid} \ | |
1146 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2) | |
1147 WITHOUT rowid} \ | |
1148 {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \ | |
1149 ] | |
1150 do_test without_rowid3-14.2aux.2.2 { | |
1151 execsql { ALTER TABLE t1 RENAME TO t4 } | |
1152 execsql { SELECT sql FROM aux.sqlite_master WHERE type = 'table'} | |
1153 } [list \ | |
1154 {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid} \ | |
1155 {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2) | |
1156 WITHOUT rowid} \ | |
1157 {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \ | |
1158 ] | |
1159 do_test without_rowid3-14.2aux.2.3 { | |
1160 catchsql { INSERT INTO t3 VALUES(1, 2, 3) } | |
1161 } {1 {FOREIGN KEY constraint failed}} | |
1162 do_test without_rowid3-14.2aux.2.4 { | |
1163 execsql { INSERT INTO t4 VALUES(1, NULL) } | |
1164 } {} | |
1165 do_test without_rowid3-14.2aux.2.5 { | |
1166 catchsql { UPDATE t4 SET b = 5 } | |
1167 } {1 {FOREIGN KEY constraint failed}} | |
1168 do_test without_rowid3-14.2aux.2.6 { | |
1169 catchsql { UPDATE t4 SET b = 1 } | |
1170 } {0 {}} | |
1171 do_test without_rowid3-14.2aux.2.7 { | |
1172 execsql { INSERT INTO t3 VALUES(1, NULL, 1) } | |
1173 } {} | |
1174 } | |
1175 | |
1176 do_test without_rowid3-2.14.3.1 { | |
1177 drop_all_tables | |
1178 execsql { | |
1179 CREATE TABLE t1(a, b REFERENCES nosuchtable); | |
1180 DROP TABLE t1; | |
1181 } | |
1182 } {} | |
1183 do_test without_rowid3-2.14.3.2 { | |
1184 execsql { | |
1185 CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT rowid; | |
1186 INSERT INTO t1 VALUES('a', 1); | |
1187 CREATE TABLE t2(x REFERENCES t1); | |
1188 INSERT INTO t2 VALUES('a'); | |
1189 } | |
1190 } {} | |
1191 do_test without_rowid3-2.14.3.3 { | |
1192 catchsql { DROP TABLE t1 } | |
1193 } {1 {FOREIGN KEY constraint failed}} | |
1194 do_test without_rowid3-2.14.3.4 { | |
1195 execsql { | |
1196 DELETE FROM t2; | |
1197 DROP TABLE t1; | |
1198 } | |
1199 } {} | |
1200 do_test without_rowid3-2.14.3.4 { | |
1201 catchsql { INSERT INTO t2 VALUES('x') } | |
1202 } {1 {no such table: main.t1}} | |
1203 do_test without_rowid3-2.14.3.5 { | |
1204 execsql { | |
1205 CREATE TABLE t1(x PRIMARY KEY) WITHOUT rowid; | |
1206 INSERT INTO t1 VALUES('x'); | |
1207 } | |
1208 execsql { INSERT INTO t2 VALUES('x') } | |
1209 } {} | |
1210 do_test without_rowid3-2.14.3.6 { | |
1211 catchsql { DROP TABLE t1 } | |
1212 } {1 {FOREIGN KEY constraint failed}} | |
1213 do_test without_rowid3-2.14.3.7 { | |
1214 execsql { | |
1215 DROP TABLE t2; | |
1216 DROP TABLE t1; | |
1217 } | |
1218 } {} | |
1219 do_test without_rowid3-2.14.3.8 { | |
1220 execsql { | |
1221 CREATE TABLE pp(x, y, PRIMARY KEY(x, y)) WITHOUT ROWID; | |
1222 CREATE TABLE cc(a, b, FOREIGN KEY(a, b) REFERENCES pp(x, z)); | |
1223 } | |
1224 catchsql { INSERT INTO cc VALUES(1, 2) } | |
1225 } {1 {foreign key mismatch - "cc" referencing "pp"}} | |
1226 do_test without_rowid3-2.14.3.9 { | |
1227 execsql { DROP TABLE cc } | |
1228 } {} | |
1229 do_test without_rowid3-2.14.3.10 { | |
1230 execsql { | |
1231 CREATE TABLE cc(a, b, | |
1232 FOREIGN KEY(a, b) REFERENCES pp DEFERRABLE INITIALLY DEFERRED | |
1233 ); | |
1234 } | |
1235 execsql { | |
1236 INSERT INTO pp VALUES('a', 'b'); | |
1237 INSERT INTO cc VALUES('a', 'b'); | |
1238 BEGIN; | |
1239 DROP TABLE pp; | |
1240 CREATE TABLE pp(a, b, c, PRIMARY KEY(b, c)) WITHOUT rowid; | |
1241 INSERT INTO pp VALUES(1, 'a', 'b'); | |
1242 COMMIT; | |
1243 } | |
1244 } {} | |
1245 do_test without_rowid3-2.14.3.11 { | |
1246 execsql { | |
1247 BEGIN; | |
1248 DROP TABLE cc; | |
1249 DROP TABLE pp; | |
1250 COMMIT; | |
1251 } | |
1252 } {} | |
1253 do_test without_rowid3-2.14.3.12 { | |
1254 execsql { | |
1255 CREATE TABLE b1(a, b); | |
1256 CREATE TABLE b2(a, b REFERENCES b1); | |
1257 DROP TABLE b1; | |
1258 } | |
1259 } {} | |
1260 do_test without_rowid3-2.14.3.13 { | |
1261 execsql { | |
1262 CREATE TABLE b3(a, b REFERENCES b2 DEFERRABLE INITIALLY DEFERRED); | |
1263 DROP TABLE b2; | |
1264 } | |
1265 } {} | |
1266 | |
1267 # Test that nothing goes wrong when dropping a table that refers to a view. | |
1268 # Or dropping a view that an existing FK (incorrectly) refers to. Or either | |
1269 # of the above scenarios with a virtual table. | |
1270 drop_all_tables | |
1271 do_test without_rowid3-2.14.4.1 { | |
1272 execsql { | |
1273 CREATE TABLE t1(x REFERENCES v); | |
1274 CREATE VIEW v AS SELECT * FROM t1; | |
1275 } | |
1276 } {} | |
1277 do_test without_rowid3-2.14.4.2 { | |
1278 execsql { | |
1279 DROP VIEW v; | |
1280 } | |
1281 } {} | |
1282 ifcapable vtab { | |
1283 register_echo_module db | |
1284 do_test without_rowid3-2.14.4.3 { | |
1285 execsql { CREATE VIRTUAL TABLE v USING echo(t1) } | |
1286 } {} | |
1287 do_test without_rowid3-2.14.4.2 { | |
1288 execsql { | |
1289 DROP TABLE v; | |
1290 } | |
1291 } {} | |
1292 } | |
1293 | |
1294 #------------------------------------------------------------------------- | |
1295 # The following tests, without_rowid3-15.*, test that unnecessary FK related sca
ns | |
1296 # and lookups are avoided when the constraint counters are zero. | |
1297 # | |
1298 drop_all_tables | |
1299 proc execsqlS {zSql} { | |
1300 set ::sqlite_search_count 0 | |
1301 set ::sqlite_found_count 0 | |
1302 set res [uplevel [list execsql $zSql]] | |
1303 concat [expr $::sqlite_found_count + $::sqlite_search_count] $res | |
1304 } | |
1305 do_test without_rowid3-15.1.1 { | |
1306 execsql { | |
1307 CREATE TABLE pp(a PRIMARY KEY, b) WITHOUT rowid; | |
1308 CREATE TABLE cc(x, y REFERENCES pp DEFERRABLE INITIALLY DEFERRED); | |
1309 INSERT INTO pp VALUES(1, 'one'); | |
1310 INSERT INTO pp VALUES(2, 'two'); | |
1311 INSERT INTO cc VALUES('neung', 1); | |
1312 INSERT INTO cc VALUES('song', 2); | |
1313 } | |
1314 } {} | |
1315 do_test without_rowid3-15.1.2 { | |
1316 execsqlS { INSERT INTO pp VALUES(3, 'three') } | |
1317 } {0} | |
1318 do_test without_rowid3-15.1.3 { | |
1319 execsql { | |
1320 BEGIN; | |
1321 INSERT INTO cc VALUES('see', 4); -- Violates deferred constraint | |
1322 } | |
1323 execsqlS { INSERT INTO pp VALUES(5, 'five') } | |
1324 } {2} | |
1325 do_test without_rowid3-15.1.4 { | |
1326 execsql { DELETE FROM cc WHERE x = 'see' } | |
1327 execsqlS { INSERT INTO pp VALUES(6, 'six') } | |
1328 } {0} | |
1329 do_test without_rowid3-15.1.5 { | |
1330 execsql COMMIT | |
1331 } {} | |
1332 do_test without_rowid3-15.1.6 { | |
1333 execsql BEGIN | |
1334 execsqlS { | |
1335 DELETE FROM cc WHERE x = 'neung'; | |
1336 ROLLBACK; | |
1337 } | |
1338 } {1} | |
1339 do_test without_rowid3-15.1.7 { | |
1340 execsql { | |
1341 BEGIN; | |
1342 DELETE FROM pp WHERE a = 2; | |
1343 } | |
1344 execsqlS { | |
1345 DELETE FROM cc WHERE x = 'neung'; | |
1346 ROLLBACK; | |
1347 } | |
1348 } {2} | |
1349 | |
1350 #------------------------------------------------------------------------- | |
1351 # This next block of tests, without_rowid3-16.*, test that rows that refer to | |
1352 # themselves may be inserted and deleted. | |
1353 # | |
1354 foreach {tn zSchema} { | |
1355 1 { CREATE TABLE self(a INTEGER PRIMARY KEY, b REFERENCES self(a)) | |
1356 WITHOUT rowid } | |
1357 2 { CREATE TABLE self(a PRIMARY KEY, b REFERENCES self(a)) WITHOUT rowid } | |
1358 3 { CREATE TABLE self(a UNIQUE, b INT PRIMARY KEY REFERENCES self(a)) | |
1359 WITHOUT rowid } | |
1360 } { | |
1361 drop_all_tables | |
1362 do_test without_rowid3-16.1.$tn.1 { | |
1363 execsql $zSchema | |
1364 execsql { INSERT INTO self VALUES(13, 13) } | |
1365 } {} | |
1366 do_test without_rowid3-16.1.$tn.2 { | |
1367 execsql { UPDATE self SET a = 14, b = 14 } | |
1368 } {} | |
1369 | |
1370 do_test without_rowid3-16.1.$tn.3 { | |
1371 catchsql { UPDATE self SET b = 15 } | |
1372 } {1 {FOREIGN KEY constraint failed}} | |
1373 | |
1374 do_test without_rowid3-16.1.$tn.4 { | |
1375 catchsql { UPDATE self SET a = 15 } | |
1376 } {1 {FOREIGN KEY constraint failed}} | |
1377 | |
1378 do_test without_rowid3-16.1.$tn.5 { | |
1379 catchsql { UPDATE self SET a = 15, b = 16 } | |
1380 } {1 {FOREIGN KEY constraint failed}} | |
1381 | |
1382 do_test without_rowid3-16.1.$tn.6 { | |
1383 catchsql { UPDATE self SET a = 17, b = 17 } | |
1384 } {0 {}} | |
1385 | |
1386 do_test without_rowid3-16.1.$tn.7 { | |
1387 execsql { DELETE FROM self } | |
1388 } {} | |
1389 do_test without_rowid3-16.1.$tn.8 { | |
1390 catchsql { INSERT INTO self VALUES(20, 21) } | |
1391 } {1 {FOREIGN KEY constraint failed}} | |
1392 } | |
1393 | |
1394 # Additional tests cases using multi-column self-referential | |
1395 # FOREIGN KEY constraints. | |
1396 # | |
1397 drop_all_tables | |
1398 do_execsql_test without_rowid3-16.4.1.1 { | |
1399 PRAGMA foreign_keys=ON; | |
1400 CREATE TABLE t1(a,b,c,d,e,f, | |
1401 UNIQUE (a,b), | |
1402 PRIMARY KEY (e,c), | |
1403 FOREIGN KEY (d,f) REFERENCES t1(e,c) | |
1404 ) WITHOUT rowid; | |
1405 INSERT INTO t1 VALUES(1,2,3,5,5,3); | |
1406 INSERT INTO t1 VALUES(2,3,4,6,6,4); | |
1407 INSERT INTO t1 VALUES('x','y',1.5,'fizzle','fizzle',1.5); | |
1408 SELECT *, '|' FROM t1 ORDER BY a, b; | |
1409 } {1 2 3 5 5 3 | 2 3 4 6 6 4 | x y 1.5 fizzle fizzle 1.5 |} | |
1410 | |
1411 do_execsql_test without_rowid3-16.4.1.2 { | |
1412 UPDATE t1 SET c=99, f=99 WHERE a=1; | |
1413 SELECT *, '|' FROM t1 ORDER BY a, b; | |
1414 } {1 2 99 5 5 99 | 2 3 4 6 6 4 | x y 1.5 fizzle fizzle 1.5 |} | |
1415 | |
1416 do_execsql_test without_rowid3-16.4.1.3 { | |
1417 UPDATE t1 SET e=876, d=876 WHERE a=2; | |
1418 SELECT *, '|' FROM t1 ORDER BY a, b; | |
1419 } {1 2 99 5 5 99 | 2 3 4 876 876 4 | x y 1.5 fizzle fizzle 1.5 |} | |
1420 | |
1421 do_test without_rowid3-16.4.1.4 { | |
1422 catchsql { | |
1423 UPDATE t1 SET c=11, e=22 WHERE a=1; | |
1424 } | |
1425 } {1 {FOREIGN KEY constraint failed}} | |
1426 | |
1427 do_test without_rowid3-16.4.1.5 { | |
1428 catchsql { | |
1429 UPDATE t1 SET d=11, f=22 WHERE a=1; | |
1430 } | |
1431 } {1 {FOREIGN KEY constraint failed}} | |
1432 | |
1433 do_execsql_test without_rowid3-16.4.1.6 { | |
1434 DELETE FROM t1 WHERE a=1; | |
1435 SELECT *, '|' FROM t1 ORDER BY a, b; | |
1436 } {2 3 4 876 876 4 | x y 1.5 fizzle fizzle 1.5 |} | |
1437 | |
1438 do_execsql_test without_rowid3-16.4.2.1 { | |
1439 DROP TABLE t1; | |
1440 CREATE TABLE t1(a,b,c,d,e,f, | |
1441 PRIMARY KEY (a,b), | |
1442 UNIQUE (e,c), | |
1443 FOREIGN KEY (d,f) REFERENCES t1(e,c) | |
1444 ) WITHOUT rowid; | |
1445 INSERT INTO t1 VALUES(1,2,3,5,5,3); | |
1446 INSERT INTO t1 VALUES(2,3,4,6,6,4); | |
1447 INSERT INTO t1 VALUES('x','y',1.5,'fizzle','fizzle',1.5); | |
1448 SELECT *, '|' FROM t1 ORDER BY a, b; | |
1449 } {1 2 3 5 5 3 | 2 3 4 6 6 4 | x y 1.5 fizzle fizzle 1.5 |} | |
1450 | |
1451 do_execsql_test without_rowid3-16.4.2.2 { | |
1452 UPDATE t1 SET c=99, f=99 WHERE a=1; | |
1453 SELECT *, '|' FROM t1 ORDER BY a, b; | |
1454 } {1 2 99 5 5 99 | 2 3 4 6 6 4 | x y 1.5 fizzle fizzle 1.5 |} | |
1455 | |
1456 do_execsql_test without_rowid3-16.4.2.3 { | |
1457 UPDATE t1 SET e=876, d=876 WHERE a=2; | |
1458 SELECT *, '|' FROM t1 ORDER BY a, b; | |
1459 } {1 2 99 5 5 99 | 2 3 4 876 876 4 | x y 1.5 fizzle fizzle 1.5 |} | |
1460 | |
1461 do_test without_rowid3-16.4.2.4 { | |
1462 catchsql { | |
1463 UPDATE t1 SET c=11, e=22 WHERE a=1; | |
1464 } | |
1465 } {1 {FOREIGN KEY constraint failed}} | |
1466 | |
1467 do_test without_rowid3-16.4.2.5 { | |
1468 catchsql { | |
1469 UPDATE t1 SET d=11, f=22 WHERE a=1; | |
1470 } | |
1471 } {1 {FOREIGN KEY constraint failed}} | |
1472 | |
1473 do_execsql_test without_rowid3-16.4.2.6 { | |
1474 DELETE FROM t1 WHERE a=1; | |
1475 SELECT *, '|' FROM t1 ORDER BY a, b; | |
1476 } {2 3 4 876 876 4 | x y 1.5 fizzle fizzle 1.5 |} | |
1477 | |
1478 | |
1479 #------------------------------------------------------------------------- | |
1480 # This next block of tests, without_rowid3-17.*, tests that if "PRAGMA count_cha
nges" | |
1481 # is turned on statements that violate immediate FK constraints return | |
1482 # SQLITE_CONSTRAINT immediately, not after returning a number of rows. | |
1483 # Whereas statements that violate deferred FK constraints return the number | |
1484 # of rows before failing. | |
1485 # | |
1486 # Also test that rows modified by FK actions are not counted in either the | |
1487 # returned row count or the values returned by sqlite3_changes(). Like | |
1488 # trigger related changes, they are included in sqlite3_total_changes() though. | |
1489 # | |
1490 drop_all_tables | |
1491 do_test without_rowid3-17.1.1 { | |
1492 execsql { PRAGMA count_changes = 1 } | |
1493 execsql { | |
1494 CREATE TABLE one(a, b, c, UNIQUE(b, c)); | |
1495 CREATE TABLE two(d, e, f, FOREIGN KEY(e, f) REFERENCES one(b, c)); | |
1496 INSERT INTO one VALUES(1, 2, 3); | |
1497 } | |
1498 } {1} | |
1499 do_test without_rowid3-17.1.2 { | |
1500 set STMT [sqlite3_prepare_v2 db "INSERT INTO two VALUES(4, 5, 6)" -1 dummy] | |
1501 sqlite3_step $STMT | |
1502 } {SQLITE_CONSTRAINT} | |
1503 verify_ex_errcode without_rowid3-17.1.2b SQLITE_CONSTRAINT_FOREIGNKEY | |
1504 ifcapable autoreset { | |
1505 do_test without_rowid3-17.1.3 { | |
1506 sqlite3_step $STMT | |
1507 } {SQLITE_CONSTRAINT} | |
1508 verify_ex_errcode without_rowid3-17.1.3b SQLITE_CONSTRAINT_FOREIGNKEY | |
1509 } else { | |
1510 do_test without_rowid3-17.1.3 { | |
1511 sqlite3_step $STMT | |
1512 } {SQLITE_MISUSE} | |
1513 } | |
1514 do_test without_rowid3-17.1.4 { | |
1515 sqlite3_finalize $STMT | |
1516 } {SQLITE_CONSTRAINT} | |
1517 verify_ex_errcode without_rowid3-17.1.4b SQLITE_CONSTRAINT_FOREIGNKEY | |
1518 do_test without_rowid3-17.1.5 { | |
1519 execsql { | |
1520 INSERT INTO one VALUES(2, 3, 4); | |
1521 INSERT INTO one VALUES(3, 4, 5); | |
1522 INSERT INTO two VALUES(1, 2, 3); | |
1523 INSERT INTO two VALUES(2, 3, 4); | |
1524 INSERT INTO two VALUES(3, 4, 5); | |
1525 } | |
1526 } {1 1 1 1 1} | |
1527 do_test without_rowid3-17.1.6 { | |
1528 catchsql { | |
1529 BEGIN; | |
1530 INSERT INTO one VALUES(0, 0, 0); | |
1531 UPDATE two SET e=e+1, f=f+1; | |
1532 } | |
1533 } {1 {FOREIGN KEY constraint failed}} | |
1534 do_test without_rowid3-17.1.7 { | |
1535 execsql { SELECT * FROM one } | |
1536 } {1 2 3 2 3 4 3 4 5 0 0 0} | |
1537 do_test without_rowid3-17.1.8 { | |
1538 execsql { SELECT * FROM two } | |
1539 } {1 2 3 2 3 4 3 4 5} | |
1540 do_test without_rowid3-17.1.9 { | |
1541 execsql COMMIT | |
1542 } {} | |
1543 do_test without_rowid3-17.1.10 { | |
1544 execsql { | |
1545 CREATE TABLE three( | |
1546 g, h, i, | |
1547 FOREIGN KEY(h, i) REFERENCES one(b, c) DEFERRABLE INITIALLY DEFERRED | |
1548 ); | |
1549 } | |
1550 } {} | |
1551 do_test without_rowid3-17.1.11 { | |
1552 set STMT [sqlite3_prepare_v2 db "INSERT INTO three VALUES(7, 8, 9)" -1 dummy] | |
1553 sqlite3_step $STMT | |
1554 } {SQLITE_ROW} | |
1555 do_test without_rowid3-17.1.12 { | |
1556 sqlite3_column_text $STMT 0 | |
1557 } {1} | |
1558 do_test without_rowid3-17.1.13 { | |
1559 sqlite3_step $STMT | |
1560 } {SQLITE_CONSTRAINT} | |
1561 verify_ex_errcode without_rowid3-17.1.13b SQLITE_CONSTRAINT_FOREIGNKEY | |
1562 do_test without_rowid3-17.1.14 { | |
1563 sqlite3_finalize $STMT | |
1564 } {SQLITE_CONSTRAINT} | |
1565 verify_ex_errcode without_rowid3-17.1.14b SQLITE_CONSTRAINT_FOREIGNKEY | |
1566 | |
1567 drop_all_tables | |
1568 do_test without_rowid3-17.2.1 { | |
1569 execsql { | |
1570 CREATE TABLE high("a'b!" PRIMARY KEY, b) WITHOUT rowid; | |
1571 CREATE TABLE low( | |
1572 c, | |
1573 "d&6" REFERENCES high ON UPDATE CASCADE ON DELETE CASCADE | |
1574 ); | |
1575 } | |
1576 } {} | |
1577 do_test without_rowid3-17.2.2 { | |
1578 execsql { | |
1579 INSERT INTO high VALUES('a', 'b'); | |
1580 INSERT INTO low VALUES('b', 'a'); | |
1581 } | |
1582 db changes | |
1583 } {1} | |
1584 set nTotal [db total_changes] | |
1585 do_test without_rowid3-17.2.3 { | |
1586 execsql { UPDATE high SET "a'b!" = 'c' } | |
1587 } {1} | |
1588 do_test without_rowid3-17.2.4 { | |
1589 db changes | |
1590 } {1} | |
1591 do_test without_rowid3-17.2.5 { | |
1592 expr [db total_changes] - $nTotal | |
1593 } {2} | |
1594 do_test without_rowid3-17.2.6 { | |
1595 execsql { SELECT * FROM high ; SELECT * FROM low } | |
1596 } {c b b c} | |
1597 do_test without_rowid3-17.2.7 { | |
1598 execsql { DELETE FROM high } | |
1599 } {1} | |
1600 do_test without_rowid3-17.2.8 { | |
1601 db changes | |
1602 } {1} | |
1603 do_test without_rowid3-17.2.9 { | |
1604 expr [db total_changes] - $nTotal | |
1605 } {4} | |
1606 do_test without_rowid3-17.2.10 { | |
1607 execsql { SELECT * FROM high ; SELECT * FROM low } | |
1608 } {} | |
1609 execsql { PRAGMA count_changes = 0 } | |
1610 | |
1611 #------------------------------------------------------------------------- | |
1612 # Test that the authorization callback works. | |
1613 # | |
1614 | |
1615 ifcapable auth { | |
1616 do_test without_rowid3-18.1 { | |
1617 execsql { | |
1618 CREATE TABLE long(a, b PRIMARY KEY, c) WITHOUT rowid; | |
1619 CREATE TABLE short(d, e, f REFERENCES long); | |
1620 CREATE TABLE mid(g, h, i REFERENCES long DEFERRABLE INITIALLY DEFERRED); | |
1621 } | |
1622 } {} | |
1623 | |
1624 proc auth {args} {eval lappend ::authargs [lrange $args 0 4]; return SQLITE_OK
} | |
1625 db auth auth | |
1626 | |
1627 # An insert on the parent table must read the child key of any deferred | |
1628 # foreign key constraints. But not the child key of immediate constraints. | |
1629 set authargs {} | |
1630 do_test without_rowid3-18.2 { | |
1631 execsql { INSERT INTO long VALUES(1, 2, 3) } | |
1632 set authargs | |
1633 } {SQLITE_INSERT long {} main {} SQLITE_READ mid i main {}} | |
1634 | |
1635 # An insert on the child table of an immediate constraint must read the | |
1636 # parent key columns (to see if it is a violation or not). | |
1637 set authargs {} | |
1638 do_test without_rowid3-18.3 { | |
1639 execsql { INSERT INTO short VALUES(1, 3, 2) } | |
1640 set authargs | |
1641 } {SQLITE_INSERT short {} main {} SQLITE_READ long b main {}} | |
1642 | |
1643 # As must an insert on the child table of a deferred constraint. | |
1644 set authargs {} | |
1645 do_test without_rowid3-18.4 { | |
1646 execsql { INSERT INTO mid VALUES(1, 3, 2) } | |
1647 set authargs | |
1648 } {SQLITE_INSERT mid {} main {} SQLITE_READ long b main {}} | |
1649 | |
1650 do_test without_rowid3-18.5 { | |
1651 execsql { | |
1652 CREATE TABLE nought(a, b PRIMARY KEY, c) WITHOUT rowid; | |
1653 CREATE TABLE cross(d, e, f, | |
1654 FOREIGN KEY(e) REFERENCES nought(b) ON UPDATE CASCADE | |
1655 ); | |
1656 } | |
1657 execsql { INSERT INTO nought VALUES(2, 1, 2) } | |
1658 execsql { INSERT INTO cross VALUES(0, 1, 0) } | |
1659 set authargs [list] | |
1660 execsql { UPDATE nought SET b = 5 } | |
1661 set authargs | |
1662 } {SQLITE_UPDATE nought b main {} SQLITE_READ cross e main {} SQLITE_READ cros
s e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_REA
D nought b main {} SQLITE_UPDATE cross e main {} SQLITE_READ nought b main {} SQ
LITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main
{}} | |
1663 | |
1664 do_test without_rowid3-18.6 { | |
1665 execsql {SELECT * FROM cross} | |
1666 } {0 5 0} | |
1667 | |
1668 do_test without_rowid3-18.7 { | |
1669 execsql { | |
1670 CREATE TABLE one(a INT PRIMARY KEY, b) WITHOUT rowid; | |
1671 CREATE TABLE two(b, c REFERENCES one); | |
1672 INSERT INTO one VALUES(101, 102); | |
1673 } | |
1674 set authargs [list] | |
1675 execsql { INSERT INTO two VALUES(100, 101); } | |
1676 set authargs | |
1677 } {SQLITE_INSERT two {} main {} SQLITE_READ one a main {}} | |
1678 | |
1679 # Return SQLITE_IGNORE to requests to read from the parent table. This | |
1680 # causes inserts of non-NULL keys into the child table to fail. | |
1681 # | |
1682 rename auth {} | |
1683 proc auth {args} { | |
1684 if {[lindex $args 1] == "long"} {return SQLITE_IGNORE} | |
1685 return SQLITE_OK | |
1686 } | |
1687 do_test without_rowid3-18.8 { | |
1688 catchsql { INSERT INTO short VALUES(1, 3, 2) } | |
1689 } {1 {FOREIGN KEY constraint failed}} | |
1690 do_test without_rowid3-18.9 { | |
1691 execsql { INSERT INTO short VALUES(1, 3, NULL) } | |
1692 } {} | |
1693 do_test without_rowid3-18.10 { | |
1694 execsql { SELECT * FROM short } | |
1695 } {1 3 2 1 3 {}} | |
1696 do_test without_rowid3-18.11 { | |
1697 catchsql { UPDATE short SET f = 2 WHERE f IS NULL } | |
1698 } {1 {FOREIGN KEY constraint failed}} | |
1699 | |
1700 db auth {} | |
1701 unset authargs | |
1702 } | |
1703 | |
1704 | |
1705 do_test without_rowid3-19.1 { | |
1706 execsql { | |
1707 CREATE TABLE main(id INT PRIMARY KEY) WITHOUT rowid; | |
1708 CREATE TABLE sub(id INT REFERENCES main(id)); | |
1709 INSERT INTO main VALUES(1); | |
1710 INSERT INTO main VALUES(2); | |
1711 INSERT INTO sub VALUES(2); | |
1712 } | |
1713 } {} | |
1714 do_test without_rowid3-19.2 { | |
1715 set S [sqlite3_prepare_v2 db "DELETE FROM main WHERE id = ?" -1 dummy] | |
1716 sqlite3_bind_int $S 1 2 | |
1717 sqlite3_step $S | |
1718 } {SQLITE_CONSTRAINT} | |
1719 verify_ex_errcode without_rowid3-19.2b SQLITE_CONSTRAINT_FOREIGNKEY | |
1720 do_test without_rowid3-19.3 { | |
1721 sqlite3_reset $S | |
1722 } {SQLITE_CONSTRAINT} | |
1723 verify_ex_errcode without_rowid3-19.3b SQLITE_CONSTRAINT_FOREIGNKEY | |
1724 do_test without_rowid3-19.4 { | |
1725 sqlite3_bind_int $S 1 1 | |
1726 sqlite3_step $S | |
1727 } {SQLITE_DONE} | |
1728 do_test without_rowid3-19.4 { | |
1729 sqlite3_finalize $S | |
1730 } {SQLITE_OK} | |
1731 | |
1732 drop_all_tables | |
1733 do_test without_rowid3-20.1 { | |
1734 execsql { | |
1735 CREATE TABLE pp(a PRIMARY KEY, b) WITHOUT rowid; | |
1736 CREATE TABLE cc(c PRIMARY KEY, d REFERENCES pp) WITHOUT rowid; | |
1737 } | |
1738 } {} | |
1739 | |
1740 foreach {tn insert} { | |
1741 1 "INSERT" | |
1742 2 "INSERT OR IGNORE" | |
1743 3 "INSERT OR ABORT" | |
1744 4 "INSERT OR ROLLBACK" | |
1745 5 "INSERT OR REPLACE" | |
1746 6 "INSERT OR FAIL" | |
1747 } { | |
1748 do_test without_rowid3-20.2.$tn.1 { | |
1749 catchsql "$insert INTO cc VALUES(1, 2)" | |
1750 } {1 {FOREIGN KEY constraint failed}} | |
1751 do_test without_rowid3-20.2.$tn.2 { | |
1752 execsql { SELECT * FROM cc } | |
1753 } {} | |
1754 do_test without_rowid3-20.2.$tn.3 { | |
1755 execsql { | |
1756 BEGIN; | |
1757 INSERT INTO pp VALUES(2, 'two'); | |
1758 INSERT INTO cc VALUES(1, 2); | |
1759 } | |
1760 catchsql "$insert INTO cc VALUES(3, 4)" | |
1761 } {1 {FOREIGN KEY constraint failed}} | |
1762 do_test without_rowid3-20.2.$tn.4 { | |
1763 execsql { COMMIT ; SELECT * FROM cc } | |
1764 } {1 2} | |
1765 do_test without_rowid3-20.2.$tn.5 { | |
1766 execsql { DELETE FROM cc ; DELETE FROM pp } | |
1767 } {} | |
1768 } | |
1769 | |
1770 foreach {tn update} { | |
1771 1 "UPDATE" | |
1772 2 "UPDATE OR IGNORE" | |
1773 3 "UPDATE OR ABORT" | |
1774 4 "UPDATE OR ROLLBACK" | |
1775 5 "UPDATE OR REPLACE" | |
1776 6 "UPDATE OR FAIL" | |
1777 } { | |
1778 do_test without_rowid3-20.3.$tn.1 { | |
1779 execsql { | |
1780 INSERT INTO pp VALUES(2, 'two'); | |
1781 INSERT INTO cc VALUES(1, 2); | |
1782 } | |
1783 } {} | |
1784 do_test without_rowid3-20.3.$tn.2 { | |
1785 catchsql "$update pp SET a = 1" | |
1786 } {1 {FOREIGN KEY constraint failed}} | |
1787 do_test without_rowid3-20.3.$tn.3 { | |
1788 execsql { SELECT * FROM pp } | |
1789 } {2 two} | |
1790 do_test without_rowid3-20.3.$tn.4 { | |
1791 catchsql "$update cc SET d = 1" | |
1792 } {1 {FOREIGN KEY constraint failed}} | |
1793 do_test without_rowid3-20.3.$tn.5 { | |
1794 execsql { SELECT * FROM cc } | |
1795 } {1 2} | |
1796 do_test without_rowid3-20.3.$tn.6 { | |
1797 execsql { | |
1798 BEGIN; | |
1799 INSERT INTO pp VALUES(3, 'three'); | |
1800 } | |
1801 catchsql "$update pp SET a = 1 WHERE a = 2" | |
1802 } {1 {FOREIGN KEY constraint failed}} | |
1803 do_test without_rowid3-20.3.$tn.7 { | |
1804 execsql { COMMIT ; SELECT * FROM pp } | |
1805 } {2 two 3 three} | |
1806 do_test without_rowid3-20.3.$tn.8 { | |
1807 execsql { | |
1808 BEGIN; | |
1809 INSERT INTO cc VALUES(2, 2); | |
1810 } | |
1811 catchsql "$update cc SET d = 1 WHERE c = 1" | |
1812 } {1 {FOREIGN KEY constraint failed}} | |
1813 do_test without_rowid3-20.3.$tn.9 { | |
1814 execsql { COMMIT ; SELECT * FROM cc } | |
1815 } {1 2 2 2} | |
1816 do_test without_rowid3-20.3.$tn.10 { | |
1817 execsql { DELETE FROM cc ; DELETE FROM pp } | |
1818 } {} | |
1819 } | |
1820 | |
1821 #------------------------------------------------------------------------- | |
1822 # The following block of tests, those prefixed with "without_rowid3-genfkey.", | |
1823 # are the same tests that were used to test the ".genfkey" command provided | |
1824 # by the shell tool. So these tests show that the built-in foreign key | |
1825 # implementation is more or less compatible with the triggers generated | |
1826 # by genfkey. | |
1827 # | |
1828 drop_all_tables | |
1829 do_test without_rowid3-genfkey.1.1 { | |
1830 execsql { | |
1831 CREATE TABLE t1(a INT PRIMARY KEY, b, c, UNIQUE(b, c)) WITHOUT rowid; | |
1832 CREATE TABLE t2(e REFERENCES t1, f); | |
1833 CREATE TABLE t3(g, h, i, FOREIGN KEY (h, i) REFERENCES t1(b, c)); | |
1834 } | |
1835 } {} | |
1836 do_test without_rowid3-genfkey.1.2 { | |
1837 catchsql { INSERT INTO t2 VALUES(1, 2) } | |
1838 } {1 {FOREIGN KEY constraint failed}} | |
1839 do_test without_rowid3-genfkey.1.3 { | |
1840 execsql { | |
1841 INSERT INTO t1 VALUES(1, 2, 3); | |
1842 INSERT INTO t2 VALUES(1, 2); | |
1843 } | |
1844 } {} | |
1845 do_test without_rowid3-genfkey.1.4 { | |
1846 execsql { INSERT INTO t2 VALUES(NULL, 3) } | |
1847 } {} | |
1848 do_test without_rowid3-genfkey.1.5 { | |
1849 catchsql { UPDATE t2 SET e = 5 WHERE e IS NULL } | |
1850 } {1 {FOREIGN KEY constraint failed}} | |
1851 do_test without_rowid3-genfkey.1.6 { | |
1852 execsql { UPDATE t2 SET e = 1 WHERE e IS NULL } | |
1853 } {} | |
1854 do_test without_rowid3-genfkey.1.7 { | |
1855 execsql { UPDATE t2 SET e = NULL WHERE f = 3 } | |
1856 } {} | |
1857 do_test without_rowid3-genfkey.1.8 { | |
1858 catchsql { UPDATE t1 SET a = 10 } | |
1859 } {1 {FOREIGN KEY constraint failed}} | |
1860 do_test without_rowid3-genfkey.1.9 { | |
1861 catchsql { UPDATE t1 SET a = NULL } | |
1862 } {1 {NOT NULL constraint failed: t1.a}} | |
1863 do_test without_rowid3-genfkey.1.10 { | |
1864 catchsql { DELETE FROM t1 } | |
1865 } {1 {FOREIGN KEY constraint failed}} | |
1866 do_test without_rowid3-genfkey.1.11 { | |
1867 execsql { UPDATE t2 SET e = NULL } | |
1868 } {} | |
1869 do_test without_rowid3-genfkey.1.12 { | |
1870 execsql { | |
1871 UPDATE t1 SET a = 10; | |
1872 DELETE FROM t1; | |
1873 DELETE FROM t2; | |
1874 } | |
1875 } {} | |
1876 do_test without_rowid3-genfkey.1.13 { | |
1877 execsql { | |
1878 INSERT INTO t3 VALUES(1, NULL, NULL); | |
1879 INSERT INTO t3 VALUES(1, 2, NULL); | |
1880 INSERT INTO t3 VALUES(1, NULL, 3); | |
1881 } | |
1882 } {} | |
1883 do_test without_rowid3-genfkey.1.14 { | |
1884 catchsql { INSERT INTO t3 VALUES(3, 1, 4) } | |
1885 } {1 {FOREIGN KEY constraint failed}} | |
1886 do_test without_rowid3-genfkey.1.15 { | |
1887 execsql { | |
1888 INSERT INTO t1 VALUES(1, 1, 4); | |
1889 INSERT INTO t3 VALUES(3, 1, 4); | |
1890 } | |
1891 } {} | |
1892 do_test without_rowid3-genfkey.1.16 { | |
1893 catchsql { DELETE FROM t1 } | |
1894 } {1 {FOREIGN KEY constraint failed}} | |
1895 do_test without_rowid3-genfkey.1.17 { | |
1896 catchsql { UPDATE t1 SET b = 10} | |
1897 } {1 {FOREIGN KEY constraint failed}} | |
1898 do_test without_rowid3-genfkey.1.18 { | |
1899 execsql { UPDATE t1 SET a = 10} | |
1900 } {} | |
1901 do_test without_rowid3-genfkey.1.19 { | |
1902 catchsql { UPDATE t3 SET h = 'hello' WHERE i = 3} | |
1903 } {1 {FOREIGN KEY constraint failed}} | |
1904 | |
1905 drop_all_tables | |
1906 do_test without_rowid3-genfkey.2.1 { | |
1907 execsql { | |
1908 CREATE TABLE t1(a INT PRIMARY KEY, b, c, UNIQUE(b, c)) WITHOUT rowid; | |
1909 CREATE TABLE t2(e REFERENCES t1 ON UPDATE CASCADE ON DELETE CASCADE, f); | |
1910 CREATE TABLE t3(g, h, i, | |
1911 FOREIGN KEY (h, i) | |
1912 REFERENCES t1(b, c) ON UPDATE CASCADE ON DELETE CASCADE | |
1913 ); | |
1914 } | |
1915 } {} | |
1916 do_test without_rowid3-genfkey.2.2 { | |
1917 execsql { | |
1918 INSERT INTO t1 VALUES(1, 2, 3); | |
1919 INSERT INTO t1 VALUES(4, 5, 6); | |
1920 INSERT INTO t2 VALUES(1, 'one'); | |
1921 INSERT INTO t2 VALUES(4, 'four'); | |
1922 } | |
1923 } {} | |
1924 do_test without_rowid3-genfkey.2.3 { | |
1925 execsql { | |
1926 UPDATE t1 SET a = 2 WHERE a = 1; | |
1927 SELECT * FROM t2; | |
1928 } | |
1929 } {2 one 4 four} | |
1930 do_test without_rowid3-genfkey.2.4 { | |
1931 execsql { | |
1932 DELETE FROM t1 WHERE a = 4; | |
1933 SELECT * FROM t2; | |
1934 } | |
1935 } {2 one} | |
1936 | |
1937 do_test without_rowid3-genfkey.2.5 { | |
1938 execsql { | |
1939 INSERT INTO t3 VALUES('hello', 2, 3); | |
1940 UPDATE t1 SET c = 2; | |
1941 SELECT * FROM t3; | |
1942 } | |
1943 } {hello 2 2} | |
1944 do_test without_rowid3-genfkey.2.6 { | |
1945 execsql { | |
1946 DELETE FROM t1; | |
1947 SELECT * FROM t3; | |
1948 } | |
1949 } {} | |
1950 | |
1951 drop_all_tables | |
1952 do_test without_rowid3-genfkey.3.1 { | |
1953 execsql { | |
1954 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(c, b)) WITHOUT rowid; | |
1955 CREATE TABLE t2(e REFERENCES t1 ON UPDATE SET NULL ON DELETE SET NULL, f); | |
1956 CREATE TABLE t3(g, h, i, | |
1957 FOREIGN KEY (h, i) | |
1958 REFERENCES t1(b, c) ON UPDATE SET NULL ON DELETE SET NULL | |
1959 ); | |
1960 } | |
1961 } {} | |
1962 do_test without_rowid3-genfkey.3.2 { | |
1963 execsql { | |
1964 INSERT INTO t1 VALUES(1, 2, 3); | |
1965 INSERT INTO t1 VALUES(4, 5, 6); | |
1966 INSERT INTO t2 VALUES(1, 'one'); | |
1967 INSERT INTO t2 VALUES(4, 'four'); | |
1968 } | |
1969 } {} | |
1970 do_test without_rowid3-genfkey.3.3 { | |
1971 execsql { | |
1972 UPDATE t1 SET a = 2 WHERE a = 1; | |
1973 SELECT * FROM t2; | |
1974 } | |
1975 } {{} one 4 four} | |
1976 do_test without_rowid3-genfkey.3.4 { | |
1977 execsql { | |
1978 DELETE FROM t1 WHERE a = 4; | |
1979 SELECT * FROM t2; | |
1980 } | |
1981 } {{} one {} four} | |
1982 do_test without_rowid3-genfkey.3.5 { | |
1983 execsql { | |
1984 INSERT INTO t3 VALUES('hello', 2, 3); | |
1985 UPDATE t1 SET c = 2; | |
1986 SELECT * FROM t3; | |
1987 } | |
1988 } {hello {} {}} | |
1989 do_test without_rowid3-genfkey.3.6 { | |
1990 execsql { | |
1991 UPDATE t3 SET h = 2, i = 2; | |
1992 DELETE FROM t1; | |
1993 SELECT * FROM t3; | |
1994 } | |
1995 } {hello {} {}} | |
1996 | |
1997 #------------------------------------------------------------------------- | |
1998 # Verify that ticket dd08e5a988d00decc4a543daa8dbbfab9c577ad8 has been | |
1999 # fixed. | |
2000 # | |
2001 do_test without_rowid3-dd08e5.1.1 { | |
2002 execsql { | |
2003 PRAGMA foreign_keys=ON; | |
2004 CREATE TABLE tdd08(a INTEGER PRIMARY KEY, b) WITHOUT rowid; | |
2005 CREATE UNIQUE INDEX idd08 ON tdd08(a,b); | |
2006 INSERT INTO tdd08 VALUES(200,300); | |
2007 | |
2008 CREATE TABLE tdd08_b(w,x,y, FOREIGN KEY(x,y) REFERENCES tdd08(a,b)); | |
2009 INSERT INTO tdd08_b VALUES(100,200,300); | |
2010 } | |
2011 } {} | |
2012 do_test without_rowid3-dd08e5.1.2 { | |
2013 catchsql { | |
2014 DELETE FROM tdd08; | |
2015 } | |
2016 } {1 {FOREIGN KEY constraint failed}} | |
2017 do_test without_rowid3-dd08e5.1.3 { | |
2018 execsql { | |
2019 SELECT * FROM tdd08; | |
2020 } | |
2021 } {200 300} | |
2022 do_test without_rowid3-dd08e5.1.4 { | |
2023 catchsql { | |
2024 INSERT INTO tdd08_b VALUES(400,500,300); | |
2025 } | |
2026 } {1 {FOREIGN KEY constraint failed}} | |
2027 do_test without_rowid3-dd08e5.1.5 { | |
2028 catchsql { | |
2029 UPDATE tdd08_b SET x=x+1; | |
2030 } | |
2031 } {1 {FOREIGN KEY constraint failed}} | |
2032 do_test without_rowid3-dd08e5.1.6 { | |
2033 catchsql { | |
2034 UPDATE tdd08 SET a=a+1; | |
2035 } | |
2036 } {1 {FOREIGN KEY constraint failed}} | |
2037 | |
2038 #------------------------------------------------------------------------- | |
2039 # Verify that ticket ce7c133ea6cc9ccdc1a60d80441f80b6180f5eba | |
2040 # fixed. | |
2041 # | |
2042 do_test without_rowid3-ce7c13.1.1 { | |
2043 execsql { | |
2044 CREATE TABLE tce71(a INTEGER PRIMARY KEY, b) WITHOUT rowid; | |
2045 CREATE UNIQUE INDEX ice71 ON tce71(a,b); | |
2046 INSERT INTO tce71 VALUES(100,200); | |
2047 CREATE TABLE tce72(w, x, y, FOREIGN KEY(x,y) REFERENCES tce71(a,b)); | |
2048 INSERT INTO tce72 VALUES(300,100,200); | |
2049 UPDATE tce71 set b = 200 where a = 100; | |
2050 SELECT * FROM tce71, tce72; | |
2051 } | |
2052 } {100 200 300 100 200} | |
2053 do_test without_rowid3-ce7c13.1.2 { | |
2054 catchsql { | |
2055 UPDATE tce71 set b = 201 where a = 100; | |
2056 } | |
2057 } {1 {FOREIGN KEY constraint failed}} | |
2058 do_test without_rowid3-ce7c13.1.3 { | |
2059 catchsql { | |
2060 UPDATE tce71 set a = 101 where a = 100; | |
2061 } | |
2062 } {1 {FOREIGN KEY constraint failed}} | |
2063 do_test without_rowid3-ce7c13.1.4 { | |
2064 execsql { | |
2065 CREATE TABLE tce73(a INTEGER PRIMARY KEY, b, UNIQUE(a,b)) WITHOUT rowid; | |
2066 INSERT INTO tce73 VALUES(100,200); | |
2067 CREATE TABLE tce74(w, x, y, FOREIGN KEY(x,y) REFERENCES tce73(a,b)); | |
2068 INSERT INTO tce74 VALUES(300,100,200); | |
2069 UPDATE tce73 set b = 200 where a = 100; | |
2070 SELECT * FROM tce73, tce74; | |
2071 } | |
2072 } {100 200 300 100 200} | |
2073 do_test without_rowid3-ce7c13.1.5 { | |
2074 catchsql { | |
2075 UPDATE tce73 set b = 201 where a = 100; | |
2076 } | |
2077 } {1 {FOREIGN KEY constraint failed}} | |
2078 do_test without_rowid3-ce7c13.1.6 { | |
2079 catchsql { | |
2080 UPDATE tce73 set a = 101 where a = 100; | |
2081 } | |
2082 } {1 {FOREIGN KEY constraint failed}} | |
2083 | |
2084 finish_test | |
OLD | NEW |