]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improved conflict-target matching logic.
authordrh <drh@noemail.net>
Fri, 13 Apr 2018 13:44:48 +0000 (13:44 +0000)
committerdrh <drh@noemail.net>
Fri, 13 Apr 2018 13:44:48 +0000 (13:44 +0000)
FossilOrigin-Name: 98d32ba661f4ba662b639994b74352b695d53a33bc8a498bd09b9e02f794c81e

manifest
manifest.uuid
src/upsert.c
test/upsert1.test

index 0377bbe3c646970f75117fe6997f8475908875b0..9b3751834ab8f5da78a1bc63d6b02358dd126e01 100644 (file)
--- 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
index 07964173a21c9517ba59ecdd9f908f36c324ab83..b96b534d305cd42aa765634b17c844b95d131d2f 100644 (file)
@@ -1 +1 @@
-2c1b1987d8de1efa8ed7e1f199710e32ff20edf8ceec570514fc63bb1ef264e0
\ No newline at end of file
+98d32ba661f4ba662b639994b74352b695d53a33bc8a498bd09b9e02f794c81e
\ No newline at end of file
index 10d91c3f639026e019916b4d0628a85fa79f6437..2b0f273e81bdbc6a857a01737360f78b55fdf998 100644 (file)
@@ -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; ii<nn; ii++){
-      if( pIdx->aiColumn[ii]!=XN_EXPR ){
-        for(jj=0; jj<nn; jj++){
-          if( pTarget->a[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; jj<nn; jj++){
-          if( sqlite3ExprCompare(pParse, pTarget->a[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; jj<nn; jj++){
+        if( sqlite3ExprCompare(pParse, pTarget->a[jj].pExpr, pExpr,
+                               pTabList->a[0].iCursor)<2
+        ){
+          break;  /* Column ii of the index matches column jj of target */
         }
       }
-      if( jj<nn ) break;
+      if( jj>=nn ){
+        /* The target contains no match for column jj of the index */
+        break;
+      }
+    }
+    if( ii<nn ){
+      /* Column ii of the index did not match any term of the conflict target.
+      ** Continue the search with the next index. */
+      continue;
     }
-    if( ii>=nn ) continue;
     pUpsert->pUpsertIdx = pIdx;
     return SQLITE_OK;
   }
index 2570adcd47d00e5a533fc801a51e2a68f25eaafe..5d74f4483a5cff37a3619a8dcfc49c2d027c1f8d 100644 (file)
@@ -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