]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix minor problems with foreign key constraints where the parent table is the same...
authordan <dan@noemail.net>
Fri, 10 Jun 2011 16:33:25 +0000 (16:33 +0000)
committerdan <dan@noemail.net>
Fri, 10 Jun 2011 16:33:25 +0000 (16:33 +0000)
FossilOrigin-Name: 442d8d8bfe443797482354ba8766d97d3d6acaae

manifest
manifest.uuid
src/fkey.c
test/fkey3.test

index ded9d9cb63e482aad0ffe4c780696fac3f537c01..79636217b094007bac1bcc852a6781a424ee3543 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sline\sin\spcache1.c\swhere\sa\sglobal\sdata\sstructure\sis\saccessed\swithout\susing\sthe\sGLOBAL()\smacro.\sThis\scauses\sa\ssubtle\smalfunction\son\stest\ssystems\sthat\suse\sSQLITE_OMIT_WSD.
-D 2011-06-09T17:53:43.990
+C Fix\sminor\sproblems\swith\sforeign\skey\sconstraints\swhere\sthe\sparent\stable\sis\sthe\ssame\sas\sthe\schild\stable.
+D 2011-06-10T16:33:25.121
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 11dcc00a8d0e5202def00e81732784fb0cc4fe1d
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -133,7 +133,7 @@ F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b
 F src/delete.c cecc926c70783452f3e8eb452c728291ce1a0b21
 F src/expr.c ab46ab0f0c44979a8164ca31728d7d10ae5e8106
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
-F src/fkey.c a43ba8a005fb5efd1deeee06853e3a6120d46a91
+F src/fkey.c 9fabba17a4d4778dc660f0cb9d781fc86d7b9d41
 F src/func.c b9117e40975245b8504cf3625d7e321d8d4b63dc
 F src/global.c 29bfb85611dd816b04f10fba0ca910366e128d38
 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
@@ -398,7 +398,7 @@ F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
 F test/filefmt.test f178cfc29501a14565954c961b226e61877dd32c
 F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
 F test/fkey2.test 080969fe219b3b082b0e097ac18c6af2e5b0631f
-F test/fkey3.test 42f88d6048d8dc079e2a8cf7baad1cc1483a7620
+F test/fkey3.test 0c4d36b6d5b88f2c233cf8a512d3e2eaedc06fd6
 F test/fkey4.test c6c8f9f9be885f95c85c7bceb26f243ad906fd49
 F test/fkey_malloc.test a5ede29bd2f6e56dea78c3d43fb86dd696c068c8
 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@@ -942,7 +942,7 @@ F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
 F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d
-P 095cd9a6ec175b703ff3fcafeffb3349f21bd831
-R 7c10b21d6dc959e0ea4f54033f3d408b
+P b11b2e1f8ccadf78bebe2278f05a8e3d3e543328
+R 82679520a5c6b1fbd50bacf672964c79
 U dan
