]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
For UPDATE and DELETE, use OP_DeferredSeek always. If the seek must later
authordrh <drh@noemail.net>
Fri, 14 Aug 2020 20:04:26 +0000 (20:04 +0000)
committerdrh <drh@noemail.net>
Fri, 14 Aug 2020 20:04:26 +0000 (20:04 +0000)
be resolved, add the OP_FinishSeek opcode after all WHERE clause terms have
been processed.  This obviates the need for the WHERE_SEEK_TABLE and
WHERE_SEEK_UNIQ_TABLE flags to sqlite3WhereBegin() and the ensuing
complication, and it allows the covering index optimization to be used
further into WHERE clause processing.

FossilOrigin-Name: a495f60d315e34b1a1bc5fb1336e05047add52c8fb2710b577c97b10a5e734f6

manifest
manifest.uuid
src/delete.c
src/sqliteInt.h
src/update.c
src/wherecode.c

index 5ba6c36bc4f2aa910f270443acb5d90acf580376..351e74e6a9fe870a2d3d47d55d1f1da37b172773 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Experimental\schange\sto\stry\sto\sget\ssome\sDELETE\soperations\sto\saccess\svalues\nusing\sthe\sindex\srather\sthan\sthe\smain\stable,\sso\sas\sto\savoid\sunnecessary\nmain\stable\sseeks.
-D 2020-08-14T17:39:31.333
+C For\sUPDATE\sand\sDELETE,\suse\sOP_DeferredSeek\salways.\s\sIf\sthe\sseek\smust\slater\nbe\sresolved,\sadd\sthe\sOP_FinishSeek\sopcode\safter\sall\sWHERE\sclause\sterms\shave\nbeen\sprocessed.\s\sThis\sobviates\sthe\sneed\sfor\sthe\sWHERE_SEEK_TABLE\sand\nWHERE_SEEK_UNIQ_TABLE\sflags\sto\ssqlite3WhereBegin()\sand\sthe\sensuing\ncomplication,\sand\sit\sallows\sthe\scovering\sindex\soptimization\sto\sbe\sused\nfurther\sinto\sWHERE\sclause\sprocessing.
+D 2020-08-14T20:04:26.522
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -486,7 +486,7 @@ F src/ctime.c e98518d2d3d4029a13c805e07313fb60c877be56db76e90dd5f3af73085d0ce6
 F src/date.c dace306a10d9b02ee553d454c8e1cf8d3c9b932e137738a6b15b90253a9bfc10
 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
 F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
-F src/delete.c 410c771c25afc113c273d9efad6ab6881bda28c75a1838b9d2c52ba20d1dc704
+F src/delete.c a2a603ab07cced8560065b0e2c4c9c842f2c5a2fd43d87355f95eb53bae7fe21
 F src/expr.c 58c06940d964c2cf455b979cf66a648499d294a5ee6dadcaeaed447257c1dc75
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 83372403298e6a7dd989a47aaacdbaa5b4307b5199dbd56e07d4896066b3de72
@@ -540,7 +540,7 @@ F src/shell.c.in b9b819feede7b85585ab0826490a352e04e2ee46e8132c92597d29972b2be1d
 F src/sqlite.h.in d2c03414a8ee5d4a6855c04dd7cd5998e45139b0fe66b65bae86d4223edd091f
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197
-F src/sqliteInt.h a1aa5457ca881cbf5adb55933bf81d7d4889375afb9a0a5df382a451c058087d
+F src/sqliteInt.h 86ad0f9164cbadb2ba9598cc6cf5b32bdb47b343c0da5ca62f3d73b60be55b65
 F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032
 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -602,7 +602,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c 4dc01b267593537e2a0d0efe9f80dabe24c5b6f7627bc6971c487fa6a1dacbbf
 F src/treeview.c 4b92992176fb2caefbe06ba5bd06e0e0ebcde3d5564758da672631f17aa51cda
 F src/trigger.c ef67bde309a831515dc3c2173d792574309f2f42d45f8c078743fae9f7f98c75
