xref: /sqlite-3.40.0/test/without_rowid3.test (revision 92e21ef0)
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
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20ifcapable {!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 triggers
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) table.
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 REPLACED 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 with
73#             FK constraint processing.
74#
75# without_rowid3-18.*: Test that the authorization callback is invoked when processing
76#             FK constraints.
77#
78# without_rowid3-20.*: Test that ON CONFLICT clauses specified as part of statements
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 dd08e5a988d00decc4a543daa8d
85#                  has been fixed.
86#
87
88
89execsql { PRAGMA foreign_keys = on }
90
91set 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
107set 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
146do_test without_rowid3-1.1.0 {
147  execsql [string map {/D/ {}} $FkeySimpleSchema]
148} {}
149foreach {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}
158drop_all_tables
159
160do_test without_rowid3-1.2.0 {
161  execsql [string map {/D/ {DEFERRABLE INITIALLY DEFERRED}} $FkeySimpleSchema]
162} {}
163foreach {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}
172drop_all_tables
173
174do_test without_rowid3-1.3.0 {
175  execsql [string map {/D/ {}} $FkeySimpleSchema]
176  execsql { PRAGMA count_changes = 1 }
177} {}
178foreach {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}
188execsql { PRAGMA count_changes = 0 }
189drop_all_tables
190
191do_test without_rowid3-1.4.0 {
192  execsql [string map {/D/ {}} $FkeySimpleSchema]
193  execsql { PRAGMA count_changes = 1 }
194} {}
195foreach {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}
201execsql { PRAGMA count_changes = 0 }
202drop_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.
207do_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}
216do_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.
221drop_all_tables
222do_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}
232do_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.
237drop_all_tables
238do_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.
250drop_all_tables
251do_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}}
259do_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#
272proc 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
286without_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
297without_rowid3-2-test 1  0 "INSERT INTO node VALUES(1, 0)"       FKV
298without_rowid3-2-test 2  0 "BEGIN"
299without_rowid3-2-test 3  1   "INSERT INTO node VALUES(1, 0)"
300without_rowid3-2-test 4  0   "UPDATE node SET parent = NULL"
301without_rowid3-2-test 5  0 "COMMIT"
302without_rowid3-2-test 6  0 "SELECT * FROM node" {1 {}}
303
304without_rowid3-2-test 7  0 "BEGIN"
305without_rowid3-2-test 8  1   "INSERT INTO leaf VALUES('a', 2)"
306without_rowid3-2-test 9  1   "INSERT INTO node VALUES(2, 0)"
307without_rowid3-2-test 10 0   "UPDATE node SET parent = 1 WHERE nodeid = 2"
308without_rowid3-2-test 11 0 "COMMIT"
309without_rowid3-2-test 12 0 "SELECT * FROM node" {1 {} 2 1}
310without_rowid3-2-test 13 0 "SELECT * FROM leaf" {a 2}
311
312without_rowid3-2-test 14 0 "BEGIN"
313without_rowid3-2-test 15 1   "DELETE FROM node WHERE nodeid = 2"
314without_rowid3-2-test 16 0   "INSERT INTO node VALUES(2, NULL)"
315without_rowid3-2-test 17 0 "COMMIT"
316without_rowid3-2-test 18 0 "SELECT * FROM node" {1 {} 2 {}}
317without_rowid3-2-test 19 0 "SELECT * FROM leaf" {a 2}
318
319without_rowid3-2-test 20 0 "BEGIN"
320without_rowid3-2-test 21 0   "INSERT INTO leaf VALUES('b', 1)"
321without_rowid3-2-test 22 0   "SAVEPOINT save"
322without_rowid3-2-test 23 0     "DELETE FROM node WHERE nodeid = 1"
323without_rowid3-2-test 24 0   "ROLLBACK TO save"
324without_rowid3-2-test 25 0 "COMMIT"
325without_rowid3-2-test 26 0 "SELECT * FROM node" {1 {} 2 {}}
326without_rowid3-2-test 27 0 "SELECT * FROM leaf" {a 2 b 1}
327
328without_rowid3-2-test 28 0 "BEGIN"
329without_rowid3-2-test 29 0   "INSERT INTO leaf VALUES('c', 1)"
330without_rowid3-2-test 30 0   "SAVEPOINT save"
331without_rowid3-2-test 31 0     "DELETE FROM node WHERE nodeid = 1"
332without_rowid3-2-test 32 1   "RELEASE save"
333without_rowid3-2-test 33 1   "DELETE FROM leaf WHERE cellid = 'b'"
334without_rowid3-2-test 34 0   "DELETE FROM leaf WHERE cellid = 'c'"
335without_rowid3-2-test 35 0 "COMMIT"
336without_rowid3-2-test 36 0 "SELECT * FROM node" {2 {}}
337without_rowid3-2-test 37 0 "SELECT * FROM leaf" {a 2}
338
339without_rowid3-2-test 38 0 "SAVEPOINT outer"
340without_rowid3-2-test 39 1   "INSERT INTO leaf VALUES('d', 3)"
341without_rowid3-2-test 40 1 "RELEASE outer"    FKV
342without_rowid3-2-test 41 1   "INSERT INTO leaf VALUES('e', 3)"
343without_rowid3-2-test 42 0   "INSERT INTO node VALUES(3, 2)"
344without_rowid3-2-test 43 0 "RELEASE outer"
345
346without_rowid3-2-test 44 0 "SAVEPOINT outer"
347without_rowid3-2-test 45 1   "DELETE FROM node WHERE nodeid=3"
348without_rowid3-2-test 47 0   "INSERT INTO node VALUES(3, 2)"
349without_rowid3-2-test 48 0 "ROLLBACK TO outer"
350without_rowid3-2-test 49 0 "RELEASE outer"
351
352without_rowid3-2-test 50 0 "SAVEPOINT outer"
353without_rowid3-2-test 51 1   "INSERT INTO leaf VALUES('f', 4)"
354without_rowid3-2-test 52 1   "SAVEPOINT inner"
355without_rowid3-2-test 53 1     "INSERT INTO leaf VALUES('g', 4)"
356without_rowid3-2-test 54 1  "RELEASE outer"   FKV
357without_rowid3-2-test 55 1   "ROLLBACK TO inner"
358without_rowid3-2-test 56 0  "COMMIT"          FKV
359without_rowid3-2-test 57 0   "INSERT INTO node VALUES(4, NULL)"
360without_rowid3-2-test 58 0 "RELEASE outer"
361without_rowid3-2-test 59 0 "SELECT * FROM node" {2 {} 3 2 4 {}}
362without_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#
370without_rowid3-2-test 61 0 "BEGIN"
371without_rowid3-2-test 62 0   "DELETE FROM leaf"
372without_rowid3-2-test 63 0   "DELETE FROM node"
373without_rowid3-2-test 64 1   "INSERT INTO leaf VALUES('a', 1)"
374without_rowid3-2-test 65 1   "INSERT INTO leaf VALUES('b', 2)"
375without_rowid3-2-test 66 1   "INSERT INTO leaf VALUES('c', 1)"
376do_test without_rowid3-2-test-67 {
377  catchsql          "INSERT INTO node SELECT parent, 3 FROM leaf"
378} {1 {UNIQUE constraint failed: node.nodeid}}
379without_rowid3-2-test 68 0 "COMMIT"           FKV
380without_rowid3-2-test 69 1   "INSERT INTO node VALUES(1, NULL)"
381without_rowid3-2-test 70 0   "INSERT INTO node VALUES(2, NULL)"
382without_rowid3-2-test 71 0 "COMMIT"
383
384without_rowid3-2-test 72 0 "BEGIN"
385without_rowid3-2-test 73 1   "DELETE FROM node"
386without_rowid3-2-test 74 0   "INSERT INTO node(nodeid) SELECT DISTINCT parent FROM leaf"
387without_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#
397drop_all_tables
398do_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} {}
411do_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} {}
418do_test without_rowid3-3.1.3 {
419  catchsql { UPDATE ab SET a = 5 }
420} {1 {CHECK constraint failed: e!=5}}
421do_test without_rowid3-3.1.4 {
422  execsql { SELECT * FROM ab }
423} {1 b}
424do_test without_rowid3-3.1.4 {
425  execsql BEGIN;
426  catchsql { UPDATE ab SET a = 5 }
427} {1 {CHECK constraint failed: e!=5}}
428do_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
433do_test without_rowid3-3.2.1 {
434  execsql BEGIN;
435  catchsql { DELETE FROM ab }
436} {1 {FOREIGN KEY constraint failed}}
437do_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#
446drop_all_tables
447do_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} {}
467do_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} {}
475do_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}
482do_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} {}
490do_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#
502drop_all_tables
503ifcapable 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
521drop_all_tables
522ifcapable 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#
538drop_all_tables
539do_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} {}
545do_test without_rowid3-7.2 {
546  catchsql { INSERT INTO t2 VALUES(1, 'A'); }
547} {1 {FOREIGN KEY constraint failed}}
548do_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} {}
555do_test without_rowid3-7.4 {
556  execsql { UPDATE t2 SET c = 2 }
557} {}
558do_test without_rowid3-7.5 {
559  catchsql { UPDATE t2 SET c = 3 }
560} {1 {FOREIGN KEY constraint failed}}
561do_test without_rowid3-7.6 {
562  catchsql { DELETE FROM t1 WHERE a = 2 }
563} {1 {FOREIGN KEY constraint failed}}
564do_test without_rowid3-7.7 {
565  execsql { DELETE FROM t1 WHERE a = 1 }
566} {}
567do_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#
575drop_all_tables
576proc 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}
580without_rowid3-8-test  1 { PRAGMA foreign_keys = 0     } 0
581without_rowid3-8-test  2 { PRAGMA foreign_keys = 1     } 1
582without_rowid3-8-test  3 { BEGIN                       } 1
583without_rowid3-8-test  4 { PRAGMA foreign_keys = 0     } 1
584without_rowid3-8-test  5 { COMMIT                      } 1
585without_rowid3-8-test  6 { PRAGMA foreign_keys = 0     } 0
586without_rowid3-8-test  7 { BEGIN                       } 0
587without_rowid3-8-test  8 { PRAGMA foreign_keys = 1     } 0
588without_rowid3-8-test  9 { COMMIT                      } 0
589without_rowid3-8-test 10 { PRAGMA foreign_keys = 1     } 1
590without_rowid3-8-test 11 { PRAGMA foreign_keys = off   } 0
591without_rowid3-8-test 12 { PRAGMA foreign_keys = on    } 1
592without_rowid3-8-test 13 { PRAGMA foreign_keys = no    } 0
593without_rowid3-8-test 14 { PRAGMA foreign_keys = yes   } 1
594without_rowid3-8-test 15 { PRAGMA foreign_keys = false } 0
595without_rowid3-8-test 16 { PRAGMA foreign_keys = true  } 1
596
597#-------------------------------------------------------------------------
598# The following tests, without_rowid3-9.*, test SET DEFAULT actions.
599#
600drop_all_tables
601do_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} {}
611do_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}
621do_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}
629do_test without_rowid3-9.1.4 {
630  execsql { SELECT * FROM t1 }
631} {2 two}
632do_test without_rowid3-9.1.5 {
633  catchsql { DELETE FROM t1 }
634} {1 {FOREIGN KEY constraint failed}}
635
636do_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} {}
649do_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}
659do_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#
670set tn 0
671foreach 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#
695do_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}}
702do_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 {}}
709do_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"}}
718do_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#
732drop_all_tables
733do_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#
748drop_all_tables
749do_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} {}
760do_test without_rowid3-12.1.2 {
761  execsql "BEGIN"
762  execsql "INSERT INTO t2 VALUES('two')"
763} {}
764do_test without_rowid3-12.1.3 {
765  execsql "UPDATE t1 SET b = 'four' WHERE b = 'one'"
766} {}
767do_test without_rowid3-12.1.4 {
768  catchsql "UPDATE t1 SET b = 'five' WHERE b = 'two'"
769} {1 {FOREIGN KEY constraint failed}}
770do_test without_rowid3-12.1.5 {
771  execsql "DELETE FROM t1 WHERE b = 'two'"
772} {}
773do_test without_rowid3-12.1.6 {
774  catchsql "COMMIT"
775} {1 {FOREIGN KEY constraint failed}}
776do_test without_rowid3-12.1.7 {
777  execsql {
778    INSERT INTO t1 VALUES(2, 'two');
779    COMMIT;
780  }
781} {}
782
783drop_all_tables
784do_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}
802do_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}
809do_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}}
818do_test without_rowid3-12.2.4 {
819  execsql {
820    SELECT * FROM t1;
821    SELECT * FROM t2;
822  }
823} {A B a b}
824
825drop_all_tables
826do_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} {}
844do_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}
853do_test without_rowid3-12.3.3 {
854  catchsql { INSERT INTO down(c39, c38) VALUES('yes', 'no') }
855} {1 {FOREIGN KEY constraint failed}}
856do_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}}
863do_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#
875drop_all_tables
876do_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} {}
884foreach {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 "ALTER
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#
917drop_all_tables
918ifcapable 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      INSERT INTO t2(a,b) VALUES(1,2);
925    }
926    catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
927  } {0 {}}
928  do_test without_rowid3-14.1.2 {
929    catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
930  } {0 {}}
931  do_test without_rowid3-14.1.3 {
932    catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
933  } {0 {}}
934  do_test without_rowid3-14.1.4 {
935    catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
936  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
937  do_test without_rowid3-14.1.5 {
938    catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
939  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
940  do_test without_rowid3-14.1.6 {
941    execsql {
942      PRAGMA foreign_keys = off;
943      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
944      PRAGMA foreign_keys = on;
945      SELECT sql FROM sqlite_schema WHERE name='t2';
946    }
947  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
948
949
950  # Test the sqlite_rename_parent() function directly.
951  #
952  proc test_rename_parent {zCreate zOld zNew} {
953    db eval {SELECT sqlite_rename_table(
954        'main', 'table', 't1', $zCreate, $zOld, $zNew, 0
955    )}
956  }
957  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
958  do_test without_rowid3-14.2.1.1 {
959    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
960  } {{CREATE TABLE t1(a REFERENCES "t3")}}
961  do_test without_rowid3-14.2.1.2 {
962    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
963  } {{CREATE TABLE t1(a REFERENCES t2)}}
964  do_test without_rowid3-14.2.1.3 {
965    test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
966  } {{CREATE TABLE t1(a REFERENCES "t3")}}
967  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
968
969  # Test ALTER TABLE RENAME TABLE a bit.
970  #
971  do_test without_rowid3-14.2.2.1 {
972    drop_all_tables
973    execsql {
974      CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid;
975      CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
976            WITHOUT rowid;
977      CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
978    }
979    execsql { SELECT sql FROM sqlite_schema WHERE type = 'table'}
980  } [list \
981    {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid}       \
982    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
983            WITHOUT rowid}    \
984    {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)}  \
985  ]
986  do_test without_rowid3-14.2.2.2 {
987    execsql { ALTER TABLE t1 RENAME TO t4 }
988    execsql { SELECT sql FROM sqlite_schema WHERE type = 'table'}
989  } [list \
990    {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid}      \
991    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)
992            WITHOUT rowid}     \
993    {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
994  ]
995  do_test without_rowid3-14.2.2.3 {
996    catchsql { INSERT INTO t3 VALUES(1, 2, 3) }
997  } {1 {FOREIGN KEY constraint failed}}
998  do_test without_rowid3-14.2.2.4 {
999    execsql { INSERT INTO t4 VALUES(1, NULL) }
1000  } {}
1001  do_test without_rowid3-14.2.2.5 {
1002    catchsql { UPDATE t4 SET b = 5 }
1003  } {1 {FOREIGN KEY constraint failed}}
1004  do_test without_rowid3-14.2.2.6 {
1005    catchsql { UPDATE t4 SET b = 1 }
1006  } {0 {}}
1007  do_test without_rowid3-14.2.2.7 {
1008    execsql { INSERT INTO t3 VALUES(1, NULL, 1) }
1009  } {}
1010
1011  # Repeat for TEMP tables
1012  #
1013  drop_all_tables
1014  do_test without_rowid3-14.1tmp.1 {
1015    # Adding a column with a REFERENCES clause is not supported.
1016    execsql {
1017      CREATE TEMP TABLE t1(a PRIMARY KEY) WITHOUT rowid;
1018      CREATE TEMP TABLE t2(a, b);
1019      INSERT INTO temp.t2(a,b) VALUES(1,2);
1020    }
1021    catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
1022  } {0 {}}
1023  do_test without_rowid3-14.1tmp.2 {
1024    catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
1025  } {0 {}}
1026  do_test without_rowid3-14.1tmp.3 {
1027    catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
1028  } {0 {}}
1029  do_test without_rowid3-14.1tmp.4 {
1030    catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
1031  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
1032  do_test without_rowid3-14.1tmp.5 {
1033    catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
1034  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
1035  do_test without_rowid3-14.1tmp.6 {
1036    execsql {
1037      PRAGMA foreign_keys = off;
1038      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
1039      PRAGMA foreign_keys = on;
1040      SELECT sql FROM temp.sqlite_schema WHERE name='t2';
1041    }
1042  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
1043
1044  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
1045  do_test without_rowid3-14.2tmp.1.1 {
1046    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
1047  } {{CREATE TABLE t1(a REFERENCES "t3")}}
1048  do_test without_rowid3-14.2tmp.1.2 {
1049    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
1050  } {{CREATE TABLE t1(a REFERENCES t2)}}
1051  do_test without_rowid3-14.2tmp.1.3 {
1052    test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
1053  } {{CREATE TABLE t1(a REFERENCES "t3")}}
1054  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
1055
1056  # Test ALTER TABLE RENAME TABLE a bit.
1057  #
1058  do_test without_rowid3-14.2tmp.2.1 {
1059    drop_all_tables
1060    execsql {
1061      CREATE TEMP TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid;
1062      CREATE TEMP TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
1063            WITHOUT rowid;
1064      CREATE TEMP TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
1065    }
1066    execsql { SELECT sql FROM sqlite_temp_schema WHERE type = 'table'}
1067  } [list \
1068    {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid}       \
1069    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
1070            WITHOUT rowid}    \
1071    {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)}  \
1072  ]
1073  do_test without_rowid3-14.2tmp.2.2 {
1074    execsql { ALTER TABLE t1 RENAME TO t4 }
1075    execsql { SELECT sql FROM temp.sqlite_schema WHERE type = 'table'}
1076  } [list \
1077    {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid}      \
1078    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)
1079            WITHOUT rowid}     \
1080    {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
1081  ]
1082  do_test without_rowid3-14.2tmp.2.3 {
1083    catchsql { INSERT INTO t3 VALUES(1, 2, 3) }
1084  } {1 {FOREIGN KEY constraint failed}}
1085  do_test without_rowid3-14.2tmp.2.4 {
1086    execsql { INSERT INTO t4 VALUES(1, NULL) }
1087  } {}
1088  do_test without_rowid3-14.2tmp.2.5 {
1089    catchsql { UPDATE t4 SET b = 5 }
1090  } {1 {FOREIGN KEY constraint failed}}
1091  do_test without_rowid3-14.2tmp.2.6 {
1092    catchsql { UPDATE t4 SET b = 1 }
1093  } {0 {}}
1094  do_test without_rowid3-14.2tmp.2.7 {
1095    execsql { INSERT INTO t3 VALUES(1, NULL, 1) }
1096  } {}
1097
1098  # Repeat for ATTACH-ed tables
1099  #
1100  drop_all_tables
1101  do_test without_rowid3-14.1aux.1 {
1102    # Adding a column with a REFERENCES clause is not supported.
1103    execsql {
1104      ATTACH ':memory:' AS aux;
1105      CREATE TABLE aux.t1(a PRIMARY KEY) WITHOUT rowid;
1106      CREATE TABLE aux.t2(a, b);
1107      INSERT INTO aux.t2(a,b) VALUES(1,2);
1108    }
1109    catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
1110  } {0 {}}
1111  do_test without_rowid3-14.1aux.2 {
1112    catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
1113  } {0 {}}
1114  do_test without_rowid3-14.1aux.3 {
1115    catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
1116  } {0 {}}
1117  do_test without_rowid3-14.1aux.4 {
1118    catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
1119  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
1120  do_test without_rowid3-14.1aux.5 {
1121    catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
1122  } {1 {Cannot add a REFERENCES column with non-NULL default value}}
1123  do_test without_rowid3-14.1aux.6 {
1124    execsql {
1125      PRAGMA foreign_keys = off;
1126      ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
1127      PRAGMA foreign_keys = on;
1128      SELECT sql FROM aux.sqlite_schema WHERE name='t2';
1129    }
1130  } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
1131
1132  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
1133  do_test without_rowid3-14.2aux.1.1 {
1134    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
1135  } {{CREATE TABLE t1(a REFERENCES "t3")}}
1136  do_test without_rowid3-14.2aux.1.2 {
1137    test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
1138  } {{CREATE TABLE t1(a REFERENCES t2)}}
1139  do_test without_rowid3-14.2aux.1.3 {
1140    test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
1141  } {{CREATE TABLE t1(a REFERENCES "t3")}}
1142  sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
1143
1144  # Test ALTER TABLE RENAME TABLE a bit.
1145  #
1146  do_test without_rowid3-14.2aux.2.1 {
1147    drop_all_tables
1148    execsql {
1149      CREATE TABLE aux.t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid;
1150      CREATE TABLE aux.t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
1151            WITHOUT rowid;
1152      CREATE TABLE aux.t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
1153    }
1154    execsql { SELECT sql FROM aux.sqlite_schema WHERE type = 'table'}
1155  } [list \
1156    {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1) WITHOUT rowid}       \
1157    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)
1158            WITHOUT rowid}    \
1159    {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)}  \
1160  ]
1161  do_test without_rowid3-14.2aux.2.2 {
1162    execsql { ALTER TABLE t1 RENAME TO t4 }
1163    execsql { SELECT sql FROM aux.sqlite_schema WHERE type = 'table'}
1164  } [list \
1165    {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4") WITHOUT rowid}      \
1166    {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)
1167            WITHOUT rowid}     \
1168    {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
1169  ]
1170  do_test without_rowid3-14.2aux.2.3 {
1171    catchsql { INSERT INTO t3 VALUES(1, 2, 3) }
1172  } {1 {FOREIGN KEY constraint failed}}
1173  do_test without_rowid3-14.2aux.2.4 {
1174    execsql { INSERT INTO t4 VALUES(1, NULL) }
1175  } {}
1176  do_test without_rowid3-14.2aux.2.5 {
1177    catchsql { UPDATE t4 SET b = 5 }
1178  } {1 {FOREIGN KEY constraint failed}}
1179  do_test without_rowid3-14.2aux.2.6 {
1180    catchsql { UPDATE t4 SET b = 1 }
1181  } {0 {}}
1182  do_test without_rowid3-14.2aux.2.7 {
1183    execsql { INSERT INTO t3 VALUES(1, NULL, 1) }
1184  } {}
1185}
1186
1187do_test without_rowid3-2.14.3.1 {
1188  drop_all_tables
1189  execsql {
1190    CREATE TABLE t1(a, b REFERENCES nosuchtable);
1191    DROP TABLE t1;
1192  }
1193} {}
1194do_test without_rowid3-2.14.3.2 {
1195  execsql {
1196    CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT rowid;
1197    INSERT INTO t1 VALUES('a', 1);
1198    CREATE TABLE t2(x REFERENCES t1);
1199    INSERT INTO t2 VALUES('a');
1200  }
1201} {}
1202do_test without_rowid3-2.14.3.3 {
1203  catchsql { DROP TABLE t1 }
1204} {1 {FOREIGN KEY constraint failed}}
1205do_test without_rowid3-2.14.3.4 {
1206  execsql {
1207    DELETE FROM t2;
1208    DROP TABLE t1;
1209  }
1210} {}
1211do_test without_rowid3-2.14.3.4 {
1212  catchsql { INSERT INTO t2 VALUES('x') }
1213} {1 {no such table: main.t1}}
1214do_test without_rowid3-2.14.3.5 {
1215  execsql {
1216    CREATE TABLE t1(x PRIMARY KEY) WITHOUT rowid;
1217    INSERT INTO t1 VALUES('x');
1218  }
1219  execsql { INSERT INTO t2 VALUES('x') }
1220} {}
1221do_test without_rowid3-2.14.3.6 {
1222  catchsql { DROP TABLE t1 }
1223} {1 {FOREIGN KEY constraint failed}}
1224do_test without_rowid3-2.14.3.7 {
1225  execsql {
1226    DROP TABLE t2;
1227    DROP TABLE t1;
1228  }
1229} {}
1230do_test without_rowid3-2.14.3.8 {
1231  execsql {
1232    CREATE TABLE pp(x, y, PRIMARY KEY(x, y)) WITHOUT ROWID;
1233    CREATE TABLE cc(a, b, FOREIGN KEY(a, b) REFERENCES pp(x, z));
1234  }
1235  catchsql { INSERT INTO cc VALUES(1, 2) }
1236} {1 {foreign key mismatch - "cc" referencing "pp"}}
1237do_test without_rowid3-2.14.3.9 {
1238  execsql { DROP TABLE cc }
1239} {}
1240do_test without_rowid3-2.14.3.10 {
1241  execsql {
1242    CREATE TABLE cc(a, b,
1243      FOREIGN KEY(a, b) REFERENCES pp DEFERRABLE INITIALLY DEFERRED
1244    );
1245  }
1246  execsql {
1247    INSERT INTO pp VALUES('a', 'b');
1248    INSERT INTO cc VALUES('a', 'b');
1249    BEGIN;
1250      DROP TABLE pp;
1251      CREATE TABLE pp(a, b, c, PRIMARY KEY(b, c)) WITHOUT rowid;
1252      INSERT INTO pp VALUES(1, 'a', 'b');
1253    COMMIT;
1254  }
1255} {}
1256do_test without_rowid3-2.14.3.11 {
1257  execsql {
1258    BEGIN;
1259      DROP TABLE cc;
1260      DROP TABLE pp;
1261    COMMIT;
1262  }
1263} {}
1264do_test without_rowid3-2.14.3.12 {
1265  execsql {
1266    CREATE TABLE b1(a, b);
1267    CREATE TABLE b2(a, b REFERENCES b1);
1268    DROP TABLE b1;
1269  }
1270} {}
1271do_test without_rowid3-2.14.3.13 {
1272  execsql {
1273    CREATE TABLE b3(a, b REFERENCES b2 DEFERRABLE INITIALLY DEFERRED);
1274    DROP TABLE b2;
1275  }
1276} {}
1277
1278# Test that nothing goes wrong when dropping a table that refers to a view.
1279# Or dropping a view that an existing FK (incorrectly) refers to. Or either
1280# of the above scenarios with a virtual table.
1281drop_all_tables
1282do_test without_rowid3-2.14.4.1 {
1283  execsql {
1284    CREATE TABLE t1(x REFERENCES v);
1285    CREATE VIEW v AS SELECT * FROM t1;
1286  }
1287} {}
1288do_test without_rowid3-2.14.4.2 {
1289  execsql {
1290    DROP VIEW v;
1291  }
1292} {}
1293ifcapable vtab {
1294  register_echo_module db
1295  do_test without_rowid3-2.14.4.3 {
1296    execsql { CREATE VIRTUAL TABLE v USING echo(t1) }
1297  } {}
1298  do_test without_rowid3-2.14.4.2 {
1299    execsql {
1300      DROP TABLE v;
1301    }
1302  } {}
1303}
1304
1305#-------------------------------------------------------------------------
1306# The following tests, without_rowid3-15.*, test that unnecessary FK related scans
1307# and lookups are avoided when the constraint counters are zero.
1308#
1309drop_all_tables
1310proc execsqlS {zSql} {
1311  set ::sqlite_search_count 0
1312  set ::sqlite_found_count 0
1313  set res [uplevel [list execsql $zSql]]
1314  concat [expr $::sqlite_found_count + $::sqlite_search_count] $res
1315}
1316do_test without_rowid3-15.1.1 {
1317  execsql {
1318    CREATE TABLE pp(a PRIMARY KEY, b) WITHOUT rowid;
1319    CREATE TABLE cc(x, y REFERENCES pp DEFERRABLE INITIALLY DEFERRED);
1320    INSERT INTO pp VALUES(1, 'one');
1321    INSERT INTO pp VALUES(2, 'two');
1322    INSERT INTO cc VALUES('neung', 1);
1323    INSERT INTO cc VALUES('song', 2);
1324  }
1325} {}
1326do_test without_rowid3-15.1.2 {
1327  execsqlS { INSERT INTO pp VALUES(3, 'three') }
1328} {0}
1329do_test without_rowid3-15.1.3 {
1330  execsql {
1331    BEGIN;
1332      INSERT INTO cc VALUES('see', 4);    -- Violates deferred constraint
1333  }
1334  execsqlS { INSERT INTO pp VALUES(5, 'five') }
1335} {2}
1336do_test without_rowid3-15.1.4 {
1337  execsql { DELETE FROM cc WHERE x = 'see' }
1338  execsqlS { INSERT INTO pp VALUES(6, 'six') }
1339} {0}
1340do_test without_rowid3-15.1.5 {
1341  execsql COMMIT
1342} {}
1343do_test without_rowid3-15.1.6 {
1344  execsql BEGIN
1345  execsqlS {
1346    DELETE FROM cc WHERE x = 'neung';
1347    ROLLBACK;
1348  }
1349} {1}
1350do_test without_rowid3-15.1.7 {
1351  execsql {
1352    BEGIN;
1353    DELETE FROM pp WHERE a = 2;
1354  }
1355  execsqlS {
1356    DELETE FROM cc WHERE x = 'neung';
1357    ROLLBACK;
1358  }
1359} {2}
1360
1361#-------------------------------------------------------------------------
1362# This next block of tests, without_rowid3-16.*, test that rows that refer to
1363# themselves may be inserted and deleted.
1364#
1365foreach {tn zSchema} {
1366  1 { CREATE TABLE self(a INTEGER PRIMARY KEY, b REFERENCES self(a))
1367             WITHOUT rowid }
1368  2 { CREATE TABLE self(a PRIMARY KEY, b REFERENCES self(a)) WITHOUT rowid }
1369  3 { CREATE TABLE self(a UNIQUE, b INT PRIMARY KEY REFERENCES self(a))
1370             WITHOUT rowid }
1371} {
1372  drop_all_tables
1373  do_test without_rowid3-16.1.$tn.1 {
1374    execsql $zSchema
1375    execsql { INSERT INTO self VALUES(13, 13) }
1376  } {}
1377  do_test without_rowid3-16.1.$tn.2 {
1378    execsql { UPDATE self SET a = 14, b = 14 }
1379  } {}
1380
1381  do_test without_rowid3-16.1.$tn.3 {
1382    catchsql { UPDATE self SET b = 15 }
1383  } {1 {FOREIGN KEY constraint failed}}
1384
1385  do_test without_rowid3-16.1.$tn.4 {
1386    catchsql { UPDATE self SET a = 15 }
1387  } {1 {FOREIGN KEY constraint failed}}
1388
1389  do_test without_rowid3-16.1.$tn.5 {
1390    catchsql { UPDATE self SET a = 15, b = 16 }
1391  } {1 {FOREIGN KEY constraint failed}}
1392
1393  do_test without_rowid3-16.1.$tn.6 {
1394    catchsql { UPDATE self SET a = 17, b = 17 }
1395  } {0 {}}
1396
1397  do_test without_rowid3-16.1.$tn.7 {
1398    execsql { DELETE FROM self }
1399  } {}
1400  do_test without_rowid3-16.1.$tn.8 {
1401    catchsql { INSERT INTO self VALUES(20, 21) }
1402  } {1 {FOREIGN KEY constraint failed}}
1403}
1404
1405# Additional tests cases using multi-column self-referential
1406# FOREIGN KEY constraints.
1407#
1408drop_all_tables
1409do_execsql_test without_rowid3-16.4.1.1 {
1410  PRAGMA foreign_keys=ON;
1411  CREATE TABLE t1(a,b,c,d,e,f,
1412     UNIQUE (a,b),
1413     PRIMARY KEY (e,c),
1414     FOREIGN KEY (d,f) REFERENCES t1(e,c)
1415  ) WITHOUT rowid;
1416  INSERT INTO t1 VALUES(1,2,3,5,5,3);
1417  INSERT INTO t1 VALUES(2,3,4,6,6,4);
1418  INSERT INTO t1 VALUES('x','y',1.5,'fizzle','fizzle',1.5);
1419  SELECT *, '|' FROM t1 ORDER BY a, b;
1420} {1 2 3 5 5 3 | 2 3 4 6 6 4 | x y 1.5 fizzle fizzle 1.5 |}
1421
1422do_execsql_test without_rowid3-16.4.1.2 {
1423  UPDATE t1 SET c=99, f=99 WHERE a=1;
1424  SELECT *, '|' FROM t1 ORDER BY a, b;
1425} {1 2 99 5 5 99 | 2 3 4 6 6 4 | x y 1.5 fizzle fizzle 1.5 |}
1426
1427do_execsql_test without_rowid3-16.4.1.3 {
1428  UPDATE t1 SET e=876, d=876 WHERE a=2;
1429  SELECT *, '|' FROM t1 ORDER BY a, b;
1430} {1 2 99 5 5 99 | 2 3 4 876 876 4 | x y 1.5 fizzle fizzle 1.5 |}
1431
1432do_test without_rowid3-16.4.1.4 {
1433  catchsql {
1434    UPDATE t1 SET c=11, e=22 WHERE a=1;
1435  }
1436} {1 {FOREIGN KEY constraint failed}}
1437
1438do_test without_rowid3-16.4.1.5 {
1439  catchsql {
1440    UPDATE t1 SET d=11, f=22 WHERE a=1;
1441  }
1442} {1 {FOREIGN KEY constraint failed}}
1443
1444do_execsql_test without_rowid3-16.4.1.6 {
1445  DELETE FROM t1 WHERE a=1;
1446  SELECT *, '|' FROM t1 ORDER BY a, b;
1447} {2 3 4 876 876 4 | x y 1.5 fizzle fizzle 1.5 |}
1448
1449do_execsql_test without_rowid3-16.4.2.1 {
1450  DROP TABLE t1;
1451  CREATE TABLE t1(a,b,c,d,e,f,
1452     PRIMARY KEY (a,b),
1453     UNIQUE (e,c),
1454     FOREIGN KEY (d,f) REFERENCES t1(e,c)
1455  ) WITHOUT rowid;
1456  INSERT INTO t1 VALUES(1,2,3,5,5,3);
1457  INSERT INTO t1 VALUES(2,3,4,6,6,4);
1458  INSERT INTO t1 VALUES('x','y',1.5,'fizzle','fizzle',1.5);
1459  SELECT *, '|' FROM t1 ORDER BY a, b;
1460} {1 2 3 5 5 3 | 2 3 4 6 6 4 | x y 1.5 fizzle fizzle 1.5 |}
1461
1462do_execsql_test without_rowid3-16.4.2.2 {
1463  UPDATE t1 SET c=99, f=99 WHERE a=1;
1464  SELECT *, '|' FROM t1 ORDER BY a, b;
1465} {1 2 99 5 5 99 | 2 3 4 6 6 4 | x y 1.5 fizzle fizzle 1.5 |}
1466
1467do_execsql_test without_rowid3-16.4.2.3 {
1468  UPDATE t1 SET e=876, d=876 WHERE a=2;
1469  SELECT *, '|' FROM t1 ORDER BY a, b;
1470} {1 2 99 5 5 99 | 2 3 4 876 876 4 | x y 1.5 fizzle fizzle 1.5 |}
1471
1472do_test without_rowid3-16.4.2.4 {
1473  catchsql {
1474    UPDATE t1 SET c=11, e=22 WHERE a=1;
1475  }
1476} {1 {FOREIGN KEY constraint failed}}
1477
1478do_test without_rowid3-16.4.2.5 {
1479  catchsql {
1480    UPDATE t1 SET d=11, f=22 WHERE a=1;
1481  }
1482} {1 {FOREIGN KEY constraint failed}}
1483
1484do_execsql_test without_rowid3-16.4.2.6 {
1485  DELETE FROM t1 WHERE a=1;
1486  SELECT *, '|' FROM t1 ORDER BY a, b;
1487} {2 3 4 876 876 4 | x y 1.5 fizzle fizzle 1.5 |}
1488
1489
1490#-------------------------------------------------------------------------
1491# This next block of tests, without_rowid3-17.*, tests that if "PRAGMA count_changes"
1492# is turned on statements that violate immediate FK constraints return
1493# SQLITE_CONSTRAINT immediately, not after returning a number of rows.
1494# Whereas statements that violate deferred FK constraints return the number
1495# of rows before failing.
1496#
1497# Also test that rows modified by FK actions are not counted in either the
1498# returned row count or the values returned by sqlite3_changes(). Like
1499# trigger related changes, they are included in sqlite3_total_changes() though.
1500#
1501drop_all_tables
1502do_test without_rowid3-17.1.1 {
1503  execsql { PRAGMA count_changes = 1 }
1504  execsql {
1505    CREATE TABLE one(a, b, c, UNIQUE(b, c));
1506    CREATE TABLE two(d, e, f, FOREIGN KEY(e, f) REFERENCES one(b, c));
1507    INSERT INTO one VALUES(1, 2, 3);
1508  }
1509} {1}
1510do_test without_rowid3-17.1.2 {
1511  set STMT [sqlite3_prepare_v2 db "INSERT INTO two VALUES(4, 5, 6)" -1 dummy]
1512  sqlite3_step $STMT
1513} {SQLITE_CONSTRAINT}
1514verify_ex_errcode without_rowid3-17.1.2b SQLITE_CONSTRAINT_FOREIGNKEY
1515ifcapable autoreset {
1516  do_test without_rowid3-17.1.3 {
1517    sqlite3_step $STMT
1518  } {SQLITE_CONSTRAINT}
1519  verify_ex_errcode without_rowid3-17.1.3b SQLITE_CONSTRAINT_FOREIGNKEY
1520} else {
1521  do_test without_rowid3-17.1.3 {
1522    sqlite3_step $STMT
1523  } {SQLITE_MISUSE}
1524}
1525do_test without_rowid3-17.1.4 {
1526  sqlite3_finalize $STMT
1527} {SQLITE_CONSTRAINT}
1528verify_ex_errcode without_rowid3-17.1.4b SQLITE_CONSTRAINT_FOREIGNKEY
1529do_test without_rowid3-17.1.5 {
1530  execsql {
1531    INSERT INTO one VALUES(2, 3, 4);
1532    INSERT INTO one VALUES(3, 4, 5);
1533    INSERT INTO two VALUES(1, 2, 3);
1534    INSERT INTO two VALUES(2, 3, 4);
1535    INSERT INTO two VALUES(3, 4, 5);
1536  }
1537} {1 1 1 1 1}
1538do_test without_rowid3-17.1.6 {
1539  catchsql {
1540    BEGIN;
1541      INSERT INTO one VALUES(0, 0, 0);
1542      UPDATE two SET e=e+1, f=f+1;
1543  }
1544} {1 {FOREIGN KEY constraint failed}}
1545do_test without_rowid3-17.1.7 {
1546  execsql { SELECT * FROM one }
1547} {1 2 3 2 3 4 3 4 5 0 0 0}
1548do_test without_rowid3-17.1.8 {
1549  execsql { SELECT * FROM two }
1550} {1 2 3 2 3 4 3 4 5}
1551do_test without_rowid3-17.1.9 {
1552  execsql COMMIT
1553} {}
1554do_test without_rowid3-17.1.10 {
1555  execsql {
1556    CREATE TABLE three(
1557      g, h, i,
1558      FOREIGN KEY(h, i) REFERENCES one(b, c) DEFERRABLE INITIALLY DEFERRED
1559    );
1560  }
1561} {}
1562do_test without_rowid3-17.1.11 {
1563  set STMT [sqlite3_prepare_v2 db "INSERT INTO three VALUES(7, 8, 9)" -1 dummy]
1564  sqlite3_step $STMT
1565} {SQLITE_ROW}
1566do_test without_rowid3-17.1.12 {
1567  sqlite3_column_text $STMT 0
1568} {1}
1569do_test without_rowid3-17.1.13 {
1570  sqlite3_step $STMT
1571} {SQLITE_CONSTRAINT}
1572verify_ex_errcode without_rowid3-17.1.13b SQLITE_CONSTRAINT_FOREIGNKEY
1573do_test without_rowid3-17.1.14 {
1574  sqlite3_finalize $STMT
1575} {SQLITE_CONSTRAINT}
1576verify_ex_errcode without_rowid3-17.1.14b SQLITE_CONSTRAINT_FOREIGNKEY
1577
1578drop_all_tables
1579do_test without_rowid3-17.2.1 {
1580  execsql {
1581    CREATE TABLE high("a'b!" PRIMARY KEY, b) WITHOUT rowid;
1582    CREATE TABLE low(
1583      c,
1584      "d&6" REFERENCES high ON UPDATE CASCADE ON DELETE CASCADE
1585    );
1586  }
1587} {}
1588do_test without_rowid3-17.2.2 {
1589  execsql {
1590    INSERT INTO high VALUES('a', 'b');
1591    INSERT INTO low VALUES('b', 'a');
1592  }
1593  db changes
1594} {1}
1595set nTotal [db total_changes]
1596do_test without_rowid3-17.2.3 {
1597  execsql { UPDATE high SET "a'b!" = 'c' }
1598} {1}
1599do_test without_rowid3-17.2.4 {
1600  db changes
1601} {1}
1602do_test without_rowid3-17.2.5 {
1603  expr [db total_changes] - $nTotal
1604} {2}
1605do_test without_rowid3-17.2.6 {
1606  execsql { SELECT * FROM high ; SELECT * FROM low }
1607} {c b b c}
1608do_test without_rowid3-17.2.7 {
1609  execsql { DELETE FROM high }
1610} {1}
1611do_test without_rowid3-17.2.8 {
1612  db changes
1613} {1}
1614do_test without_rowid3-17.2.9 {
1615  expr [db total_changes] - $nTotal
1616} {4}
1617do_test without_rowid3-17.2.10 {
1618  execsql { SELECT * FROM high ; SELECT * FROM low }
1619} {}
1620execsql { PRAGMA count_changes = 0 }
1621
1622#-------------------------------------------------------------------------
1623# Test that the authorization callback works.
1624#
1625
1626ifcapable auth {
1627  do_test without_rowid3-18.1 {
1628    execsql {
1629      CREATE TABLE long(a, b PRIMARY KEY, c) WITHOUT rowid;
1630      CREATE TABLE short(d, e, f REFERENCES long);
1631      CREATE TABLE mid(g, h, i REFERENCES long DEFERRABLE INITIALLY DEFERRED);
1632    }
1633  } {}
1634
1635  proc auth {args} {eval lappend ::authargs [lrange $args 0 4]; return SQLITE_OK}
1636  db auth auth
1637
1638  # An insert on the parent table must read the child key of any deferred
1639  # foreign key constraints. But not the child key of immediate constraints.
1640  set authargs {}
1641  do_test without_rowid3-18.2 {
1642    execsql { INSERT INTO long VALUES(1, 2, 3) }
1643    set authargs
1644  } {SQLITE_INSERT long {} main {} SQLITE_READ mid i main {}}
1645
1646  # An insert on the child table of an immediate constraint must read the
1647  # parent key columns (to see if it is a violation or not).
1648  set authargs {}
1649  do_test without_rowid3-18.3 {
1650    execsql { INSERT INTO short VALUES(1, 3, 2) }
1651    set authargs
1652  } {SQLITE_INSERT short {} main {} SQLITE_READ long b main {}}
1653
1654  # As must an insert on the child table of a deferred constraint.
1655  set authargs {}
1656  do_test without_rowid3-18.4 {
1657    execsql { INSERT INTO mid VALUES(1, 3, 2) }
1658    set authargs
1659  } {SQLITE_INSERT mid {} main {} SQLITE_READ long b main {}}
1660
1661  do_test without_rowid3-18.5 {
1662    execsql {
1663      CREATE TABLE nought(a, b PRIMARY KEY, c) WITHOUT rowid;
1664      CREATE TABLE cross(d, e, f,
1665        FOREIGN KEY(e) REFERENCES nought(b) ON UPDATE CASCADE
1666      );
1667    }
1668    execsql { INSERT INTO nought VALUES(2, 1, 2) }
1669    execsql { INSERT INTO cross VALUES(0, 1, 0) }
1670    set authargs [list]
1671    execsql { UPDATE nought SET b = 5 }
1672    set authargs
1673  } {SQLITE_UPDATE nought b main {} SQLITE_READ cross e main {} SQLITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_UPDATE cross e main {} SQLITE_READ nought b main {} SQLITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {}}
1674
1675  do_test without_rowid3-18.6 {
1676    execsql {SELECT * FROM cross}
1677  } {0 5 0}
1678
1679  do_test without_rowid3-18.7 {
1680    execsql {
1681      CREATE TABLE one(a INT PRIMARY KEY, b) WITHOUT rowid;
1682      CREATE TABLE two(b, c REFERENCES one);
1683      INSERT INTO one VALUES(101, 102);
1684    }
1685    set authargs [list]
1686    execsql { INSERT INTO two VALUES(100, 101); }
1687    set authargs
1688  } {SQLITE_INSERT two {} main {} SQLITE_READ one a main {}}
1689
1690  # Return SQLITE_IGNORE to requests to read from the parent table. This
1691  # causes inserts of non-NULL keys into the child table to fail.
1692  #
1693  rename auth {}
1694  proc auth {args} {
1695    if {[lindex $args 1] == "long"} {return SQLITE_IGNORE}
1696    return SQLITE_OK
1697  }
1698  do_test without_rowid3-18.8 {
1699    catchsql { INSERT INTO short VALUES(1, 3, 2) }
1700  } {1 {FOREIGN KEY constraint failed}}
1701  do_test without_rowid3-18.9 {
1702    execsql { INSERT INTO short VALUES(1, 3, NULL) }
1703  } {}
1704  do_test without_rowid3-18.10 {
1705    execsql { SELECT * FROM short }
1706  } {1 3 2 1 3 {}}
1707  do_test without_rowid3-18.11 {
1708    catchsql { UPDATE short SET f = 2 WHERE f IS NULL }
1709  } {1 {FOREIGN KEY constraint failed}}
1710
1711  db auth {}
1712  unset authargs
1713}
1714
1715
1716do_test without_rowid3-19.1 {
1717  execsql {
1718    CREATE TABLE main(id INT PRIMARY KEY) WITHOUT rowid;
1719    CREATE TABLE sub(id INT REFERENCES main(id));
1720    INSERT INTO main VALUES(1);
1721    INSERT INTO main VALUES(2);
1722    INSERT INTO sub VALUES(2);
1723  }
1724} {}
1725do_test without_rowid3-19.2 {
1726  set S [sqlite3_prepare_v2 db "DELETE FROM main WHERE id = ?" -1 dummy]
1727  sqlite3_bind_int $S 1 2
1728  sqlite3_step $S
1729} {SQLITE_CONSTRAINT}
1730verify_ex_errcode without_rowid3-19.2b SQLITE_CONSTRAINT_FOREIGNKEY
1731do_test without_rowid3-19.3 {
1732  sqlite3_reset $S
1733} {SQLITE_CONSTRAINT}
1734verify_ex_errcode without_rowid3-19.3b SQLITE_CONSTRAINT_FOREIGNKEY
1735do_test without_rowid3-19.4 {
1736  sqlite3_bind_int $S 1 1
1737  sqlite3_step $S
1738} {SQLITE_DONE}
1739do_test without_rowid3-19.4 {
1740  sqlite3_finalize $S
1741} {SQLITE_OK}
1742
1743drop_all_tables
1744do_test without_rowid3-20.1 {
1745  execsql {
1746    CREATE TABLE pp(a PRIMARY KEY, b) WITHOUT rowid;
1747    CREATE TABLE cc(c PRIMARY KEY, d REFERENCES pp) WITHOUT rowid;
1748  }
1749} {}
1750
1751foreach {tn insert} {
1752  1 "INSERT"
1753  2 "INSERT OR IGNORE"
1754  3 "INSERT OR ABORT"
1755  4 "INSERT OR ROLLBACK"
1756  5 "INSERT OR REPLACE"
1757  6 "INSERT OR FAIL"
1758} {
1759  do_test without_rowid3-20.2.$tn.1 {
1760    catchsql "$insert INTO cc VALUES(1, 2)"
1761  } {1 {FOREIGN KEY constraint failed}}
1762  do_test without_rowid3-20.2.$tn.2 {
1763    execsql { SELECT * FROM cc }
1764  } {}
1765  do_test without_rowid3-20.2.$tn.3 {
1766    execsql {
1767      BEGIN;
1768        INSERT INTO pp VALUES(2, 'two');
1769        INSERT INTO cc VALUES(1, 2);
1770    }
1771    catchsql "$insert INTO cc VALUES(3, 4)"
1772  } {1 {FOREIGN KEY constraint failed}}
1773  do_test without_rowid3-20.2.$tn.4 {
1774    execsql { COMMIT ; SELECT * FROM cc }
1775  } {1 2}
1776  do_test without_rowid3-20.2.$tn.5 {
1777    execsql { DELETE FROM cc ; DELETE FROM pp }
1778  } {}
1779}
1780
1781foreach {tn update} {
1782  1 "UPDATE"
1783  2 "UPDATE OR IGNORE"
1784  3 "UPDATE OR ABORT"
1785  4 "UPDATE OR ROLLBACK"
1786  5 "UPDATE OR REPLACE"
1787  6 "UPDATE OR FAIL"
1788} {
1789  do_test without_rowid3-20.3.$tn.1 {
1790    execsql {
1791      INSERT INTO pp VALUES(2, 'two');
1792      INSERT INTO cc VALUES(1, 2);
1793    }
1794  } {}
1795  do_test without_rowid3-20.3.$tn.2 {
1796    catchsql "$update pp SET a = 1"
1797  } {1 {FOREIGN KEY constraint failed}}
1798  do_test without_rowid3-20.3.$tn.3 {
1799    execsql { SELECT * FROM pp }
1800  } {2 two}
1801  do_test without_rowid3-20.3.$tn.4 {
1802    catchsql "$update cc SET d = 1"
1803  } {1 {FOREIGN KEY constraint failed}}
1804  do_test without_rowid3-20.3.$tn.5 {
1805    execsql { SELECT * FROM cc }
1806  } {1 2}
1807  do_test without_rowid3-20.3.$tn.6 {
1808    execsql {
1809      BEGIN;
1810        INSERT INTO pp VALUES(3, 'three');
1811    }
1812    catchsql "$update pp SET a = 1 WHERE a = 2"
1813  } {1 {FOREIGN KEY constraint failed}}
1814  do_test without_rowid3-20.3.$tn.7 {
1815    execsql { COMMIT ; SELECT * FROM pp }
1816  } {2 two 3 three}
1817  do_test without_rowid3-20.3.$tn.8 {
1818    execsql {
1819      BEGIN;
1820        INSERT INTO cc VALUES(2, 2);
1821    }
1822    catchsql "$update cc SET d = 1 WHERE c = 1"
1823  } {1 {FOREIGN KEY constraint failed}}
1824  do_test without_rowid3-20.3.$tn.9 {
1825    execsql { COMMIT ; SELECT * FROM cc }
1826  } {1 2 2 2}
1827  do_test without_rowid3-20.3.$tn.10 {
1828    execsql { DELETE FROM cc ; DELETE FROM pp }
1829  } {}
1830}
1831
1832#-------------------------------------------------------------------------
1833# The following block of tests, those prefixed with "without_rowid3-genfkey.",
1834# are the same tests that were used to test the ".genfkey" command provided
1835# by the shell tool. So these tests show that the built-in foreign key
1836# implementation is more or less compatible with the triggers generated
1837# by genfkey.
1838#
1839drop_all_tables
1840do_test without_rowid3-genfkey.1.1 {
1841  execsql {
1842    CREATE TABLE t1(a INT PRIMARY KEY, b, c, UNIQUE(b, c)) WITHOUT rowid;
1843    CREATE TABLE t2(e REFERENCES t1, f);
1844    CREATE TABLE t3(g, h, i, FOREIGN KEY (h, i) REFERENCES t1(b, c));
1845  }
1846} {}
1847do_test without_rowid3-genfkey.1.2 {
1848  catchsql { INSERT INTO t2 VALUES(1, 2) }
1849} {1 {FOREIGN KEY constraint failed}}
1850do_test without_rowid3-genfkey.1.3 {
1851  execsql {
1852    INSERT INTO t1 VALUES(1, 2, 3);
1853    INSERT INTO t2 VALUES(1, 2);
1854  }
1855} {}
1856do_test without_rowid3-genfkey.1.4 {
1857  execsql { INSERT INTO t2 VALUES(NULL, 3) }
1858} {}
1859do_test without_rowid3-genfkey.1.5 {
1860  catchsql { UPDATE t2 SET e = 5 WHERE e IS NULL }
1861} {1 {FOREIGN KEY constraint failed}}
1862do_test without_rowid3-genfkey.1.6 {
1863  execsql { UPDATE t2 SET e = 1 WHERE e IS NULL }
1864} {}
1865do_test without_rowid3-genfkey.1.7 {
1866  execsql { UPDATE t2 SET e = NULL WHERE f = 3 }
1867} {}
1868do_test without_rowid3-genfkey.1.8 {
1869  catchsql { UPDATE t1 SET a = 10 }
1870} {1 {FOREIGN KEY constraint failed}}
1871do_test without_rowid3-genfkey.1.9 {
1872  catchsql { UPDATE t1 SET a = NULL }
1873} {1 {NOT NULL constraint failed: t1.a}}
1874do_test without_rowid3-genfkey.1.10 {
1875  catchsql { DELETE FROM t1 }
1876} {1 {FOREIGN KEY constraint failed}}
1877do_test without_rowid3-genfkey.1.11 {
1878  execsql { UPDATE t2 SET e = NULL }
1879} {}
1880do_test without_rowid3-genfkey.1.12 {
1881  execsql {
1882    UPDATE t1 SET a = 10;
1883    DELETE FROM t1;
1884    DELETE FROM t2;
1885  }
1886} {}
1887do_test without_rowid3-genfkey.1.13 {
1888  execsql {
1889    INSERT INTO t3 VALUES(1, NULL, NULL);
1890    INSERT INTO t3 VALUES(1, 2, NULL);
1891    INSERT INTO t3 VALUES(1, NULL, 3);
1892  }
1893} {}
1894do_test without_rowid3-genfkey.1.14 {
1895  catchsql { INSERT INTO t3 VALUES(3, 1, 4) }
1896} {1 {FOREIGN KEY constraint failed}}
1897do_test without_rowid3-genfkey.1.15 {
1898  execsql {
1899    INSERT INTO t1 VALUES(1, 1, 4);
1900    INSERT INTO t3 VALUES(3, 1, 4);
1901  }
1902} {}
1903do_test without_rowid3-genfkey.1.16 {
1904  catchsql { DELETE FROM t1 }
1905} {1 {FOREIGN KEY constraint failed}}
1906do_test without_rowid3-genfkey.1.17 {
1907  catchsql { UPDATE t1 SET b = 10}
1908} {1 {FOREIGN KEY constraint failed}}
1909do_test without_rowid3-genfkey.1.18 {
1910  execsql { UPDATE t1 SET a = 10}
1911} {}
1912do_test without_rowid3-genfkey.1.19 {
1913  catchsql { UPDATE t3 SET h = 'hello' WHERE i = 3}
1914} {1 {FOREIGN KEY constraint failed}}
1915
1916drop_all_tables
1917do_test without_rowid3-genfkey.2.1 {
1918  execsql {
1919    CREATE TABLE t1(a INT PRIMARY KEY, b, c, UNIQUE(b, c)) WITHOUT rowid;
1920    CREATE TABLE t2(e REFERENCES t1 ON UPDATE CASCADE ON DELETE CASCADE, f);
1921    CREATE TABLE t3(g, h, i,
1922        FOREIGN KEY (h, i)
1923        REFERENCES t1(b, c) ON UPDATE CASCADE ON DELETE CASCADE
1924    );
1925  }
1926} {}
1927do_test without_rowid3-genfkey.2.2 {
1928  execsql {
1929    INSERT INTO t1 VALUES(1, 2, 3);
1930    INSERT INTO t1 VALUES(4, 5, 6);
1931    INSERT INTO t2 VALUES(1, 'one');
1932    INSERT INTO t2 VALUES(4, 'four');
1933  }
1934} {}
1935do_test without_rowid3-genfkey.2.3 {
1936  execsql {
1937    UPDATE t1 SET a = 2 WHERE a = 1;
1938    SELECT * FROM t2;
1939  }
1940} {2 one 4 four}
1941do_test without_rowid3-genfkey.2.4 {
1942  execsql {
1943    DELETE FROM t1 WHERE a = 4;
1944    SELECT * FROM t2;
1945  }
1946} {2 one}
1947
1948do_test without_rowid3-genfkey.2.5 {
1949  execsql {
1950    INSERT INTO t3 VALUES('hello', 2, 3);
1951    UPDATE t1 SET c = 2;
1952    SELECT * FROM t3;
1953  }
1954} {hello 2 2}
1955do_test without_rowid3-genfkey.2.6 {
1956  execsql {
1957    DELETE FROM t1;
1958    SELECT * FROM t3;
1959  }
1960} {}
1961
1962drop_all_tables
1963do_test without_rowid3-genfkey.3.1 {
1964  execsql {
1965    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(c, b)) WITHOUT rowid;
1966    CREATE TABLE t2(e REFERENCES t1 ON UPDATE SET NULL ON DELETE SET NULL, f);
1967    CREATE TABLE t3(g, h, i,
1968        FOREIGN KEY (h, i)
1969        REFERENCES t1(b, c) ON UPDATE SET NULL ON DELETE SET NULL
1970    );
1971  }
1972} {}
1973do_test without_rowid3-genfkey.3.2 {
1974  execsql {
1975    INSERT INTO t1 VALUES(1, 2, 3);
1976    INSERT INTO t1 VALUES(4, 5, 6);
1977    INSERT INTO t2 VALUES(1, 'one');
1978    INSERT INTO t2 VALUES(4, 'four');
1979  }
1980} {}
1981do_test without_rowid3-genfkey.3.3 {
1982  execsql {
1983    UPDATE t1 SET a = 2 WHERE a = 1;
1984    SELECT * FROM t2;
1985  }
1986} {{} one 4 four}
1987do_test without_rowid3-genfkey.3.4 {
1988  execsql {
1989    DELETE FROM t1 WHERE a = 4;
1990    SELECT * FROM t2;
1991  }
1992} {{} one {} four}
1993do_test without_rowid3-genfkey.3.5 {
1994  execsql {
1995    INSERT INTO t3 VALUES('hello', 2, 3);
1996    UPDATE t1 SET c = 2;
1997    SELECT * FROM t3;
1998  }
1999} {hello {} {}}
2000do_test without_rowid3-genfkey.3.6 {
2001  execsql {
2002    UPDATE t3 SET h = 2, i = 2;
2003    DELETE FROM t1;
2004    SELECT * FROM t3;
2005  }
2006} {hello {} {}}
2007
2008#-------------------------------------------------------------------------
2009# Verify that ticket dd08e5a988d00decc4a543daa8dbbfab9c577ad8 has been
2010# fixed.
2011#
2012do_test without_rowid3-dd08e5.1.1 {
2013  execsql {
2014    PRAGMA foreign_keys=ON;
2015    CREATE TABLE tdd08(a INTEGER PRIMARY KEY, b) WITHOUT rowid;
2016    CREATE UNIQUE INDEX idd08 ON tdd08(a,b);
2017    INSERT INTO tdd08 VALUES(200,300);
2018
2019    CREATE TABLE tdd08_b(w,x,y, FOREIGN KEY(x,y) REFERENCES tdd08(a,b));
2020    INSERT INTO tdd08_b VALUES(100,200,300);
2021  }
2022} {}
2023do_test without_rowid3-dd08e5.1.2 {
2024  catchsql {
2025    DELETE FROM tdd08;
2026  }
2027} {1 {FOREIGN KEY constraint failed}}
2028do_test without_rowid3-dd08e5.1.3 {
2029  execsql {
2030    SELECT * FROM tdd08;
2031  }
2032} {200 300}
2033do_test without_rowid3-dd08e5.1.4 {
2034  catchsql {
2035    INSERT INTO tdd08_b VALUES(400,500,300);
2036  }
2037} {1 {FOREIGN KEY constraint failed}}
2038do_test without_rowid3-dd08e5.1.5 {
2039  catchsql {
2040    UPDATE tdd08_b SET x=x+1;
2041  }
2042} {1 {FOREIGN KEY constraint failed}}
2043do_test without_rowid3-dd08e5.1.6 {
2044  catchsql {
2045    UPDATE tdd08 SET a=a+1;
2046  }
2047} {1 {FOREIGN KEY constraint failed}}
2048
2049#-------------------------------------------------------------------------
2050# Verify that ticket ce7c133ea6cc9ccdc1a60d80441f80b6180f5eba
2051# fixed.
2052#
2053do_test without_rowid3-ce7c13.1.1 {
2054  execsql {
2055    CREATE TABLE tce71(a INTEGER PRIMARY KEY, b) WITHOUT rowid;
2056    CREATE UNIQUE INDEX ice71 ON tce71(a,b);
2057    INSERT INTO tce71 VALUES(100,200);
2058    CREATE TABLE tce72(w, x, y, FOREIGN KEY(x,y) REFERENCES tce71(a,b));
2059    INSERT INTO tce72 VALUES(300,100,200);
2060    UPDATE tce71 set b = 200 where a = 100;
2061    SELECT * FROM tce71, tce72;
2062  }
2063} {100 200 300 100 200}
2064do_test without_rowid3-ce7c13.1.2 {
2065  catchsql {
2066    UPDATE tce71 set b = 201 where a = 100;
2067  }
2068} {1 {FOREIGN KEY constraint failed}}
2069do_test without_rowid3-ce7c13.1.3 {
2070  catchsql {
2071    UPDATE tce71 set a = 101 where a = 100;
2072  }
2073} {1 {FOREIGN KEY constraint failed}}
2074do_test without_rowid3-ce7c13.1.4 {
2075  execsql {
2076    CREATE TABLE tce73(a INTEGER PRIMARY KEY, b, UNIQUE(a,b)) WITHOUT rowid;
2077    INSERT INTO tce73 VALUES(100,200);
2078    CREATE TABLE tce74(w, x, y, FOREIGN KEY(x,y) REFERENCES tce73(a,b));
2079    INSERT INTO tce74 VALUES(300,100,200);
2080    UPDATE tce73 set b = 200 where a = 100;
2081    SELECT * FROM tce73, tce74;
2082  }
2083} {100 200 300 100 200}
2084do_test without_rowid3-ce7c13.1.5 {
2085  catchsql {
2086    UPDATE tce73 set b = 201 where a = 100;
2087  }
2088} {1 {FOREIGN KEY constraint failed}}
2089do_test without_rowid3-ce7c13.1.6 {
2090  catchsql {
2091    UPDATE tce73 set a = 101 where a = 100;
2092  }
2093} {1 {FOREIGN KEY constraint failed}}
2094
2095# Confirm that changes() works on WITHOUT ROWID tables that use the
2096# xfer optimization.
2097#
2098db close
2099sqlite3 db :memory:
2100do_execsql_test without_rowid3-30.1 {
2101  CREATE TABLE t1(a,b,PRIMARY KEY(a,b)) WITHOUT ROWID;
2102  CREATE TABLE t2(a,b,PRIMARY KEY(a,b)) WITHOUT ROWID;
2103  INSERT INTO t1 VALUES(1,2),(3,4),(5,6);
2104  SELECT changes();
2105} {3}
2106do_execsql_test without_rowid3-30.2 {
2107  INSERT INTO t2 SELECT * FROM t1;
2108  SELECT changes();
2109} {3}
2110
2111finish_test
2112