-C Enhance\sthe\ssqlite3_data_count()\sroutine\sso\sthat\sit\scan\sbe\sused\sto\sdetermine\nif\sSQLITE_DONE\shas\sbeen\sseen\son\sthe\sprepared\sstatement.
-D 2011-10-07T12:59:23.182
+C Begin\san\seffort\sto\senhance\sthe\squery\splanner\sto\sdo\sa\sbetter\sjob\swith\sOR\sterms\nin\sthe\sWHERE\sclause.\s\sThis\schange\sallows\sANDs\soutside\sof\sthe\sOR\sto\sbe\sfactored\ninto\sthe\sOR\sterms\sif\sthat\sis\shelpful\sin\sfinding\sbetter\sindices.
+D 2011-10-07T13:33:10.760
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in a162fe39e249b8ed4a65ee947c30152786cfe897
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/wal.c 3154756177d6219e233d84291d5b05f4e06ff5e9
F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
-F src/where.c aafcb21a74e41f9aae76ea604e1e787ff8574125
+F src/where.c 80c53e8e21fe9c5c5830e33d806fc168577427ed
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P baa80c7bc31900decae0d8e6090b30fcde377492
-R 1223a474d1e5cea6170a2af45d3f0303
+P 9913996e7b0f94ba1c51200b61433193002f3638
+R 7d8737bed3e72adf3b068f98f3f5d762
+T *branch * or-opt
+T *sym-or-opt *
+T -sym-trunk *
U drh
-Z 7e8fd93d23ec7d2fecbdff0e025997fa
+Z 6d6f0e795135cadc2210cb2fc14d2593
/*
** An instance of the following structure holds all information about a
** WHERE clause. Mostly this is a container for one or more WhereTerms.
+**
+** Explanation of pOuter: For a WHERE clause of the form
+**
+** a AND ((b AND c) OR (d AND e)) AND f
+**
+** There are separate WhereClause objects for the whole clause and for
+** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the
+** subclauses points to the WhereClause object for the whole clause.
*/
struct WhereClause {
Parse *pParse; /* The parser context */
WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */
Bitmask vmask; /* Bitmask identifying virtual table cursors */
+ WhereClause *pOuter; /* Outer conjunction */
u8 op; /* Split operator. TK_AND or TK_OR */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
){
pWC->pParse = pParse;
pWC->pMaskSet = pMaskSet;
+ pWC->pOuter = 0;
pWC->nTerm = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
pWC->a = pWC->aStatic;
int k;
assert( iCur>=0 );
op &= WO_ALL;
- for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
- if( pTerm->leftCursor==iCur
- && (pTerm->prereqRight & notReady)==0
- && pTerm->u.leftColumn==iColumn
- && (pTerm->eOperator & op)!=0
- ){
- if( pIdx && pTerm->eOperator!=WO_ISNULL ){
- Expr *pX = pTerm->pExpr;
- CollSeq *pColl;
- char idxaff;
- int j;
- Parse *pParse = pWC->pParse;
-
- idxaff = pIdx->pTable->aCol[iColumn].affinity;
- if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
-
- /* Figure out the collation sequence required from an index for
- ** it to be useful for optimising expression pX. Store this
- ** value in variable pColl.
- */
- assert(pX->pLeft);
- pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
- assert(pColl || pParse->nErr);
-
- for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
- if( NEVER(j>=pIdx->nColumn) ) return 0;
+ for(; pWC; pWC=pWC->pOuter){
+ for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
+ if( pTerm->leftCursor==iCur
+ && (pTerm->prereqRight & notReady)==0
+ && pTerm->u.leftColumn==iColumn
+ && (pTerm->eOperator & op)!=0
+ ){
+ if( pIdx && pTerm->eOperator!=WO_ISNULL ){
+ Expr *pX = pTerm->pExpr;
+ CollSeq *pColl;
+ char idxaff;
+ int j;
+ Parse *pParse = pWC->pParse;
+
+ idxaff = pIdx->pTable->aCol[iColumn].affinity;
+ if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
+
+ /* Figure out the collation sequence required from an index for
+ ** it to be useful for optimising expression pX. Store this
+ ** value in variable pColl.
+ */
+ assert(pX->pLeft);
+ pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
+ assert(pColl || pParse->nErr);
+
+ for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
+ if( NEVER(j>=pIdx->nColumn) ) return 0;
+ }
+ if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
}
- if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
+ return pTerm;
}
- return pTerm;
}
}
return 0;
whereClauseInit(pAndWC, pWC->pParse, pMaskSet);
whereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
exprAnalyzeAll(pSrc, pAndWC);
+ pAndWC->pOuter = pWC;
testcase( db->mallocFailed );
if( !db->mallocFailed ){
for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
WhereClause tempWC;
tempWC.pParse = pWC->pParse;
tempWC.pMaskSet = pWC->pMaskSet;
+ tempWC.pOuter = pWC;
tempWC.op = TK_AND;
tempWC.a = pOrTerm;
tempWC.nTerm = 1;
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
- Bitmask notReady /* Which tables are currently available */
+ Bitmask notReady, /* Which tables are currently available */
+ Expr *pWhere /* Complete WHERE clause */
){
int j, k; /* Loop counters */
int iCur; /* The VDBE cursor for the table */
int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
int iRetInit; /* Address of regReturn init */
int untestedTerms = 0; /* Some terms not completely tested */
- int ii;
+ int ii; /* Loop counter */
+ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
pTerm = pLevel->plan.u.pTerm;
assert( pTerm!=0 );
}
iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
+ /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y
+ ** Then for every term xN, evaluate as the subexpression: xN AND z
+ ** That way, terms in y that are factored into the disjunction will
+ ** be picked up by the recursive calls to sqlite3WhereBegin() below.
+ */
+ if( pWC->nTerm>1 ){
+ pAndExpr = sqlite3ExprAlloc(pParse->db, TK_AND, 0, 0);
+ pAndExpr->pRight = pWhere;
+ }
+
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
+ Expr *pOrExpr = pOrTerm->pExpr;
+ if( pAndExpr ){
+ pAndExpr->pLeft = pOrExpr;
+ pOrExpr = pAndExpr;
+ }
/* Loop through table entries that match term pOrTerm. */
- pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0, 0,
+ pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
if( pSubWInfo ){
}
}
}
+ sqlite3DbFree(pParse->db, pAndExpr);
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
sqlite3VdbeResolveLabel(v, iLoopBody);
for(i=0; i<nTabList; i++){
pLevel = &pWInfo->a[i];
explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags);
- notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
+ notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady, pWhere);
pWInfo->iContinue = pLevel->addrCont;
}