Comment and variable-name cleanup in where.c. Add testcase() macros to
insure adequate test coverage of table-driven logic. (CVS 5032) FossilOrigin-Name: adcef73b3925266a14a552cd9b06c14f22aaefc8
This commit is contained in:
parent
1cceeb93ea
commit
981642f389
12
manifest
12
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\stypo\sin\sthe\sdocumentation\son\ssqlite3_open_v2().\s(CVS\s5031)
|
||||
D 2008-04-19T14:06:28
|
||||
C Comment\sand\svariable-name\scleanup\sin\swhere.c.\s\sAdd\stestcase()\smacros\sto\ninsure\sadequate\stest\scoverage\sof\stable-driven\slogic.\s(CVS\s5032)
|
||||
D 2008-04-19T14:40:44
|
||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||
F Makefile.in 25b3282a4ac39388632c2fb0e044ff494d490952
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -183,7 +183,7 @@ F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
|
||||
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
|
||||
F src/vdbemem.c 237e61216381998ff71c6431e5e7bd03386f6225
|
||||
F src/vtab.c f5e78bf73df3b0c1b53861109c1b2e0800b108cc
|
||||
F src/where.c 011f866cf0f05c832eea5a30e079eb108253ac64
|
||||
F src/where.c 85719d58e0f680b5d8239dc6af82b159775d7376
|
||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/all.test d56a3ca8acdf761204aff0a2e7aa5eb8e11b31e6
|
||||
@ -631,7 +631,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P df02175ec0f28d57942b8275b540ff855dfbeb09
|
||||
R 6299f6a06e93546f99df6a47ebb09453
|
||||
P f7b62daa9fe71dc713bde107507fc7bcb812d62b
|
||||
R 6e41e3d0b22d62b812d3d07204f15026
|
||||
U drh
|
||||
Z 385bf8bab63aafd1f261478c271df70c
|
||||
Z 179f0ff656646746a01845fdd389ea41
|
||||
|
@ -1 +1 @@
|
||||
f7b62daa9fe71dc713bde107507fc7bcb812d62b
|
||||
adcef73b3925266a14a552cd9b06c14f22aaefc8
|
84
src/where.c
84
src/where.c
@ -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.301 2008/04/18 10:25:24 danielk1977 Exp $
|
||||
** $Id: where.c,v 1.302 2008/04/19 14:40:44 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -1272,8 +1272,10 @@ static double bestVirtualIndex(
|
||||
** to this virtual table */
|
||||
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
||||
if( pTerm->leftCursor != pSrc->iCursor ) continue;
|
||||
if( pTerm->eOperator==WO_IN ) continue;
|
||||
if( pTerm->eOperator==WO_ISNULL ) continue;
|
||||
if( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
|
||||
testcase( pTerm->eOperator==WO_IN );
|
||||
testcase( pTerm->eOperator==WO_ISNULL );
|
||||
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
|
||||
nTerm++;
|
||||
}
|
||||
|
||||
@ -1320,8 +1322,10 @@ static double bestVirtualIndex(
|
||||
|
||||
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
||||
if( pTerm->leftCursor != pSrc->iCursor ) continue;
|
||||
if( pTerm->eOperator==WO_IN ) continue;
|
||||
if( pTerm->eOperator==WO_ISNULL ) continue;
|
||||
if( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
|
||||
testcase( pTerm->eOperator==WO_IN );
|
||||
testcase( pTerm->eOperator==WO_ISNULL );
|
||||
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
|
||||
pIdxCons[j].iColumn = pTerm->leftColumn;
|
||||
pIdxCons[j].iTermOffset = i;
|
||||
pIdxCons[j].op = pTerm->eOperator;
|
||||
@ -1867,6 +1871,8 @@ static int codeAllEqualityTerms(
|
||||
if( r1!=regBase+j ){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
|
||||
}
|
||||
testcase( pTerm->eOperator & WO_ISNULL );
|
||||
testcase( pTerm->eOperator & WO_IN );
|
||||
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->brk);
|
||||
}
|
||||
@ -2456,7 +2462,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}else if( pLevel->flags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
|
||||
/* Case 3: A scan using an index.
|
||||
**
|
||||
** The WHERE clause may contain one or more equality
|
||||
** The WHERE clause may contain zero or more equality
|
||||
** terms ("==" or "IN" operators) that refer to the N
|
||||
** left-most columns of the index. It may also contain
|
||||
** inequality constraints (>, <, >= or <=) on the indexed
|
||||
@ -2472,10 +2478,15 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** x=5 AND y>5 AND y<10
|
||||
** x=5 AND y=5 AND z<=10
|
||||
**
|
||||
** This cannot be optimized:
|
||||
** The z<10 term of the following cannot be used, only
|
||||
** the x=5 term:
|
||||
**
|
||||
** x=5 AND z<10
|
||||
**
|
||||
** N may be zero if there are inequality constraints.
|
||||
** If there are no inequality constraints, then N is at
|
||||
** least one.
|
||||
**
|
||||
** This case is also used when there are no WHERE clause
|
||||
** constraints but an index is selected anyway, in order
|
||||
** to force the output order to conform to an ORDER BY.
|
||||
@ -2505,7 +2516,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
int endEq; /* True if range end uses ==, >= or <= */
|
||||
int start_constraints; /* Start of range is constrained */
|
||||
int k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */
|
||||
char *ptr;
|
||||
int nConstraint; /* Number of constraint terms */
|
||||
int op;
|
||||
|
||||
/* Generate code to evaluate all constraint terms using == or IN
|
||||
@ -2545,16 +2556,20 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** a forward order scan on a descending index, interchange the
|
||||
** start and end terms (pRangeStart and pRangeEnd).
|
||||
*/
|
||||
if( bRev==((pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)?1:0) ){
|
||||
if( bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){
|
||||
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
|
||||
}
|
||||
|
||||
startEq = ((!pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE))?1:0);
|
||||
endEq = ((!pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE))?1:0);
|
||||
start_constraints = ((pRangeStart || nEq>0)?1:0);
|
||||
testcase( pRangeStart && pRangeStart->eOperator & WO_LE );
|
||||
testcase( pRangeStart && pRangeStart->eOperator & WO_GE );
|
||||
testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE );
|
||||
testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE );
|
||||
startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE);
|
||||
endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE);
|
||||
start_constraints = pRangeStart || nEq>0;
|
||||
|
||||
/* Seek the index cursor to the start of the range. */
|
||||
ptr = (char *)(sqlite3_intptr_t)nEq;
|
||||
nConstraint = nEq;
|
||||
if( pRangeStart ){
|
||||
int dcc = pParse->disableColCache;
|
||||
if( pRangeEnd ){
|
||||
@ -2563,42 +2578,55 @@ WhereInfo *sqlite3WhereBegin(
|
||||
sqlite3ExprCode(pParse, pRangeStart->pExpr->pRight, regBase+nEq);
|
||||
pParse->disableColCache = dcc;
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
|
||||
ptr++;
|
||||
nConstraint++;
|
||||
}else if( isMinQuery ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
|
||||
ptr++;
|
||||
nConstraint++;
|
||||
startEq = 0;
|
||||
start_constraints = 1;
|
||||
}
|
||||
codeApplyAffinity(pParse, regBase, (int)ptr, pIdx);
|
||||
codeApplyAffinity(pParse, regBase, nConstraint, pIdx);
|
||||
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
||||
sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, ptr, P4_INT32);
|
||||
assert( op!=0 );
|
||||
testcase( op==OP_Rewind );
|
||||
testcase( op==OP_Last );
|
||||
testcase( op==OP_MoveGt );
|
||||
testcase( op==OP_MoveGe );
|
||||
testcase( op==OP_MoveLe );
|
||||
testcase( op==OP_MoveLt );
|
||||
sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase,
|
||||
(char*)nConstraint, P4_INT32);
|
||||
|
||||
/* Load the value for the inequality constraint at the end of the
|
||||
** range (if any).
|
||||
*/
|
||||
ptr = (char *)(sqlite3_intptr_t)nEq;
|
||||
nConstraint = nEq;
|
||||
if( pRangeEnd ){
|
||||
sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
|
||||
codeApplyAffinity(pParse, regBase, nEq+1, pIdx);
|
||||
ptr++;
|
||||
nConstraint++;
|
||||
}
|
||||
|
||||
/* Top of the loop body */
|
||||
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
|
||||
|
||||
/* Check if the index cursor is past the end of the range. */
|
||||
op = aEndOp[((pRangeEnd || nEq)?1:0) * (1 + bRev)];
|
||||
sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, ptr, P4_INT32);
|
||||
op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)];
|
||||
testcase( op==OP_Noop );
|
||||
testcase( op==OP_IdxGE );
|
||||
testcase( op==OP_IdxLT );
|
||||
sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase,
|
||||
(char*)nConstraint, P4_INT32);
|
||||
sqlite3VdbeChangeP5(v, endEq!=bRev);
|
||||
|
||||
/* If there are inequality constraints (there may not be if the
|
||||
** index is only being used to optimize ORDER BY), check that the
|
||||
** value of the table column the inequality contrains is not NULL.
|
||||
/* If there are inequality constraints, check that the value
|
||||
** of the table column that the inequality contrains is not NULL.
|
||||
** If it is, jump to the next iteration of the loop.
|
||||
*/
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
testcase( pLevel->flags & WHERE_BTM_LIMIT );
|
||||
testcase( pLevel->flags & WHERE_TOP_LIMIT );
|
||||
if( pLevel->flags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT) ){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, r1, cont);
|
||||
@ -2619,7 +2647,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
disableTerm(pLevel, pRangeStart);
|
||||
disableTerm(pLevel, pRangeEnd);
|
||||
}else{
|
||||
/* Case 5: There is no usable index. We must do a complete
|
||||
/* Case 4: There is no usable index. We must do a complete
|
||||
** scan of the entire table.
|
||||
*/
|
||||
assert( omitTable==0 );
|
||||
@ -2635,6 +2663,8 @@ WhereInfo *sqlite3WhereBegin(
|
||||
*/
|
||||
for(pTerm=wc.a, j=wc.nTerm; j>0; j--, pTerm++){
|
||||
Expr *pE;
|
||||
testcase( pTerm->flags & TERM_VIRTUAL );
|
||||
testcase( pTerm->flags & TERM_CODED );
|
||||
if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
||||
if( (pTerm->prereqAll & notReady)!=0 ) continue;
|
||||
pE = pTerm->pExpr;
|
||||
@ -2656,6 +2686,8 @@ WhereInfo *sqlite3WhereBegin(
|
||||
sqlite3ExprClearColumnCache(pParse, pLevel->iTabCur);
|
||||
sqlite3ExprClearColumnCache(pParse, pLevel->iIdxCur);
|
||||
for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){
|
||||
testcase( pTerm->flags & TERM_VIRTUAL );
|
||||
testcase( pTerm->flags & TERM_CODED );
|
||||
if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
||||
if( (pTerm->prereqAll & notReady)!=0 ) continue;
|
||||
assert( pTerm->pExpr );
|
||||
@ -2690,6 +2722,8 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
sqlite3_query_plan[nQPlan++] = ' ';
|
||||
}
|
||||
testcase( pLevel->flags & WHERE_ROWID_EQ );
|
||||
testcase( pLevel->flags & WHERE_ROWID_RANGE );
|
||||
if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
|
||||
memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
|
||||
nQPlan += 2;
|
||||
|
Loading…
x
Reference in New Issue
Block a user