From: dan Date: Tue, 11 Apr 2017 19:58:55 +0000 (+0000) Subject: Avoid updating unaffected indexes on a table as part of an UPDATE that requires X-Git-Tag: version-3.19.0~70^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Ffkey-optimization;p=thirdparty%2Fsqlite.git Avoid updating unaffected indexes on a table as part of an UPDATE that requires foreign key processing in some cases. FossilOrigin-Name: 477bea9ed0dd0fa69896bfd16d9b1d22170cbab784e3279ce65c29c47e032f34 --- diff --git a/manifest b/manifest index e085e3f18c..103f117e15 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Limit\sthe\sdepth\sof\srecursion\sfor\svalid\sJSON\sin\sthe\sJSON1\sextension\sin\sorder\nto\savoid\susing\sexcess\sstack\sspace\sin\sthe\srecursive\sdescent\sparser.\nFix\sfor\sticket\s[981329adeef51011052667a9]. -D 2017-04-11T18:55:05.542 +C Avoid\supdating\sunaffected\sindexes\son\sa\stable\sas\spart\sof\san\sUPDATE\sthat\srequires\nforeign\skey\sprocessing\sin\ssome\scases. +D 2017-04-11T19:58:55.816 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a @@ -356,7 +356,7 @@ F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c F src/expr.c f6572c7690fa619e85b1192b683ccc30cd123363415963c061ada3770b18f6a7 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 -F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae +F src/fkey.c db65492ae549c3b548c9ef1f279ce1684f1c473b116e1c56a90878cd5dcf968d F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174 F src/global.c 4a34512d82fc5aa13c802db06bcfff5e1d3de955 F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd @@ -464,7 +464,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5 F src/treeview.c 84d0ac737e1231702679f0289180021e19c5cc186ec413e8dcb704a887c76ec8 F src/trigger.c c9f0810043b265724fdb1bdd466894f984dfc182 -F src/update.c 456d4a4656f8a03c2abc88a51b19172197400e58 +F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6 F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569 @@ -1571,7 +1571,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 76cd611d41465fcec61c21520d55172cb236530f38386b7d4a5544ba87de2353 -R 4121191f9cbabfb85c1e92872e6e98a5 -U drh -Z 8a8f0ee4e24e0270c8727f53d830c8c6 +P 1f68c184596912d742b50b1ca38252a9e783aacf121619a27b17a7ae9f6df041 +R 64d829e1406f8fce120ec976a7526a63 +T *branch * fkey-optimization +T *sym-fkey-optimization * +T -sym-trunk * +U dan +Z 11630915b607d65a1bf3ba20257e205b diff --git a/manifest.uuid b/manifest.uuid index fa40f168fa..b8b2d6e02b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1f68c184596912d742b50b1ca38252a9e783aacf121619a27b17a7ae9f6df041 \ No newline at end of file +477bea9ed0dd0fa69896bfd16d9b1d22170cbab784e3279ce65c29c47e032f34 \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index cb78764f51..f91a6de547 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1087,8 +1087,16 @@ u32 sqlite3FkOldmask( ** UPDATE statement modifies the rowid fields of the table. ** ** If any foreign key processing will be required, this function returns -** true. If there is no foreign key related processing, this function -** returns false. +** non-zero. If there is no foreign key related processing, this function +** returns zero. +** +** For an UPDATE, this function returns 2 if: +** +** * There are any FKs for which pTab is the child and the parent table, or +** * the UPDATE modifies one or more parent keys for which the action is +** not "NO ACTION" (i.e. is CASCADE, SET DEFAULT or SET NULL). +** +** Or, assuming some other foreign key processing is required, 1. */ int sqlite3FkRequired( Parse *pParse, /* Parse context */ @@ -1096,12 +1104,13 @@ int sqlite3FkRequired( int *aChange, /* Non-NULL for UPDATE operations */ int chngRowid /* True for UPDATE that affects rowid */ ){ + int eRet = 0; if( pParse->db->flags&SQLITE_ForeignKeys ){ if( !aChange ){ /* A DELETE operation. Foreign key processing is required if the ** table in question is either the child or parent table for any ** foreign key constraint. */ - return (sqlite3FkReferences(pTab) || pTab->pFKey); + eRet = (sqlite3FkReferences(pTab) || pTab->pFKey); }else{ /* This is an UPDATE. Foreign key processing is only required if the ** operation modifies one or more child or parent key columns. */ @@ -1109,16 +1118,22 @@ int sqlite3FkRequired( /* Check if any child key columns are being modified. */ for(p=pTab->pFKey; p; p=p->pNextFrom){ - if( fkChildIsModified(pTab, p, aChange, chngRowid) ) return 1; + if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) return 2; + if( fkChildIsModified(pTab, p, aChange, chngRowid) ){ + eRet = 1; + } } /* Check if any parent key columns are being modified. */ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ - if( fkParentIsModified(pTab, p, aChange, chngRowid) ) return 1; + if( fkParentIsModified(pTab, p, aChange, chngRowid) ){ + if( p->aAction[1]!=OE_None ) return 2; + eRet = 1; + } } } } - return 0; + return eRet; } /* diff --git a/src/update.c b/src/update.c index 8fca7eb988..fa8885be66 100644 --- a/src/update.c +++ b/src/update.c @@ -285,7 +285,7 @@ void sqlite3Update( */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int reg; - if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){ + if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; }else{ @@ -640,7 +640,7 @@ void sqlite3Update( assert( regNew==regNewRowid+1 ); #ifdef SQLITE_ENABLE_PREUPDATE_HOOK sqlite3VdbeAddOp3(v, OP_Delete, iDataCur, - OPFLAG_ISUPDATE | ((hasFK || chngKey) ? 0 : OPFLAG_ISNOOP), + OPFLAG_ISUPDATE | ((hasFK>1 || chngKey) ? 0 : OPFLAG_ISNOOP), regNewRowid ); if( eOnePass==ONEPASS_MULTI ){ @@ -651,7 +651,7 @@ void sqlite3Update( sqlite3VdbeAppendP4(v, pTab, P4_TABLE); } #else - if( hasFK || chngKey ){ + if( hasFK>1 || chngKey ){ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); } #endif