From 981642f3896a383b6db14ce56445be4e17b5d982 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 19 Apr 2008 14:40:43 +0000 Subject: [PATCH] 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 --- manifest | 12 ++++---- manifest.uuid | 2 +- src/where.c | 84 ++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 66 insertions(+), 32 deletions(-) diff --git a/manifest b/manifest index 09726b55c6..6cb4b86d29 100644 --- a/manifest +++ b/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 diff --git a/manifest.uuid b/manifest.uuid index 0ea254a6af..bc25a98ea9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f7b62daa9fe71dc713bde107507fc7bcb812d62b \ No newline at end of file +adcef73b3925266a14a552cd9b06c14f22aaefc8 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 5bce2262ee..c12462822d 100644 --- a/src/where.c +++ b/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; inTerm; 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; inTerm; 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; jflags & 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; -- 2.47.2