From: drh Date: Tue, 29 Sep 2020 01:48:46 +0000 (+0000) Subject: The OP_SeekScan opcode works, but using it requires disabling the X-Git-Tag: version-3.34.0~82^2~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f761d937c233ab7e1ac1a187a80c45846a8d1c52;p=thirdparty%2Fsqlite.git The OP_SeekScan opcode works, but using it requires disabling the IN-earlyout optimization because the OP_IfNoHope opcode might move the cursor. FossilOrigin-Name: f3c36b840c9a29c0add28039db216f4207a308e5057fc76e3f0004024a8267ac --- diff --git a/manifest b/manifest index 4e0a60c882..52cf306121 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Revisiting\sthe\sIN-scan\soptimization\sto\stry\sto\sfix\sit\sfor\sthe\scorner\scase\nwhere\sthe\sstatistics\sdeceive\sthe\squery\splanner\sinto\susing\sa\sscan\swhen\nan\sindexed\slookup\swould\sbe\sbetter.\s\sThis\scheck-in\schanges\sthe\scode\ngeneration\sto\sdo\sthe\sIN-scan\susing\sa\snew\sOP_SeekScan\sopcode.\s\sThat\snew\nopcode\sis\sdesigned\sto\sabandon\sthe\sscan\sand\sfall\sback\sto\sa\sseek\sif\nit\sdoesn't\sfind\sa\smatch\squickly\senough.\s\sFor\sthis\swork-in-progress\scheck-in,\s\nOP_SeekScan\sis\sstill\sa\sno-op\sand\sOP_SeekGE\sstill\sends\sup\sdoing\sall\sthe\swork. -D 2020-09-28T19:51:54.673 +C The\sOP_SeekScan\sopcode\sworks,\sbut\susing\sit\srequires\sdisabling\sthe\nIN-earlyout\soptimization\sbecause\sthe\sOP_IfNoHope\sopcode\smight\smove\sthe\ncursor. +D 2020-09-29T01:48:46.942 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -607,7 +607,7 @@ F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c c0c7977de7ef9b8cb10f6c85f2d0557889a658f817b0455909a49179ba4c8002 F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286 -F src/vdbe.c 17584029ae2c2acc955f3dc19858fad1a3d509f31d42ddd2ff7be3552d4c77d3 +F src/vdbe.c f13b70fa1deea20698e19c86c4aae3cf93495c74b4c57e7139f628cf4f711ddf F src/vdbe.h 83603854bfa5851af601fc0947671eb260f4363e62e960e8a994fb9bbcd2aaa1 F src/vdbeInt.h 3ca5e9fd6e095a8b6cf6bc3587a46fc93499503b2fe48951e1034ba9e2ce2f6e F src/vdbeapi.c c5e7cb2ab89a24d7f723e87b508f21bfb1359a04db5277d8a99fd1e015c12eb9 @@ -622,9 +622,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 69e770e96fd56cc21608992bf2c6f1f3dc5cf2572d0495c6a643b06c3a679f14 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 3df26a33dc4f54e8771600fb7fdebe1ece0896c2ad68c30ab40b017aa4395049 -F src/where.c c628a6850b023cfacfdbf6060481eae5e538ccb3c3464a700b501e08d4cce74b +F src/where.c da9c0d503f81cc8444eb3525b75eec2bb3d198f4d5939b207977f2fc20d85b54 F src/whereInt.h 59077fbd0b3d01bc8715e746c86a99ebf4c85bde8a57077ec04d2a23e59666ec -F src/wherecode.c 4096498d05f0c1bfff435ef48679e774a345bb2c700215da1383902e14877d5c +F src/wherecode.c 9c2301ecfd8c347969207c1042181ac39573964167ada5bc0025b9a8447d5f8f F src/whereexpr.c 2a05552e808047a93845278c98c6ca64a265fa8e9ffd087c161bb11bfe339866 F src/window.c edd6f5e25a1e8f2b6f5305b7f5f7da7bb35f07f0d432b255b1d4c2fcab4205aa F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 @@ -1880,10 +1880,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 43f7ddad800acf40917c5cc3d926640dbec17c34d5f1cbbb74bd80f44eeed0a5 -R 91153af0a9416b3fbb7b5420545d1fbb -T *branch * in-scan-vs-index -T *sym-in-scan-vs-index * -T -sym-trunk * +P d720b6981eeb0ffdb14494ca63eca298ee724ae4ad4863c7c7cbfdad7fa52519 +R 93eab6914a9c3b5b8c8ceb0a0d7c7688 U drh -Z 22384fb99540c2e7915964a3edd63b6d +Z 1fb2faea0368362fc6f0f58448eca8a2 diff --git a/manifest.uuid b/manifest.uuid index 0ba7bb60dc..af2ea4ee4c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d720b6981eeb0ffdb14494ca63eca298ee724ae4ad4863c7c7cbfdad7fa52519 \ No newline at end of file +f3c36b840c9a29c0add28039db216f4207a308e5057fc76e3f0004024a8267ac \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index d14838e4f1..ff1cf87cb1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4425,6 +4425,11 @@ seek_not_found: ** opcode is to bypass unnecessary OP_SeekGE operations. */ case OP_SeekScan: { + VdbeCursor *pC; + int res; + int n; + UnpackedRecord r; + assert( pOp[1].opcode==OP_SeekGE ); assert( pOp[2].opcode==OP_IdxGT ); assert( pOp[1].p1==pOp[2].p1 ); @@ -4432,7 +4437,61 @@ case OP_SeekScan: { assert( pOp[1].p3==pOp[2].p3 ); assert( pOp[1].p4.i==pOp[2].p4.i ); assert( pOp->p1>0 ); - break; /* No-op for now. FIX ME. */ + pC = p->apCsr[pOp[1].p1]; + assert( pC!=0 ); + assert( pC->eCurType==CURTYPE_BTREE ); + assert( !pC->isTable ); + if( pC->nullRow ){ +#ifdef SQLITE_DEBUG + if( db->flags&SQLITE_VdbeTrace ){ + printf("... no prior seeks - fall through\n"); + } +#endif + break; + } + n = pOp->p1; + assert( n>=1 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = (u16)pOp[1].p4.i; + r.default_rc = 0; + r.aMem = &aMem[pOp[1].p3]; +#ifdef SQLITE_DEBUG + { + int i; + for(i=0; i0 ){ +#ifdef SQLITE_DEBUG + if( db->flags&SQLITE_VdbeTrace ){ + printf("... %d steps and then skip\n", pOp->p1 - n); + } +#endif + pOp++; + goto jump_to_p2; + } + if( res==0 ){ +#ifdef SQLITE_DEBUG + if( db->flags&SQLITE_VdbeTrace ){ + printf("... %d steps and then success\n", pOp->p1 - n); + } +#endif + pOp += 2; + break; + } + if( n<=0 ) break; + n--; + rc = sqlite3BtreeNext(pC->uc.pCursor, 0); + if( rc ) goto abort_due_to_error; + } + break; } diff --git a/src/where.c b/src/where.c index 0ab5adee8f..8a33e86194 100644 --- a/src/where.c +++ b/src/where.c @@ -5360,7 +5360,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeJumpHere(v, pIn->addrInTop+1); if( pIn->eEndLoopOp!=OP_Noop ){ if( pIn->nPrefix ){ - assert( pLoop->wsFlags & WHERE_IN_EARLYOUT ); + int bEarlyOut = + (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 + && (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0; if( pLevel->iLeftJoin ){ /* For LEFT JOIN queries, cursor pIn->iCur may not have been ** opened yet. This occurs for WHERE clauses such as @@ -5371,12 +5373,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ ** jump over the OP_Next or OP_Prev instruction about to ** be coded. */ sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur, - sqlite3VdbeCurrentAddr(v) + 2 + - ((pLoop->wsFlags & WHERE_VIRTUALTABLE)==0) - ); + sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut); VdbeCoverage(v); } - if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){ + if( bEarlyOut ){ sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur, sqlite3VdbeCurrentAddr(v)+2, pIn->iBase, pIn->nPrefix); diff --git a/src/wherecode.c b/src/wherecode.c index 8227d0d7d0..adf03e6c38 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -570,7 +570,7 @@ static int codeEqualityTerm( if( pLevel->u.in.nIn==0 ){ pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse); } - if( iEq>0 ){ + if( iEq>0 && (pLoop->wsFlags && WHERE_IN_SEEKSCAN)==0 ){ pLoop->wsFlags |= WHERE_IN_EARLYOUT; } @@ -1911,7 +1911,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); } - if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ + if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){ sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq); }