-F src/update.c fb15bec5b54fd098f4b84f6abc83c7103b45ba8484011fff8edf5ae31656eab6
+F src/update.c 55a6203008d033fc1a9c125d7a0a61efdb79bbb2e6db427b917d1d427b4639be
 F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
 F src/util.c c8bf30c4356b091bcc3b624d0e24b2b4d11b8be4d6c90d8e0705971e15cc819b
@@ -624,7 +624,7 @@ F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
 F src/walker.c 3df26a33dc4f54e8771600fb7fdebe1ece0896c2ad68c30ab40b017aa4395049
 F src/where.c 50fe9fc0b929b6c3c7b71a6b7601a942e76512e38a220de948f1c79af237ad9b
 F src/whereInt.h eb8c2847fb464728533777efec1682b3c074224293b2da73513c61a609efbeab
-F src/wherecode.c 8064fe5c042824853a9b1fda670054a51a49033a6c79059988c97751ccf8088e
+F src/wherecode.c cb9bc7cef99578c99baceafeea9c9bcc738d5be37f56dbfe3a1c61ea52483fd0
 F src/whereexpr.c 264d58971eaf8256eb5b0917bcd7fc7a1f1109fdda183a8382308a1b18a2dce7
 F src/window.c edd6f5e25a1e8f2b6f5305b7f5f7da7bb35f07f0d432b255b1d4c2fcab4205aa
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1879,10 +1879,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 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f
-R 90cb3c0f751fa2f3ee092ca1f77cf5d7
-T *branch * delete-bytecode-optimization
-T *sym-delete-bytecode-optimization *
-T -sym-trunk *
+P 2f7cb6ab39e54fd6eb3a280d3022c3d4f4ed92e83af7226e63e0199a96397a6b
+R 02225c94aba95601035e446dd1dfb037
 U drh
