modernc.org/cc@v1.0.1/v2/testdata/_sqlite/test/without_rowid3.test (about)

     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 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  
    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 FROM 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 "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  #
   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 REFERENCES 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 temp.sqlite_master WHERE name='t2';
  1035      }
  1036    } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES 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 temp.sqlite_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 REFERENCES 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 scans 
  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_changes"
  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 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 {}}
  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  # Confirm that changes() works on WITHOUT ROWID tables that use the
  2085  # xfer optimization.
  2086  #
  2087  db close
  2088  sqlite3 db :memory:
  2089  do_execsql_test without_rowid3-30.1 {
  2090    CREATE TABLE t1(a,b,PRIMARY KEY(a,b)) WITHOUT ROWID;
  2091    CREATE TABLE t2(a,b,PRIMARY KEY(a,b)) WITHOUT ROWID;
  2092    INSERT INTO t1 VALUES(1,2),(3,4),(5,6);
  2093    SELECT changes();
  2094  } {3}
  2095  do_execsql_test without_rowid3-30.2 {
  2096    INSERT INTO t2 SELECT * FROM t1;
  2097    SELECT changes();
  2098  } {3}
  2099  
  2100  finish_test