aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vdbe.c61
-rw-r--r--src/where.c10
-rw-r--r--src/wherecode.c4
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);
}