-Z b9254e6f44cc1c24322dcc5d82dd0b50
+Z 6927cf3647c698c9871735d62c2df08c
index d83942f49c4686b86ce09ab079e74dc6fe19025b..c660dbf67db38449644b4b1d625c7f34dc37654d 100644 (file)
@@ -1 +1 @@
-2f7cb6ab39e54fd6eb3a280d3022c3d4f4ed92e83af7226e63e0199a96397a6b
\ No newline at end of file
+a495f60d315e34b1a1bc5fb1336e05047add52c8fb2710b577c97b10a5e734f6
\ No newline at end of file
index ae2f85b3a9f61570f6c53c9c6b180da2bc02f47a..bfb486fa54562558e2070de9a55228937ce1f02d 100644 (file)
@@ -425,7 +425,7 @@ void sqlite3DeleteFrom(
   }else
 #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
   {
-    u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE;
+    u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK;
     if( sNC.ncFlags & NC_VarSelect ) bComplex = 1;
     wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
     if( HasRowid(pTab) ){
@@ -461,6 +461,9 @@ void sqlite3DeleteFrom(
     assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
     assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF );
     if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse);
+    if( sqlite3WhereUsesDeferredSeek(pWInfo) ){
+      sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur);
+    }
   
     /* Keep track of the number of rows to be deleted */
     if( memCnt ){
@@ -495,6 +498,7 @@ void sqlite3DeleteFrom(
       if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
       if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
       if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
+      addrBypass = sqlite3VdbeMakeLabel(pParse);
     }else{
       if( pPk ){
         /* Add the PK key for this row to the temporary table */
@@ -508,13 +512,6 @@ void sqlite3DeleteFrom(
         nKey = 1;  /* OP_DeferredSeek always uses a single rowid */
         sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
       }
-    }
-  
-    /* If this DELETE cannot use the ONEPASS strategy, this is the 
-    ** end of the WHERE loop */
-    if( eOnePass!=ONEPASS_OFF ){
-      addrBypass = sqlite3VdbeMakeLabel(pParse);
-    }else{
       sqlite3WhereEnd(pWInfo);
     }
   
index 74e854452b80ae2cb75126a0674360bc53c6fe59..a5d108b6c7cb8d946f7e49c409f2b995e829f747 100644 (file)
@@ -2953,9 +2953,9 @@ struct SrcList {
 #define WHERE_DISTINCTBY       0x0080 /* pOrderby is really a DISTINCT clause */
 #define WHERE_WANT_DISTINCT    0x0100 /* All output needs to be distinct */
 #define WHERE_SORTBYGROUP      0x0200 /* Support sqlite3WhereIsSorted() */
-#define WHERE_SEEK_TABLE       0x0400 /* Do not defer seeks on main table */
+                        /*     0x0400    not currently used */
 #define WHERE_ORDERBY_LIMIT    0x0800 /* ORDERBY+LIMIT on the inner loop */
-#define WHERE_SEEK_UNIQ_TABLE  0x1000 /* Do not defer seeks if unique */
+                        /*     0x1000    not currently used */
                         /*     0x2000    not currently used */
 #define WHERE_USE_LIMIT        0x4000 /* Use the LIMIT in cost estimates */
                         /*     0x8000    not currently used */
index a9c43d62eb3e407426462e0536e0b94c0f19c006..3c9fd9eb11b12d0f6f98f99b09b8cab13dd0accb 100644 (file)
@@ -705,7 +705,7 @@ void sqlite3Update(
       ** be deleted as a result of REPLACE conflict handling. Any of these
       ** things might disturb a cursor being used to scan through the table
       ** or index, causing a single-pass approach to malfunction.  */
-      flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
+      flags = WHERE_ONEPASS_DESIRED;
       if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
         flags |= WHERE_ONEPASS_MULTIROW;
       }
index 5473a0282eca034f80063099fffc6d9ae5a6e2b0..ece2c754d1a76e4f3e027ce5dea37e108c432424 100644 (file)
@@ -1909,17 +1909,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
     if( omitTable ){
       /* pIdx is a covering index.  No need to access the main table. */
     }else if( HasRowid(pIdx->pTable) ){
-      if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)
-       || ( (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)!=0
-           && (pWInfo->eOnePass==ONEPASS_SINGLE || pLoop->nLTerm==0) )
-      ){
-        iRowidReg = ++pParse->nMem;
-        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
-        sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
-        VdbeCoverage(v);
-      }else{
-        codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
-      }
+      codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
     }else if( iCur!=iIdxCur ){
       Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
       iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
@@ -2046,7 +2036,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
     int iRetInit;                             /* Address of regReturn init */
     int untestedTerms = 0;             /* Some terms not completely tested */
     int ii;                            /* Loop counter */
-    u16 wctrlFlags;                    /* Flags for sub-WHERE clause */
     Expr *pAndExpr = 0;                /* An ".. AND (...)" expression */
     Table *pTab = pTabItem->pTab;
 
@@ -2147,7 +2136,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
     ** eliminating duplicates from other WHERE clauses, the action for each
     ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
     */
-    wctrlFlags =  WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE);
     ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
     for(ii=0; ii<pOrWc->nTerm; ii++){
       WhereTerm *pOrTerm = &pOrWc->a[ii];
@@ -2166,7 +2154,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
         ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
         WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
         pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
-                                      wctrlFlags, iCovCur);
+                                      WHERE_OR_SUBCLAUSE, iCovCur);
         assert( pSubWInfo || pParse->nErr || db->mallocFailed );
         if( pSubWInfo ){
           WhereLoop *pSubLoop;
@@ -2264,6 +2252,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
           }else{
             pCov = 0;
           }
+          if( sqlite3WhereUsesDeferredSeek(pSubWInfo) ){
+            pWInfo->bDeferredSeek = 1;
+          }
 
           /* Finish the loop through table entries that match term pOrTerm. */
           sqlite3WhereEnd(pSubWInfo);