More refactoring in where.c. (CVS 2552)

FossilOrigin-Name: a35bd50af8961133adc66e40c38402e81a02bb56
This commit is contained in:
drh
2005-07-19 22:22:12 +00:00
parent 0fcef5e110
commit e8b9727835
3 changed files with 62 additions and 70 deletions
+6 -6
View File
@@ -1,5 +1,5 @@
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
@@ -85,7 +85,7 @@ F src/vdbeapi.c 7f392f0792d1258c958083d7de9eae7c3530c9a6
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
@@ -286,7 +286,7 @@ F www/tclsqlite.tcl 425be741b8ae664f55cb1ef2371aab0a75109cf9
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
+1 -1
View File
@@ -1 +1 @@
57c6bd3760163c174be4a2ece58f414e82b55938
a35bd50af8961133adc66e40c38402e81a02bb56
+55 -63
View File
@@ -16,7 +16,7 @@
** 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"
@@ -551,6 +551,35 @@ static void buildIndexProbe(Vdbe *v, int nColumn, int brk, Index *pIdx){
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.
@@ -1139,22 +1168,10 @@ WhereInfo *sqlite3WhereBegin(
** 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);
@@ -1287,21 +1304,11 @@ WhereInfo *sqlite3WhereBegin(
/* 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
@@ -1325,22 +1332,14 @@ WhereInfo *sqlite3WhereBegin(
** 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;
@@ -1370,21 +1369,14 @@ WhereInfo *sqlite3WhereBegin(
** "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;
}