From: dan Date: Thu, 24 Sep 2009 18:19:41 +0000 (+0000) Subject: Fixes and test cases to make sure the affinity and collation sequence associated... X-Git-Tag: fts3-refactor~148 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=140026bdb544add1dce781360d0acf3d76c30c71;p=thirdparty%2Fsqlite.git Fixes and test cases to make sure the affinity and collation sequence associated with the parent key is used when comparing it with a child key value. FossilOrigin-Name: 76e8e74b49be4c80b9fb20d52e9b39db8001362e --- diff --git a/manifest b/manifest index 582aa5b872..f9e2d72fee 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 4c97bc684d..a08ff0d621 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -beb2094f94849c66d98bab5999ff474cd91eea11 \ No newline at end of file +76e8e74b49be4c80b9fb20d52e9b39db8001362e \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index dbf8b0c777..f81c6a8e23 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -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; iisDeferred && !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 ); diff --git a/test/fkey2.test b/test/fkey2.test index 2715b2226a..826c0f8eba 100644 --- a/test/fkey2.test +++ b/test/fkey2.test @@ -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.