diff options
author | drh <drh@noemail.net> | 2016-03-04 16:42:43 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2016-03-04 16:42:43 +0000 |
commit | 2606aca80f35c4672c7834e90786d737679fa35b (patch) | |
tree | 2a8be85e2e802ad5ba42c4bb8e9102712cb287aa /src/wherecode.c | |
parent | fd37e67b16d6c6228aa58709299c86ec81a552a5 (diff) | |
parent | 3298a641a2b1c883b34e9d85541db50d6e2d1ff9 (diff) | |
download | sqlite-2606aca80f35c4672c7834e90786d737679fa35b.tar.gz sqlite-2606aca80f35c4672c7834e90786d737679fa35b.zip |
Merge recent enhancements from trunk. Default page size is 4096. Writes
to statement journals are avoided.
FossilOrigin-Name: 456df3365e2df60e34762f2024bb551538b3f72b
Diffstat (limited to 'src/wherecode.c')
-rw-r--r-- | src/wherecode.c | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/src/wherecode.c b/src/wherecode.c index accc14086..bfc52fb47 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -874,6 +874,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( int iReg; /* P3 Value for OP_VFilter */ int addrNotFound; int nConstraint = pLoop->nLTerm; + int iIn; /* Counter for IN constraints */ sqlite3ExprCachePush(pParse); iReg = sqlite3GetTempRange(pParse, nConstraint+2); @@ -896,14 +897,48 @@ Bitmask sqlite3WhereCodeOneLoopStart( pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC); VdbeCoverage(v); pLoop->u.vtab.needFree = 0; - for(j=0; j<nConstraint && j<16; j++){ - if( (pLoop->u.vtab.omitMask>>j)&1 ){ - disableTerm(pLevel, pLoop->aLTerm[j]); - } - } pLevel->p1 = iCur; pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; pLevel->p2 = sqlite3VdbeCurrentAddr(v); + iIn = pLevel->u.in.nIn; + for(j=nConstraint-1; j>=0; j--){ + pTerm = pLoop->aLTerm[j]; + if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){ + disableTerm(pLevel, pTerm); + }else if( (pTerm->eOperator & WO_IN)!=0 ){ + Expr *pCompare; /* The comparison operator */ + Expr *pRight; /* RHS of the comparison */ + VdbeOp *pOp; /* Opcode to access the value of the IN constraint */ + + /* Reload the constraint value into reg[iReg+j+2]. The same value + ** was loaded into the same register prior to the OP_VFilter, but + ** the xFilter implementation might have changed the datatype or + ** encoding of the value in the register, so it *must* be reloaded. */ + assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed ); + if( pLevel->u.in.aInLoop!=0 ){ + assert( iIn>0 ); + pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop); + assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid ); + assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 ); + assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 ); + testcase( pOp->opcode==OP_Rowid ); + sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3); + } + + /* Generate code that will continue to the next row if + ** the IN constraint is not satisfied */ + pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0, 0); + assert( pCompare!=0 || db->mallocFailed ); + if( pCompare ){ + pCompare->pLeft = pTerm->pExpr->pLeft; + pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0); + if( pRight ) pRight->iTable = iReg+j+2; + sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0); + pCompare->pLeft = 0; + sqlite3ExprDelete(db, pCompare); + } + } + } sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); sqlite3ExprCachePop(pParse); }else |