]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fixes and test cases to make sure the affinity and collation sequence associated...
authordan <dan@noemail.net>
Thu, 24 Sep 2009 18:19:41 +0000 (18:19 +0000)
committerdan <dan@noemail.net>
Thu, 24 Sep 2009 18:19:41 +0000 (18:19 +0000)
FossilOrigin-Name: 76e8e74b49be4c80b9fb20d52e9b39db8001362e

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

index 582aa5b87243849dce217880f32b4001fae4c2fb..f9e2d72fee435c5cd7e5b483593f401f6c59daca 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sbug\sin\sthe\scode\sfor\sREPLACE\sconflict\shandling\son\sIPK\scolumns\swhen\sthere\sare\sno\sindexes\son\sthe\stable.\sTriggers\sand\sforeign\skey\sprocessing\swere\sbeing\sbypassed.
-D 2009-09-24T16:52:28
+C Fixes\sand\stest\scases\sto\smake\ssure\sthe\saffinity\sand\scollation\ssequence\sassociated\swith\sthe\sparent\skey\sis\sused\swhen\scomparing\sit\swith\sa\schild\skey\svalue.
+D 2009-09-24T18:19:42
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -116,7 +116,7 @@ F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638
 F src/delete.c 2a3d6fc0861b2f8dbd9feb7847b390267b281c60
 F src/expr.c c7f3f718bd5c392344ec8694a41c1824f30cf375
 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
-F src/fkey.c d5610f840b76e7b478d9700df9f3be0ab96ba1b8
+F src/fkey.c 5ec139b6d22a981a777fb195d9311068f5a8c75b
 F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606
 F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
 F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
@@ -330,7 +330,7 @@ F test/expr.test 9f521ae22f00e074959f72ce2e55d46b9ed23f68
 F test/filectrl.test 8923a6dc7630f31c8a9dd3d3d740aa0922df7bf8
 F test/filefmt.test 84e3d0fe9f12d0d2ac852465c6f8450aea0d6f43
 F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
-F test/fkey2.test 30dedac189b10da51c0cbdee84e334ed3119b8f0
+F test/fkey2.test c81035086cec3014838c0af60b3fc228c3875214
 F test/fkey3.test 2183cac9075f3aae4875106eb9255bb73618444e
 F test/fkey_malloc.test da912d000bb6ceb1cd11b655de1989762fa71ceb
 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@@ -755,7 +755,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 8a000a8aae4d356e68acf2bc1788d2c40279522c
-R 1cd4e9cb0400f55e65581cc0c3e21846
+P beb2094f94849c66d98bab5999ff474cd91eea11
+R b4aeb3f8101f131cf6580b25c102b171
 U dan
-Z 294416087638c741514386eadd008bb9
+Z be9e9a4e87b8676ab6aa8bb0309f6406
index 4c97bc684d0ab7b9b00bf62562fdad731d6528c3..a08ff0d6216296e21fa251be3586658230a3c73e 100644 (file)
@@ -1 +1 @@
-beb2094f94849c66d98bab5999ff474cd91eea11
\ No newline at end of file
+76e8e74b49be4c80b9fb20d52e9b39db8001362e
\ No newline at end of file
index dbf8b0c7774d39af7881e92f48f4916b33567521..f81c6a8e238ae2331d6be288c23ace869483bca0 100644 (file)
@@ -310,34 +310,40 @@ static void fkLookupParent(
   if( pIdx==0 ){
     /* If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY
     ** column of the parent table (table pTab).  */
-    int iReg = aiCol[0] + regData + 1;
+    int regTemp = sqlite3GetTempReg(pParse);
+
+    /* Invoke MustBeInt to coerce the child key value to an integer (i.e. 
+    ** apply the affinity of the parent key). If this fails, then there
+    ** is no matching parent key. Before using MustBeInt, make a copy of
+    ** the value. Otherwise, the value inserted into the child key column
+    ** will have INTEGER affinity applied to it, which may not be correct.  */
+    sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
+    sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
     sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
-    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iReg);
+    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp);
     sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
     sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
