-C Simplify\sthe\sVM\scode\sthat\simplements\sWHERE\sclaues.\s(CVS\s6067)
-D 2008-12-28T16:55:25
+C Optimize\sWHERE\sclauses\sthat\sconstain\sAND,\sBETWEEN,\sand\sLIKE\sterms\sas\soperands\nof\san\sOR.\s(CVS\s6068)
+D 2008-12-28T18:35:09
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 77635d0909c2067cee03889a1e04ce910d8fb809
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/vdbemem.c f9c859ac17e2e05a0f249868ce4f191f69edd31d
F src/vtab.c e39e011d7443a8d574b1b9cde207a35522e6df43
F src/walker.c 488c2660e13224ff70c0c82761118efb547f8f0d
-F src/where.c f41330e71f3dde12cc6631ae9f75c9869b92c32b
+F src/where.c 4050b918a379e23d5b645d888b91dba2e7c469a9
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 597662c5d777a122f9a3df0047ea5c5bd383a911
F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 42c4373595f4409d9c6a9987b4a60000ad664faf
-F test/where7.test b04da5cee08a573c120c95781d7413a7e25ac8d5
+F test/where7.test c27e4865d69b35dc21b4cbff097cf02e9cdc9950
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/zeroblob.test 792124852ec61458a2eb527b5091791215e0be95
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 08352f9ea9d2a1759320efc46e418079000855cb
-R b27114cf38ee45f9d895c0015e5cf61b
+P fa95f843e179a38f663978d675607c4c3037928d
+R 7f2475a8de47b6500bdb0400363621d0
U drh
-Z 5701aac5e9c50a29a7e1c4535e66ab21
+Z 2bf13b04bd3fbd90db56a109bb7f3eb1
** 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.345 2008/12/28 16:55:25 drh Exp $
+** $Id: where.c,v 1.346 2008/12/28 18:35:09 drh Exp $
*/
#include "sqliteInt.h"
struct WhereClause {
Parse *pParse; /* The parser context */
WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */
+ u8 op; /* Split operator. TK_AND or TK_OR */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
** a dynamically allocated instance of the following structure.
*/
struct WhereAndInfo {
- WhereClause wc; /* The OR subexpression broken out */
- Index *pIdx; /* Index to use */
- double cost; /* Cost of evaluating this OR subexpression */
+ WhereClause wc; /* The subexpression broken out */
};
/*
** all terms of the WHERE clause.
*/
static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
+ pWC->op = (u8)op;
if( pExpr==0 ) return;
if( pExpr->op!=op ){
whereClauseInsert(pWC, pExpr, 0);
indexable = chngToIN = ~(Bitmask)0;
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
+ WhereAndInfo *pAndInfo;
+ assert( pOrTerm->eOperator==0 );
+ assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
chngToIN = 0;
- indexable = 0; /***** FIX ME. Some AND clauses are indexable. */
+ pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
+ if( pAndInfo ){
+ WhereClause *pAndWC;
+ WhereTerm *pAndTerm;
+ int j;
+ Bitmask b = 0;
+ pOrTerm->u.pAndInfo = pAndInfo;
+ pOrTerm->wtFlags |= TERM_ANDINFO;
+ pOrTerm->eOperator = WO_AND;
+ pAndWC = &pAndInfo->wc;
+ whereClauseInit(pAndWC, pWC->pParse, pMaskSet);
+ whereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
+ exprAnalyzeAll(pSrc, pAndWC);
+ for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
+ if( pAndTerm->pExpr && allowedOp(pAndTerm->pExpr->op) ){
+ b |= getMask(pMaskSet, pAndTerm->leftCursor);
+ }
+ }
+ indexable &= b;
+ }
}else if( pOrTerm->wtFlags & TERM_COPIED ){
/* Skip this term for now. We revisit it when we process the
** corresponding TERM_VIRTUAL term */
** skipped. Or, if the children are satisfied by an index, the original
** BETWEEN term is skipped.
*/
- else if( pExpr->op==TK_BETWEEN ){
+ else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
ExprList *pList = pExpr->pList;
int i;
static const u8 ops[] = {TK_GE, TK_LE};
** an OR operator.
*/
else if( pExpr->op==TK_OR ){
+ assert( pWC->op==TK_AND );
exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
}
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
** The last character of the prefix "abc" is incremented to form the
** termination condition "abd".
*/
- if( isLikeOrGlob(pParse, pExpr, &nPattern, &isComplete, &noCase) ){
+ if( isLikeOrGlob(pParse, pExpr, &nPattern, &isComplete, &noCase)
+ && pWC->op==TK_AND ){
Expr *pLeft, *pRight;
Expr *pStr1, *pStr2;
Expr *pNewExpr1, *pNewExpr2;
double nRow = 0;
for(j=0, pOrTerm=pOrWC->a; j<pOrWC->nTerm; j++, pOrTerm++){
WhereCost sTermCost;
- if( pOrTerm->leftCursor!=iCur ) continue;
- tempWC.a = pOrTerm;
- bestIndex(pParse, &tempWC, pSrc, notReady, 0, &sTermCost);
+ if( pOrTerm->eOperator==WO_AND ){
+ WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc;
+ bestIndex(pParse, pAndWC, pSrc, notReady, 0, &sTermCost);
+ }else if( pOrTerm->leftCursor==iCur ){
+ tempWC.a = pOrTerm;
+ bestIndex(pParse, &tempWC, pSrc, notReady, 0, &sTermCost);
+ }else{
+ continue;
+ }
if( sTermCost.plan.wsFlags==0 ){
rTotal = pCost->rCost;
break;
oneTab.a[0] = *pTabItem;
for(j=0, pOrTerm=pOrWc->a; j<pOrWc->nTerm; j++, pOrTerm++){
WhereInfo *pSubWInfo;
- if( pOrTerm->leftCursor!=iCur ) continue;
+ if( pOrTerm->leftCursor!=iCur && pOrTerm->eOperator!=WO_AND ) continue;
pSubWInfo = sqlite3WhereBegin(pParse, &oneTab, pOrTerm->pExpr, 0,
WHERE_FILL_ROWSET | WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE,
regOrRowset);