-Z e98f319e77bc2f43df3a70aff2c9cf53
+Z 3e44af2707cf5eb06c1e283bd2e9d2ca
index 4449540538b1859a39e33fcd1aac1db863bcbe4a..3b5ddc572a948c80502ad2fbb5304012b8fb8cf1 100644 (file)
@@ -1 +1 @@
-b11b2e1f8ccadf78bebe2278f05a8e3d3e543328
\ No newline at end of file
+442d8d8bfe443797482354ba8766d97d3d6acaae
\ No newline at end of file
index 34fdfda5d94636c2194cc3a1926128fea9dbea40..dda8a50d44b843ec8ef426360817d98cca8a6ed0 100644 (file)
@@ -386,13 +386,25 @@ static void fkLookupParent(
       /* If the parent table is the same as the child table, and we are about
       ** to increment the constraint-counter (i.e. this is an INSERT operation),
       ** then check if the row being inserted matches itself. If so, do not
-      ** increment the constraint-counter.  */
+      ** increment the constraint-counter. 
+      **
+      ** If any of the parent-key values are NULL, then the row cannot match 
+      ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
+      ** of the parent-key values are NULL (at this point it is known that
+      ** none of the child key values are).
+      */
       if( pTab==pFKey->pFrom && nIncr==1 ){
         int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
         for(i=0; i<nCol; i++){
           int iChild = aiCol[i]+1+regData;
           int iParent = pIdx->aiColumn[i]+1+regData;
+          assert( aiCol[i]!=pTab->iPKey );
+          if( pIdx->aiColumn[i]==pTab->iPKey ){
+            /* The parent key is a composite key that includes the IPK column */
+            iParent = regData;
+          }
           sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
+          sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
         }
         sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
       }
index 88b5aad370e225b42634e542f1107cb6c972fe7e..2df3be530ed9125120457bcbedef4d77c9a0ee35 100644 (file)
@@ -21,6 +21,8 @@ ifcapable {!foreignkey||!trigger} {
   return
 }
 
+set testprefix fkey3
+
 # Create a table and some data to work with.
 #
 do_test fkey3-1.1 {
@@ -77,4 +79,79 @@ do_test fkey3-2.1 {
   }
 } {1 100 1 101 2 100 2 101}
 
+
+#-------------------------------------------------------------------------
+# The following tests - fkey-3.* - test some edge cases to do with 
+# inserting rows into tables that have foreign keys where the parent
+# table is the same as the child table. Especially cases where the
+# new row being inserted matches itself.
+#
+do_execsql_test 3.1.1 {
+  CREATE TABLE t3(a, b, c, d, 
+    UNIQUE(a, b),
+    FOREIGN KEY(c, d) REFERENCES t3(a, b)
+  );
+  INSERT INTO t3 VALUES(1, 2, 1, 2);
+} {}
+do_catchsql_test 3.1.2 {
+  INSERT INTO t3 VALUES(NULL, 2, 5, 2);
+} {1 {foreign key constraint failed}}
+do_catchsql_test 3.1.3 {
+  INSERT INTO t3 VALUES(NULL, 3, 5, 2);
+} {1 {foreign key constraint failed}}
+
+do_execsql_test 3.2.1 {
+  CREATE TABLE t4(a UNIQUE, b REFERENCES t4(a));
+}
+do_catchsql_test 3.2.2 {
+  INSERT INTO t4 VALUES(NULL, 1);
+} {1 {foreign key constraint failed}}
+
+do_execsql_test 3.3.1 {
+  CREATE TABLE t5(a INTEGER PRIMARY KEY, b REFERENCES t5(a));
+  INSERT INTO t5 VALUES(NULL, 1);
+} {}
+do_catchsql_test 3.3.2 {
+  INSERT INTO t5 VALUES(NULL, 3);
+} {1 {foreign key constraint failed}}
+
+do_execsql_test 3.4.1 {
+  CREATE TABLE t6(a INTEGER PRIMARY KEY, b, c, d,
+    FOREIGN KEY(c, d) REFERENCES t6(a, b)
+  );
+  CREATE UNIQUE INDEX t6i ON t6(b, a);
+}
+do_execsql_test 3.4.2  { INSERT INTO t6 VALUES(NULL, 'a', 1, 'a'); } {}
+do_execsql_test 3.4.3  { INSERT INTO t6 VALUES(2, 'a', 2, 'a');    } {}
+do_execsql_test 3.4.4  { INSERT INTO t6 VALUES(NULL, 'a', 1, 'a'); } {}
+do_execsql_test 3.4.5  { INSERT INTO t6 VALUES(5, 'a', 2, 'a'); } {}
+do_catchsql_test 3.4.6 { 
+  INSERT INTO t6 VALUES(NULL, 'a', 65, 'a');    
+} {1 {foreign key constraint failed}}
+
+do_execsql_test 3.4.7 {
+  INSERT INTO t6 VALUES(100, 'one', 100, 'one');
+  DELETE FROM t6 WHERE a = 100;
+}
+do_execsql_test 3.4.8 {
+  INSERT INTO t6 VALUES(100, 'one', 100, 'one');
+  UPDATE t6 SET c = 1, d = 'a' WHERE a = 100;
+  DELETE FROM t6 WHERE a = 100;
+}
+
+do_execsql_test 3.5.1 {
+  CREATE TABLE t7(a, b, c, d INTEGER PRIMARY KEY,
+    FOREIGN KEY(c, d) REFERENCES t7(a, b)
+  );
+  CREATE UNIQUE INDEX t7i ON t7(a, b);
+}
+do_execsql_test 3.5.2  { INSERT INTO t7 VALUES('x', 1, 'x', NULL) } {}
+do_execsql_test 3.5.3  { INSERT INTO t7 VALUES('x', 2, 'x', 2) } {}
+do_catchsql_test 3.5.4  { 
+  INSERT INTO t7 VALUES('x', 450, 'x', NULL);
+} {1 {foreign key constraint failed}}
+do_catchsql_test 3.5.5  { 
+  INSERT INTO t7 VALUES('x', 450, 'x', 451);
+} {1 {foreign key constraint failed}}
+
 finish_test