-C Refactoring\sof\sthe\squery\soptimizer\sin\sadvance\sof\sadding\sbetter\soptimization.\s(CVS\s2551)
-D 2005-07-19T17:38:23
+C More\srefactoring\sin\swhere.c.\s(CVS\s2552)
+D 2005-07-19T22:22:13
F Makefile.in 22ea9c0fe748f591712d8fe3c6d972c6c173a165
F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F src/vdbeaux.c 3732a86566a6be4da4c606e9334baf3fd98667af
F src/vdbefifo.c b8805850afe13b43f1de78d58088cb5d66f88e1e
F src/vdbemem.c da8e8d6f29dd1323f782f000d7cd120027c9ff03
-F src/where.c 1da2268f5e37257276dff46ebbc1cc596a9efaa1
+F src/where.c 5a84161299ff90aeb67c885f6bf89c29c3efbb27
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
F test/alter.test 9d6837a3d946b73df692b7cef2a7644d2e2f6bc6
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
-P ca69f36832d57775e73ac5cdbe0a32d7b759432b
-R 9a4258be8ecf1889fef260cdd1d2d34b
+P 57c6bd3760163c174be4a2ece58f414e82b55938
+R 3cdcdb6928aa7a2c42a275a913941b5a
U drh
-Z a631f1b7791a9c3a4f6bac427d47518f
+Z b929286800f2e064fa91faa90163e11f
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
-** $Id: where.c,v 1.146 2005/07/19 17:38:23 drh Exp $
+** $Id: where.c,v 1.147 2005/07/19 22:22:13 drh Exp $
*/
#include "sqliteInt.h"
sqlite3IndexAffinityStr(v, pIdx);
}
+/*
+** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
+** where X is a reference to the iColumn of table iCur and <op> is either
+** op1 or op2. Return a pointer to the term.
+*/
+static WhereTerm *findTerm(
+ WhereClause *pWC, /* The WHERE clause to be searched */
+ int iCur, /* Cursor number of LHS */
+ int iColumn, /* Column number of LHS */
+ Bitmask loopMask, /* RHS must not overlap with this mask */
+ u8 op1, u8 op2 /* Expression must use either of these opcodes */
+){
+ WhereTerm *pTerm;
+ int k;
+ for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
+ u8 op = pTerm->pExpr->op;
+ if( pTerm->leftCursor==iCur
+ && (pTerm->prereqRight & loopMask)==0
+ && pTerm->leftColumn==iColumn
+ && (op==op1 || op==op2)
+ ){
+ break;
+ }
+ }
+ assert( k>0 ); /* The search is always successful */
+ return pTerm;
+}
+
+
/*
** Generate code for an equality term of the WHERE clause. An equality
** term can be either X=expr or X IN (...). pTerm is the X.
** constraints that column. If the WHERE clause term is X=expr, then
** generate code to evaluate expr and leave the result on the stack */
for(j=0; j<nColumn; j++){
- for(pTerm=wc.a, k=0; k<wc.nTerm; k++, pTerm++){
- Expr *pX = pTerm->pExpr;
- assert( pX );
- if( pTerm->leftCursor==iCur
- && (pTerm->prereqRight & loopMask)==0
- && pTerm->leftColumn==pIdx->aiColumn[j]
- && (pX->op==TK_EQ || pX->op==TK_IN)
- ){
- char idxaff = pIdx->pTable->aCol[pTerm->leftColumn].affinity;
- assert( (pTerm->flags & TERM_CODED)==0 );
- if( sqlite3IndexAffinityOk(pX, idxaff) ){
- codeEqualityTerm(pParse, pTerm, brk, pLevel);
- break;
- }
- }
- }
+ pTerm = findTerm(&wc, iCur, pIdx->aiColumn[j], loopMask, TK_EQ, TK_IN);
+ assert( pTerm!=0 );
+ assert( (pTerm->flags & TERM_CODED)==0 );
+ codeEqualityTerm(pParse, pTerm, brk, pLevel);
}
pLevel->iMem = pParse->nMem++;
cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
/* Evaluate the equality constraints
*/
for(j=0; j<nEqColumn; j++){
- int iIdxCol = pIdx->aiColumn[j];
- for(pTerm=wc.a, k=0; k<wc.nTerm; k++, pTerm++){
- Expr *pX;
- if( pTerm->leftCursor==iCur
- && pTerm->leftColumn==iIdxCol
- && (pX = pTerm->pExpr)->op==TK_EQ
- && (pTerm->prereqRight & loopMask)==0
- ){
- assert( (pTerm->flags & TERM_CODED)==0 );
- sqlite3ExprCode(pParse, pX->pRight);
- disableTerm(pLevel, pTerm);
- break;
- }
- }
- assert( k<wc.nTerm );
+ pTerm = findTerm(&wc, iCur, pIdx->aiColumn[j], loopMask, TK_EQ, TK_EQ);
+ assert( pTerm!=0 );
+ assert( (pTerm->flags & TERM_CODED)==0 );
+ sqlite3ExprCode(pParse, pTerm->pExpr->pRight);
+ disableTerm(pLevel, pTerm);
}
/* Duplicate the equality term values because they will all be
** key computed here really ends up being the start key.
*/
if( (score & 4)!=0 ){
- for(pTerm=wc.a, k=0; k<wc.nTerm; k++, pTerm++){
- Expr *pX = pTerm->pExpr;
- assert( pX );
- if( pTerm->leftCursor==iCur
- && (pX->op==TK_LT || pX->op==TK_LE)
- && (pTerm->prereqRight & loopMask)==0
- && pTerm->leftColumn==pIdx->aiColumn[j]
- ){
- assert( (pTerm->flags & TERM_CODED)==0 );
- sqlite3ExprCode(pParse, pX->pRight);
- leFlag = pX->op==TK_LE;
- disableTerm(pLevel, pTerm);
- break;
- }
- }
- assert( k<wc.nTerm );
+ Expr *pX;
+ pTerm = findTerm(&wc, iCur, pIdx->aiColumn[j], loopMask, TK_LT, TK_LE);
+ assert( pTerm!=0 );
+ pX = pTerm->pExpr;
+ assert( (pTerm->flags & TERM_CODED)==0 );
+ sqlite3ExprCode(pParse, pX->pRight);
+ leFlag = pX->op==TK_LE;
+ disableTerm(pLevel, pTerm);
testOp = OP_IdxGE;
}else{
testOp = nEqColumn>0 ? OP_IdxGE : OP_Noop;
** "start" key really ends up being used as the termination key.
*/
if( (score & 8)!=0 ){
- for(pTerm=wc.a, k=0; k<wc.nTerm; k++, pTerm++){
- Expr *pX = pTerm->pExpr;
- assert( pX );
- if( pTerm->leftCursor==iCur
- && (pX->op==TK_GT || pX->op==TK_GE)
- && (pTerm->prereqRight & loopMask)==0
- && pTerm->leftColumn==pIdx->aiColumn[j]
- ){
- assert( (pTerm->flags & TERM_CODED)==0 );
- sqlite3ExprCode(pParse, pX->pRight);
- geFlag = pX->op==TK_GE;
- disableTerm(pLevel, pTerm);
- break;
- }
- }
+ Expr *pX;
+ pTerm = findTerm(&wc, iCur, pIdx->aiColumn[j], loopMask, TK_GT, TK_GE);
+ assert( pTerm!=0 );
+ pX = pTerm->pExpr;
+ assert( (pTerm->flags & TERM_CODED)==0 );
+ sqlite3ExprCode(pParse, pX->pRight);
+ geFlag = pX->op==TK_GE;
+ disableTerm(pLevel, pTerm);
}else{
geFlag = 1;
}