+    sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-4);
+    sqlite3ReleaseTempReg(pParse, regTemp);
+    assert( 
+      sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v)-4)->opcode==OP_MustBeInt 
+    );
   }else{
+    int nCol = pFKey->nCol;
+    int regTemp = sqlite3GetTempRange(pParse, nCol);
     int regRec = sqlite3GetTempReg(pParse);
     KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
 
     sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
     sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
-
-    if( pFKey->nCol>1 ){
-      int nCol = pFKey->nCol;
-      int regTemp = sqlite3GetTempRange(pParse, nCol);
-      for(i=0; i<nCol; i++){ 
-        sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[i]+1+regData, regTemp+i);
-      }
-      sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
-      sqlite3ReleaseTempRange(pParse, regTemp, nCol);
-    }else{
-      int iReg = aiCol[0] + regData + 1;
-      sqlite3VdbeAddOp3(v, OP_MakeRecord, iReg, 1, regRec);
-      sqlite3IndexAffinityStr(v, pIdx);
+    for(i=0; i<nCol; i++){ 
+      sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[i]+1+regData, regTemp+i);
     }
-
+    sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
+    sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0);
     sqlite3VdbeAddOp3(v, OP_Found, iCur, iOk, regRec);
     sqlite3ReleaseTempReg(pParse, regRec);
+    sqlite3ReleaseTempRange(pParse, regTemp, nCol);
   }
 
   if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
@@ -408,7 +414,16 @@ static void fkScanChildren(
 
     pLeft = sqlite3Expr(db, TK_REGISTER, 0);
     if( pLeft ){
-      pLeft->iTable = (pIdx ? (regData+pIdx->aiColumn[i]+1) : regData);
+      if( pIdx ){
+        int iCol = pIdx->aiColumn[i];
+        Column *pCol = &pIdx->pTable->aCol[iCol];
+        pLeft->iTable = regData+iCol+1;
+        pLeft->affinity = pCol->affinity;
+        pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl);
+      }else{
+        pLeft->iTable = regData;
+        pLeft->affinity = SQLITE_AFF_INTEGER;
+      }
     }
     iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
     assert( iCol>=0 );
index 2715b2226a5f9e2989888d9bc01fe0ea32049a0d..826c0f8eba8882f9934a8571d567436e07b78df5 100644 (file)
@@ -119,6 +119,7 @@ set FkeySimpleTests {
   4.11 "DELETE FROM t7 WHERE b=1"         {1 {foreign key constraint failed}}
   4.12 "UPDATE t7 SET b = 2"              {1 {foreign key constraint failed}}
   4.13 "UPDATE t7 SET b = 1"              {0 {}}
+  4.14 "INSERT INTO t8 VALUES('a', 'b')"  {1 {foreign key constraint failed}}
 
   5.1  "INSERT INTO t9 VALUES(1, 3)"      {1 {no such table: main.nosuchtable}}
   5.2  "INSERT INTO t10 VALUES(1, 3)"     {1 {foreign key mismatch}}
@@ -151,6 +152,50 @@ foreach {tn zSql res} $FkeySimpleTests {
 execsql { PRAGMA count_changes = 0 }
 drop_all_tables
 
+# Special test: When the parent key is an IPK, make sure the affinity of
+# the IPK is not applied to the child key value before it is inserted
+# into the child table.
+do_test fkey2-1.4.1 {
+  execsql {
+    CREATE TABLE i(i INTEGER PRIMARY KEY);
+    CREATE TABLE j(j REFERENCES i);
+    INSERT INTO i VALUES(35);
+    INSERT INTO j VALUES('35.0');
+    SELECT j, typeof(j) FROM j;
+  }
+} {35.0 text}
+do_test fkey2-1.4.2 {
+  catchsql { DELETE FROM i }
+} {1 {foreign key constraint failed}}
+
+# Same test using a regular primary key with integer affinity.
+drop_all_tables
+do_test fkey2-1.5.1 {
+  execsql {
+    CREATE TABLE i(i INT UNIQUE);
+    CREATE TABLE j(j REFERENCES i(i));
+    INSERT INTO i VALUES('35.0');
+    INSERT INTO j VALUES('35.0');
+    SELECT j, typeof(j) FROM j;
+    SELECT i, typeof(i) FROM i;
+  }
+} {35.0 text 35 integer}
+do_test fkey2-1.5.2 {
+  catchsql { DELETE FROM i }
+} {1 {foreign key constraint failed}}
+
+# Use a collation sequence on the parent key.
+drop_all_tables
+do_test fkey2-1.5.1 {
+  execsql {
+    CREATE TABLE i(i TEXT COLLATE nocase PRIMARY KEY);
+    CREATE TABLE j(j TEXT COLLATE binary REFERENCES i(i));
+    INSERT INTO i VALUES('SQLite');
+    INSERT INTO j VALUES('sqlite');
+  }
+  catchsql { DELETE FROM i }
+} {1 {foreign key constraint failed}}
+
 #-------------------------------------------------------------------------
 # This section (test cases fkey2-2.*) contains tests to check that the
 # deferred foreign key constraint logic works.