From: drh Date: Fri, 13 Apr 2018 13:44:48 +0000 (+0000) Subject: Improved conflict-target matching logic. X-Git-Tag: version-3.24.0~146^2~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3b45d8bfb789a492afa6fabbea6ed2bbc0083870;p=thirdparty%2Fsqlite.git Improved conflict-target matching logic. FossilOrigin-Name: 98d32ba661f4ba662b639994b74352b695d53a33bc8a498bd09b9e02f794c81e --- diff --git a/manifest b/manifest index 0377bbe3c6..9b3751834a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Back\soff\sof\sthe\sextended\supsert\ssyntax\sthat\sallows\smultiple\sON\sCONFLICT\nclauses.\s\sThe\ssyntax\snow\sis\sexactly\sas\sin\sPostgreSQL\sand\sMySQL.\s\sAdd\ssupport\nfor\sWHERE\sclauses\son\sthe\sconflict-target\sphrase,\sfor\spartial\sindexes. -D 2018-04-13T13:06:45.203 +C Improved\sconflict-target\smatching\slogic. +D 2018-04-13T13:44:48.035 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -557,7 +557,7 @@ F src/tokenize.c 5b0c661a85f783d35b9883830736eeb63be4aefc4f6b7d9cd081d48782c041e F src/treeview.c 14d5d1254702ec96876aa52642cb31548612384134970409fae333b25b39d6bb F src/trigger.c 00ef0b16ab3f0063439e6582086f57f3beb93cd7e7ba46569a8bdc490c16283d F src/update.c f5210fb55d26e20d14d0106c9479a83c63a005b70b1b5291481c48d6dac6fb9f -F src/upsert.c ae29d025a270b5afec16db2e63b0cd0af8d3352d91d64919a99782e025407e89 +F src/upsert.c 5012bea924018c69cfc3cb12a9fa6089efe9895bda70732c7fa60d2320de4d1f F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 762ee9bbf8733d87d8cd06f58d950e881982e416f8c767334a40ffd341b6bff5 @@ -1507,7 +1507,7 @@ F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97 F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8 F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32 F test/update2.test 5e67667e1c54017d964e626db765cf8bedcf87483c184f4c575bdb8c1dd2313e -F test/upsert1.test 4812fa1f1f16a605e859c55cca5eaf0f849d6b776c435b350baa072971fc707d +F test/upsert1.test 6eb6c5bb63bdc86001ca547d9af715034fc3cf234a70bfc5d75ccc31d8a308db F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568 F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7 F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9 @@ -1719,7 +1719,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 809696434097e62e8ef486c7478b5eb62c0cf1342522a5584939fade82821410 -R bc4b0627a7bb4afe327711991decf93f +P 2c1b1987d8de1efa8ed7e1f199710e32ff20edf8ceec570514fc63bb1ef264e0 +R 9c391c2b4558210a880a408a3702ba04 U drh -Z 68c4f573817a14375916ff20c8db5c24 +Z c59a31f6f872acbe917575a2e26812a5 diff --git a/manifest.uuid b/manifest.uuid index 07964173a2..b96b534d30 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2c1b1987d8de1efa8ed7e1f199710e32ff20edf8ceec570514fc63bb1ef264e0 \ No newline at end of file +98d32ba661f4ba662b639994b74352b695d53a33bc8a498bd09b9e02f794c81e \ No newline at end of file diff --git a/src/upsert.c b/src/upsert.c index 10d91c3f63..2b0f273e81 100644 --- a/src/upsert.c +++ b/src/upsert.c @@ -86,6 +86,7 @@ int sqlite3UpsertAnalyzeTarget( Index *pIdx; ExprList *pTarget; Expr *pTerm; + Expr sCol[2]; int rc; assert( pTabList->nSrc==1 ); @@ -118,6 +119,18 @@ int sqlite3UpsertAnalyzeTarget( return SQLITE_OK; } + /* Initialize sCol[0..1] to be an expression parse tree for a + ** single column of an index. The sCol[0] node will be the TK_COLLATE + ** operator and sCol[1] will be the TK_COLUMN operator. Code below + ** will populate the specific collation and column number values + ** prior to comparing against the conflict-target expression. + */ + memset(sCol, 0, sizeof(sCol)); + sCol[0].op = TK_COLLATE; + sCol[0].pLeft = &sCol[1]; + sCol[1].op = TK_COLUMN; + sCol[1].iTable = pTabList->a[0].iCursor; + /* Check for matches against other indexes */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int ii, jj, nn; @@ -132,26 +145,33 @@ int sqlite3UpsertAnalyzeTarget( } nn = pIdx->nKeyCol; for(ii=0; iiaiColumn[ii]!=XN_EXPR ){ - for(jj=0; jja[jj].pExpr->op!=TK_COLUMN ) continue; - if( pTarget->a[jj].pExpr->iColumn!=pIdx->aiColumn[ii] ) continue; - break; - } - }else{ - Expr *pExpr; + Expr *pExpr; + if( pIdx->aiColumn[ii]==XN_EXPR ){ assert( pIdx->aColExpr!=0 ); assert( pIdx->aColExpr->nExpr>ii ); pExpr = pIdx->aColExpr->a[ii].pExpr; - for(jj=0; jja[jj].pExpr, pExpr, -1)==0 ){ - break; - } + }else{ + sCol[1].iColumn = pIdx->aiColumn[ii]; + sCol[0].u.zToken = (char*)pIdx->azColl[ii]; + pExpr = &sCol[0]; + } + for(jj=0; jja[jj].pExpr, pExpr, + pTabList->a[0].iCursor)<2 + ){ + break; /* Column ii of the index matches column jj of target */ } } - if( jj=nn ){ + /* The target contains no match for column jj of the index */ + break; + } + } + if( ii=nn ) continue; pUpsert->pUpsertIdx = pIdx; return SQLITE_OK; } diff --git a/test/upsert1.test b/test/upsert1.test index 2570adcd47..5d74f4483a 100644 --- a/test/upsert1.test +++ b/test/upsert1.test @@ -39,19 +39,24 @@ do_catchsql_test upsert1-120 { INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(c) DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} +breakpoint do_catchsql_test upsert1-130 { INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(b COLLATE nocase) DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} -if 0 { do_catchsql_test upsert1-200 { DROP INDEX t1x1; DELETE FROM t1; CREATE UNIQUE INDEX t1x1 ON t1(a||b); INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(a||b) DO NOTHING; SELECT * FROM t1; -} {0 {5 6}} -} +} {0 {5 6 0}} +do_catchsql_test upsert1-210 { + DELETE FROM t1; + INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(a||+b) DO NOTHING; + SELECT * FROM t1; +} {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} + finish_test