typedef struct WhereTerm WhereTerm;
typedef struct WhereLoopBuilder WhereLoopBuilder;
typedef struct WhereScan WhereScan;
-typedef struct WhereVtabPlan WhereVtabPlan;
-
/*
** For each nested loop in a WHERE clause implementation, the WhereInfo
struct WhereLoop *pWLoop; /* The selected WhereLoop object */
};
-/*
-** The WHERE clause processing routine has two halves. The
-** first part does the start of the WHERE loop and the second
-** half does the tail of the WHERE loop. An instance of
-** this structure is returned by the first half and passed
-** into the second half to give some continuity.
-*/
-struct WhereInfo {
- Parse *pParse; /* Parsing and code generating context */
- SrcList *pTabList; /* List of tables in the join */
- ExprList *pOrderBy; /* The ORDER BY clause or NULL */
- ExprList *pDistinct; /* DISTINCT ON values, or NULL */
- Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
- u16 nOBSat; /* Number of ORDER BY terms satisfied by indices */
- u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
- u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
- u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
- u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
- int iTop; /* The very beginning of the WHERE loop */
- int iContinue; /* Jump here to continue with next record */
- int iBreak; /* Jump here to break out of the loop */
- int nLevel; /* Number of nested loop */
- struct WhereClause *pWC; /* Decomposition of the WHERE clause */
- struct WhereLoop *pLoops; /* List of all WhereLoop objects */
- double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
- double nRowOut; /* Estimated number of output rows */
- WhereLevel a[1]; /* Information about each nest loop in WHERE */
-};
-
/*
** Each instance of this object represents a way of evaluating one
** term of a join. The WhereClause object holds a table of these
** 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 */
+ WhereInfo *pWInfo; /* WHERE clause processing context */
WhereClause *pOuter; /* Outer conjunction */
u8 op; /* Split operator. TK_AND or TK_OR */
- u16 wctrlFlags; /* Might include WHERE_AND_ONLY */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
*/
struct WhereLoopBuilder {
WhereInfo *pWInfo; /* Information about this WHERE */
- sqlite3 *db; /* Database connection */
- Parse *pParse; /* Parsing context */
+// sqlite3 *db; /* Database connection */
+// Parse *pParse; /* Parsing context */
+// SrcList *pTabList; /* FROM clause */
WhereClause *pWC; /* WHERE clause terms */
- SrcList *pTabList; /* FROM clause */
ExprList *pOrderBy; /* ORDER BY clause */
WhereLoop *pNew; /* Template WhereLoop */
WhereLoop *pBest; /* If non-NULL, store single best loop here */
int mxTerm; /* Maximum number of aTerm[] entries on pNew */
};
+/*
+** The WHERE clause processing routine has two halves. The
+** first part does the start of the WHERE loop and the second
+** half does the tail of the WHERE loop. An instance of
+** this structure is returned by the first half and passed
+** into the second half to give some continuity.
+*/
+struct WhereInfo {
+ Parse *pParse; /* Parsing and code generating context */
+ SrcList *pTabList; /* List of tables in the join */
+ ExprList *pOrderBy; /* The ORDER BY clause or NULL */
+ ExprList *pDistinct; /* DISTINCT ON values, or NULL */
+ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
+ u16 nOBSat; /* Number of ORDER BY terms satisfied by indices */
+ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
+ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
+ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
+ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
+ int iTop; /* The very beginning of the WHERE loop */
+ int iContinue; /* Jump here to continue with next record */
+ int iBreak; /* Jump here to break out of the loop */
+ int nLevel; /* Number of nested loop */
+ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
+ WhereClause sWC; /* Decomposition of the WHERE clause */
+ WhereLoop *pLoops; /* List of all WhereLoop objects */
+ double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
+ double nRowOut; /* Estimated number of output rows */
+ WhereLevel a[1]; /* Information about each nest loop in WHERE */
+};
+
/*
** Bitmasks for the operators that indices are able to exploit. An
** OR-ed combination of these values can be used when searching for
*/
static void whereClauseInit(
WhereClause *pWC, /* The WhereClause to be initialized */
- Parse *pParse, /* The parsing context */
- WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmasks */
- u16 wctrlFlags /* Might include WHERE_AND_ONLY */
+ WhereInfo *pWInfo /* The WHERE processing context */
){
- pWC->pParse = pParse;
- pWC->pMaskSet = pMaskSet;
+ pWC->pWInfo = pWInfo;
pWC->pOuter = 0;
pWC->nTerm = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
pWC->a = pWC->aStatic;
- pWC->wctrlFlags = wctrlFlags;
}
/* Forward reference */
static void whereClauseClear(WhereClause *pWC){
int i;
WhereTerm *a;
- sqlite3 *db = pWC->pParse->db;
+ sqlite3 *db = pWC->pWInfo->pParse->db;
for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
if( a->wtFlags & TERM_DYNAMIC ){
sqlite3ExprDelete(db, a->pExpr);
testcase( wtFlags & TERM_VIRTUAL ); /* EV: R-00211-15100 */
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
- sqlite3 *db = pWC->pParse->db;
+ sqlite3 *db = pWC->pWInfo->pParse->db;
pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
if( pWC->a==0 ){
if( wtFlags & TERM_DYNAMIC ){
/* Verify the affinity and collating sequence match */
if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
CollSeq *pColl;
+ Parse *pParse = pWC->pWInfo->pParse;
pX = pTerm->pExpr;
if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
continue;
}
assert(pX->pLeft);
- pColl = sqlite3BinaryCompareCollSeq(pWC->pParse,
+ pColl = sqlite3BinaryCompareCollSeq(pParse,
pX->pLeft, pX->pRight);
- if( pColl==0 ) pColl = pWC->pParse->db->pDfltColl;
+ if( pColl==0 ) pColl = pParse->db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
continue;
}
WhereClause *pWC, /* the complete WHERE clause */
int idxTerm /* Index of the OR-term to be analyzed */
){
- Parse *pParse = pWC->pParse; /* Parser context */
+ WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
+ Parse *pParse = pWInfo->pParse; /* Parser context */
sqlite3 *db = pParse->db; /* Database connection */
WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */
Expr *pExpr = pTerm->pExpr; /* The expression of the term */
- WhereMaskSet *pMaskSet = pWC->pMaskSet; /* Table use masks */
int i; /* Loop counters */
WhereClause *pOrWc; /* Breakup of pTerm into subterms */
WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */
if( pOrInfo==0 ) return;
pTerm->wtFlags |= TERM_ORINFO;
pOrWc = &pOrInfo->wc;
- whereClauseInit(pOrWc, pWC->pParse, pMaskSet, pWC->wctrlFlags);
+ whereClauseInit(pOrWc, pWInfo);
whereSplit(pOrWc, pExpr, TK_OR);
exprAnalyzeAll(pSrc, pOrWc);
if( db->mallocFailed ) return;
pOrTerm->wtFlags |= TERM_ANDINFO;
pOrTerm->eOperator = WO_AND;
pAndWC = &pAndInfo->wc;
- whereClauseInit(pAndWC, pWC->pParse, pMaskSet, pWC->wctrlFlags);
+ whereClauseInit(pAndWC, pWC->pWInfo);
whereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
exprAnalyzeAll(pSrc, pAndWC);
pAndWC->pOuter = pWC;
for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
assert( pAndTerm->pExpr );
if( allowedOp(pAndTerm->pExpr->op) ){
- b |= getMask(pMaskSet, pAndTerm->leftCursor);
+ b |= getMask(&pWInfo->sMaskSet, pAndTerm->leftCursor);
}
}
}
** corresponding TERM_VIRTUAL term */
}else{
Bitmask b;
- b = getMask(pMaskSet, pOrTerm->leftCursor);
+ b = getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor);
if( pOrTerm->wtFlags & TERM_VIRTUAL ){
WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
- b |= getMask(pMaskSet, pOther->leftCursor);
+ b |= getMask(&pWInfo->sMaskSet, pOther->leftCursor);
}
indexable &= b;
if( (pOrTerm->eOperator & WO_EQ)==0 ){
assert( j==1 );
continue;
}
- if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){
+ if( (chngToIN & getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor))==0 ){
/* This term must be of the form t1.a==t2.b where t2 is in the
** chngToIN set but t1 is not. This term will be either preceeded
** or follwed by an inverted copy (t2.b==t1.a). Skip this term
** on the second iteration */
assert( j==1 );
assert( IsPowerOfTwo(chngToIN) );
- assert( chngToIN==getMask(pMaskSet, iCursor) );
+ assert( chngToIN==getMask(&pWInfo->sMaskSet, iCursor) );
break;
}
testcase( j==1 );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
- pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
+ pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
}
assert( pLeft!=0 );
WhereClause *pWC, /* the WHERE clause */
int idxTerm /* Index of the term to be analyzed */
){
+ WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
WhereTerm *pTerm; /* The term to be analyzed */
WhereMaskSet *pMaskSet; /* Set of table index masks */
Expr *pExpr; /* The expression to be analyzed */
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
int noCase = 0; /* LIKE/GLOB distinguishes case */
int op; /* Top-level operator. pExpr->op */
- Parse *pParse = pWC->pParse; /* Parsing context */
+ Parse *pParse = pWInfo->pParse; /* Parsing context */
sqlite3 *db = pParse->db; /* Database connection */
if( db->mallocFailed ){
return;
}
pTerm = &pWC->a[idxTerm];
- pMaskSet = pWC->pMaskSet;
+ pMaskSet = &pWInfo->sMaskSet;
pExpr = pTerm->pExpr;
assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
static Bitmask codeOneLoopStart(
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 */
){
int j, k; /* Loop counters */
pParse = pWInfo->pParse;
v = pParse->pVdbe;
- pWC = pWInfo->pWC;
+ pWC = &pWInfo->sWC;
pLevel = &pWInfo->a[iLevel];
pLoop = pLevel->pWLoop;
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
bRev = (pWInfo->revMask>>iLevel)&1;
omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
- && (wctrlFlags & WHERE_FORCE_TABLE)==0;
+ && (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0;
VdbeNoopComment((v, "Begin Join Loop %d", iLevel));
/* Create labels for the "break" and "continue" instructions
** the first one after the nEq equality constraints in the index,
** this requires some special handling.
*/
- if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0
+ if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
&& (pWInfo->nOBSat>0)
&& (pIdx->nColumn>nEq)
){
** fall through to the next instruction, just as an OP_Next does if
** called on an uninitialized cursor.
*/
- if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
regRowset = ++pParse->nMem;
regRowid = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
explainOneScan(
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
);
- if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
int r;
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}
- newNotReady = notReady & ~getMask(pWC->pMaskSet, iCur);
+ newNotReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur);
/* Insert code to test every subexpression that can be completely
** computed using the current set of tables.
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
if( ALWAYS(pWInfo) ){
- whereClauseClear(pWInfo->pWC);
+ whereClauseClear(&pWInfo->sWC);
while( pWInfo->pLoops ){
WhereLoop *p = pWInfo->pLoops;
pWInfo->pLoops = p->pNextLoop;
static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
WhereLoop **ppPrev, *p, *pNext = 0, *pToFree = 0;
WhereTerm **paTerm = 0;
- sqlite3 *db = pBuilder->db;
WhereInfo *pWInfo = pBuilder->pWInfo;
+ sqlite3 *db = pWInfo->pParse->db;
/* If pBuilder->pBest is defined, then only keep track of the single
** best WhereLoop. pBuilder->pBest->maskSelf==0 indicates that no
#if WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf("ins-best: ");
- whereLoopPrint(pTemplate, pBuilder->pTabList);
+ whereLoopPrint(pTemplate, pWInfo->pTabList);
}
#endif
return SQLITE_OK;
if( sqlite3WhereTrace & 0x8 ){
if( p!=0 ){
sqlite3DebugPrintf("ins-del: ");
- whereLoopPrint(p, pBuilder->pTabList);
+ whereLoopPrint(p, pWInfo->pTabList);
}
sqlite3DebugPrintf("ins-new: ");
- whereLoopPrint(pTemplate, pBuilder->pTabList);
+ whereLoopPrint(pTemplate, pWInfo->pTabList);
}
#endif
if( p==0 ){
#if WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf("ins-noop: ");
- whereLoopPrint(pTemplate, pBuilder->pTabList);
+ whereLoopPrint(pTemplate, pWInfo->pTabList);
}
#endif
return SQLITE_OK;
Index *pProbe, /* An index on pSrc */
int nInMul /* Number of iterations due to IN */
){
- sqlite3 *db; /* Database connection malloc context */
+ WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
+ Parse *pParse = pWInfo->pParse; /* Parsing context */
+ sqlite3 *db = pParse->db; /* Database connection malloc context */
WhereLoop *pNew; /* Template WhereLoop under construction */
WhereTerm *pTerm; /* A WhereTerm under consideration */
int opMask; /* Valid operators for constraints */
double rLogSize; /* Logarithm of table size */
WhereTerm *pTop, *pBtm; /* Top and bottom range constraints */
- db = pBuilder->db;
pNew = pBuilder->pNew;
if( db->mallocFailed ) return SQLITE_NOMEM;
if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
/* Adjust nOut and rRun for STAT3 range values */
double rDiv;
- whereRangeScanEst(pBuilder->pParse, pProbe, pNew->u.btree.nEq,
+ whereRangeScanEst(pParse, pProbe, pNew->u.btree.nEq,
pBtm, pTop, &rDiv);
pNew->nOut = savedLoop.nOut/rDiv;
}
#ifdef SQLITE_ENABLE_STAT3
if( pNew->u.btree.nEq==1 && pProbe->nSample ){
if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){
- rc = whereEqualScanEst(pBuilder->pParse, pProbe, pTerm->pExpr->pRight,
+ rc = whereEqualScanEst(pParse, pProbe, pTerm->pExpr->pRight,
&pNew->nOut);
}else if( (pTerm->eOperator & WO_IN)
&& !ExprHasProperty(pTerm->pExpr, EP_xIsSelect) ){
- rc = whereInScanEst(pBuilder->pParse, pProbe, pTerm->pExpr->x.pList,
+ rc = whereInScanEst(pParse, pProbe, pTerm->pExpr->x.pList,
&pNew->nOut);
}
int iCol;
int ii;
- if( (pOB = pBuilder->pOrderBy)==0 ) return 0;
+ if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
iCol = pIndex->aiColumn[0];
for(ii=0; ii<pOB->nExpr; ii++){
Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
WhereLoopBuilder *pBuilder, /* WHERE clause information */
Bitmask mExtra /* Extra prerequesites for using this table */
){
+ WhereInfo *pWInfo; /* WHERE analysis context */
Index *pProbe; /* An index we are evaluating */
Index sPk; /* A fake index object for the primary key */
tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
+ SrcList *pTabList; /* The FROM clause */
struct SrcList_item *pSrc; /* The FROM clause btree term to add */
WhereLoop *pNew; /* Template WhereLoop object */
int rc = SQLITE_OK; /* Return code */
double rLogSize; /* Logarithm of the number of rows in the table */
pNew = pBuilder->pNew;
- pSrc = pBuilder->pTabList->a + pNew->iTab;
+ pWInfo = pBuilder->pWInfo;
+ pTabList = pWInfo->pTabList;
+ pSrc = pTabList->a + pNew->iTab;
assert( !IsVirtual(pSrc->pTab) );
if( pSrc->pIndex ){
/* Automatic indexes */
if( !pBuilder->pBest
- && pBuilder->pTabList->nSrc>1
- && (pBuilder->pParse->db->flags & SQLITE_AutoIndex)!=0
+ && pTabList->nSrc>1
+ && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
&& !pSrc->viaCoroutine
&& !pSrc->notIndexed
&& !pSrc->isCorrelated
/* Full scan via index */
if( (m==0 || b)
&& pProbe->bUnordered==0
- && (pBuilder->pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
+ && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
&& sqlite3GlobalConfig.bUseCis
- && OptimizationEnabled(pBuilder->pParse->db, SQLITE_CoverIdxScan)
+ && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
){
pNew->iSortIdx = b ? iSortIdx : 0;
pNew->nOut = rSize;
WhereLoopBuilder *pBuilder, /* WHERE clause information */
Bitmask mExtra /* Extra prerequesites for using this table */
){
+ WhereInfo *pWInfo; /* WHERE analysis context */
Parse *pParse; /* The parsing context */
WhereClause *pWC; /* The WHERE clause */
struct SrcList_item *pSrc; /* The FROM clause term to search */
WhereLoop *pNew;
int rc = SQLITE_OK;
- pParse = pBuilder->pParse;
+ pWInfo = pBuilder->pWInfo;
+ pParse = pWInfo->pParse;
db = pParse->db;
pWC = pBuilder->pWC;
pNew = pBuilder->pNew;
- pSrc = &pBuilder->pTabList->a[pNew->iTab];
+ pSrc = &pWInfo->pTabList->a[pNew->iTab];
pTab = pSrc->pTab;
assert( IsVirtual(pTab) );
pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pBuilder->pOrderBy);
** btrees or virtual tables.
*/
static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
+ WhereInfo *pWInfo = pBuilder->pWInfo;
WhereClause *pWC;
WhereLoop *pNew;
WhereTerm *pTerm, *pWCEnd;
WhereLoop sBest;
struct SrcList_item *pItem;
-
pWC = pBuilder->pWC;
- if( pWC->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
+ if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
pWCEnd = pWC->a + pWC->nTerm;
pNew = pBuilder->pNew;
double nRow = 0;
Bitmask prereq = mExtra;
- pItem = pBuilder->pTabList->a + pNew->iTab;
+ pItem = pWInfo->pTabList->a + pNew->iTab;
iCur = pItem->iCursor;
sSubBuild = *pBuilder;
sSubBuild.pOrderBy = 0;
if( (pOrTerm->eOperator & WO_AND)!=0 ){
sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
}else if( pOrTerm->leftCursor==iCur ){
- tempWC.pParse = pWC->pParse;
- tempWC.pMaskSet = pWC->pMaskSet;
+ tempWC.pWInfo = pWC->pWInfo;
tempWC.pOuter = pWC;
tempWC.op = TK_AND;
- tempWC.wctrlFlags = 0;
tempWC.nTerm = 1;
tempWC.a = pOrTerm;
sSubBuild.pWC = &tempWC;
** Add all WhereLoop objects for all tables
*/
static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
+ WhereInfo *pWInfo = pBuilder->pWInfo;
Bitmask mExtra = 0;
Bitmask mPrior = 0;
int iTab;
- SrcList *pTabList = pBuilder->pTabList;
+ SrcList *pTabList = pWInfo->pTabList;
struct SrcList_item *pItem;
WhereClause *pWC = pBuilder->pWC;
- sqlite3 *db = pBuilder->db;
- int nTabList = pBuilder->pWInfo->nLevel;
+ sqlite3 *db = pWInfo->pParse->db;
+ int nTabList = pWInfo->nLevel;
int rc = SQLITE_OK;
WhereLoop *pNew;
}
for(iTab=0, pItem=pTabList->a; iTab<nTabList; iTab++, pItem++){
pNew->iTab = iTab;
- pNew->maskSelf = getMask(pWC->pMaskSet, pItem->iCursor);
+ pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor);
if( (pItem->jointype & (JT_LEFT|JT_CROSS))!=0 ){
mExtra = mPrior;
}
Bitmask obSat = 0; /* Mask of ORDER BY terms satisfied so far */
Bitmask obDone; /* Mask of all ORDER BY terms */
Bitmask orderDistinctMask; /* Mask of all well-ordered loops */
- WhereMaskSet *pMaskSet; /* WhereMaskSet object for this where clause */
/*
isOrderDistinct = 1;
obDone = MASKBIT(nOrderBy)-1;
orderDistinctMask = 0;
- pMaskSet = pWInfo->pWC->pMaskSet;
for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast;
assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
Expr *p;
if( MASKBIT(i) & obSat ) continue;
p = pOrderBy->a[i].pExpr;
- if( (exprTableUsage(pMaskSet, p)&~orderDistinctMask)==0 ){
+ if( (exprTableUsage(&pWInfo->sMaskSet, p)&~orderDistinctMask)==0 ){
obSat |= MASKBIT(i);
}
}
/* Variable initialization */
memset(&sWLB, 0, sizeof(sWLB));
- sWLB.pParse = pParse;
- sWLB.db = pParse->db;
- sWLB.pTabList = pTabList;
sWLB.pOrderBy = pOrderBy;
/* The number of tables in the FROM clause is limited by the number of
*/
db = pParse->db;
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
- pWInfo = sqlite3DbMallocZero(db,
- nByteWInfo +
- sizeof(WhereClause) +
- sizeof(WhereMaskSet)
- );
+ pWInfo = sqlite3DbMallocZero(db, nByteWInfo);
if( db->mallocFailed ){
sqlite3DbFree(db, pWInfo);
pWInfo = 0;
pWInfo->pOrderBy = pOrderBy;
pWInfo->pDistinct = pDistinct;
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
- pWInfo->pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
- pMaskSet = (WhereMaskSet*)&pWInfo->pWC[1];
+ pMaskSet = &pWInfo->sMaskSet;
sWLB.pWInfo = pWInfo;
- sWLB.pWC = pWInfo->pWC;
+ sWLB.pWC = &pWInfo->sWC;
/* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
** subexpression is separated by an AND operator.
*/
initMaskSet(pMaskSet);
- whereClauseInit(pWInfo->pWC, pParse, pMaskSet, wctrlFlags);
+ whereClauseInit(&pWInfo->sWC, pWInfo);
sqlite3ExprCodeConstants(pParse, pWhere);
- whereSplit(pWInfo->pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
+ whereSplit(&pWInfo->sWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
/* Special case: a WHERE clause that is constant. Evaluate the
** expression and either jump over all of the code or fall thru.
** want to analyze these virtual terms, so start analyzing at the end
** and work forward so that the added virtual terms are never processed.
*/
- exprAnalyzeAll(pTabList, pWInfo->pWC);
+ exprAnalyzeAll(pTabList, &pWInfo->sWC);
if( db->mallocFailed ){
goto whereBeginError;
}
** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
*/
- if( pDistinct && isDistinctRedundant(pParse,pTabList,pWInfo->pWC,pDistinct) ){
+ if( pDistinct && isDistinctRedundant(pParse,pTabList,&pWInfo->sWC,pDistinct) ){
pDistinct = 0;
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}
}
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
if( (pLoop->wsFlags & WHERE_TEMP_INDEX)!=0 ){
- constructAutomaticIndex(pParse, pWInfo->pWC, pTabItem, notReady, pLevel);
+ constructAutomaticIndex(pParse, &pWInfo->sWC, pTabItem, notReady, pLevel);
}else
#endif
if( pLoop->wsFlags & WHERE_INDEXED ){
VdbeComment((v, "%s", pIx->zName));
}
sqlite3CodeVerifySchema(pParse, iDb);
- notReady &= ~getMask(pWInfo->pWC->pMaskSet, pTabItem->iCursor);
+ notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor);
}
pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
if( db->mallocFailed ) goto whereBeginError;
for(ii=0; ii<nTabList; ii++){
pLevel = &pWInfo->a[ii];
explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
- notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady);
+ notReady = codeOneLoopStart(pWInfo, ii, notReady);
pWInfo->iContinue = pLevel->addrCont;
}