diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vdbe.c | 61 | ||||
-rw-r--r-- | src/where.c | 10 | ||||
-rw-r--r-- | src/wherecode.c | 4 |
3 files changed, 67 insertions, 8 deletions
diff --git a/src/vdbe.c b/src/vdbe.c index d14838e4f..ff1cf87cb 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; i<r.nField; i++){ + assert( memIsValid(&r.aMem[i]) ); + REGISTER_TRACE(pOp[1].p3+i, &aMem[pOp[1].p3+i]); + } + } +#endif + res = 0; /* Not needed. Only used to silence a warning. */ + while(1){ + rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res); + if( rc ) goto abort_due_to_error; + if( res>0 ){ +#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 0ab5adee8..8a33e8619 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 8227d0d7d..adf03e6c3 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); } |