Clean up and reorganize the elements of the various objects in the
analysis tree for the NGQP. FossilOrigin-Name: bfc76ae1e94fc5b7fd2c9484a36a8dfe6655d165
This commit is contained in:
parent
6f32848d61
commit
70d1834483
12
manifest
12
manifest
@ -1,5 +1,5 @@
|
||||
C Move\sthe\sdefinitions\sof\sthe\sWhereLevel\sand\sWhereInfo\sobjects\sout\sof\nsqliteInt.h\sand\sinto\swhere.c.\s\sThis\swill\sfacilitate\sfuture\srefactoring\nof\sthe\sinternal\squery\splanner\sdata\sstructures.
|
||||
D 2013-06-05T23:39:34.316
|
||||
C Clean\sup\sand\sreorganize\sthe\selements\sof\sthe\svarious\sobjects\sin\sthe\nanalysis\stree\sfor\sthe\sNGQP.
|
||||
D 2013-06-06T19:16:33.565
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -289,7 +289,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
|
||||
F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
|
||||
F src/where.c 83c6fce38c5c22a1573bc3acbc0d1241a140331a
|
||||
F src/where.c e3b7d7ef7aebae993b5ee37b7fc104f1dcea4bc0
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||
@ -1094,7 +1094,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P 9b1c4954e468d0acfb5787e6bff56d50a3e7bc1a
|
||||
R 2a5a6c03912e176e1d2592bfb6917650
|
||||
P 1574653b9b4522b489d4c62d9cf70166bb3bddfd
|
||||
R 5e3fae80c355d69a47b06cb86e66bb8c
|
||||
U drh
|
||||
Z 58f6e83bb7528a16d0e3d3a98418299b
|
||||
Z 38b156b13260a994e987fde6c73313cc
|
||||
|
@ -1 +1 @@
|
||||
1574653b9b4522b489d4c62d9cf70166bb3bddfd
|
||||
bfc76ae1e94fc5b7fd2c9484a36a8dfe6655d165
|
222
src/where.c
222
src/where.c
@ -45,8 +45,6 @@ typedef struct WherePath WherePath;
|
||||
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
|
||||
@ -86,35 +84,6 @@ struct WhereLevel {
|
||||
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
|
||||
@ -279,11 +248,9 @@ struct WhereScan {
|
||||
** 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 */
|
||||
@ -347,16 +314,46 @@ struct WhereMaskSet {
|
||||
*/
|
||||
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
|
||||
@ -454,17 +451,13 @@ int sqlite3WhereOkOnePass(WhereInfo *pWInfo){
|
||||
*/
|
||||
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 */
|
||||
@ -493,7 +486,7 @@ static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){
|
||||
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);
|
||||
@ -534,7 +527,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
|
||||
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 ){
|
||||
@ -811,14 +804,15 @@ WhereTerm *whereScanNext(WhereScan *pScan){
|
||||
/* 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;
|
||||
}
|
||||
@ -1177,11 +1171,11 @@ static void exprAnalyzeOrTerm(
|
||||
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 */
|
||||
@ -1200,7 +1194,7 @@ static void exprAnalyzeOrTerm(
|
||||
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;
|
||||
@ -1226,7 +1220,7 @@ static void exprAnalyzeOrTerm(
|
||||
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;
|
||||
@ -1235,7 +1229,7 @@ static void exprAnalyzeOrTerm(
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1246,10 +1240,10 @@ static void exprAnalyzeOrTerm(
|
||||
** 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 ){
|
||||
@ -1311,7 +1305,7 @@ static void exprAnalyzeOrTerm(
|
||||
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
|
||||
@ -1330,7 +1324,7 @@ static void exprAnalyzeOrTerm(
|
||||
** 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 );
|
||||
@ -1379,7 +1373,7 @@ static void exprAnalyzeOrTerm(
|
||||
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 );
|
||||
@ -1428,6 +1422,7 @@ static void exprAnalyze(
|
||||
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 */
|
||||
@ -1438,14 +1433,14 @@ static void exprAnalyze(
|
||||
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);
|
||||
@ -3068,7 +3063,6 @@ static void explainOneScan(
|
||||
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 */
|
||||
@ -3091,14 +3085,14 @@ static Bitmask codeOneLoopStart(
|
||||
|
||||
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
|
||||
@ -3355,7 +3349,7 @@ static Bitmask codeOneLoopStart(
|
||||
** 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)
|
||||
){
|
||||
@ -3624,7 +3618,7 @@ static Bitmask codeOneLoopStart(
|
||||
** 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);
|
||||
@ -3679,7 +3673,7 @@ static Bitmask codeOneLoopStart(
|
||||
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,
|
||||
@ -3751,7 +3745,7 @@ static Bitmask codeOneLoopStart(
|
||||
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.
|
||||
@ -3906,7 +3900,7 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
|
||||
*/
|
||||
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;
|
||||
@ -3945,8 +3939,8 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
||||
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
|
||||
@ -3969,7 +3963,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
||||
#if WHERETRACE_ENABLED
|
||||
if( sqlite3WhereTrace & 0x8 ){
|
||||
sqlite3DebugPrintf("ins-best: ");
|
||||
whereLoopPrint(pTemplate, pBuilder->pTabList);
|
||||
whereLoopPrint(pTemplate, pWInfo->pTabList);
|
||||
}
|
||||
#endif
|
||||
return SQLITE_OK;
|
||||
@ -4021,10 +4015,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
||||
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 ){
|
||||
@ -4060,7 +4054,7 @@ whereLoopInsert_noop:
|
||||
#if WHERETRACE_ENABLED
|
||||
if( sqlite3WhereTrace & 0x8 ){
|
||||
sqlite3DebugPrintf("ins-noop: ");
|
||||
whereLoopPrint(pTemplate, pBuilder->pTabList);
|
||||
whereLoopPrint(pTemplate, pWInfo->pTabList);
|
||||
}
|
||||
#endif
|
||||
return SQLITE_OK;
|
||||
@ -4079,7 +4073,9 @@ static int whereLoopAddBtreeIndex(
|
||||
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 */
|
||||
@ -4091,7 +4087,6 @@ static int whereLoopAddBtreeIndex(
|
||||
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;
|
||||
|
||||
@ -4173,18 +4168,18 @@ static int whereLoopAddBtreeIndex(
|
||||
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);
|
||||
|
||||
}
|
||||
@ -4227,7 +4222,7 @@ static int indexMightHelpWithOrderBy(
|
||||
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);
|
||||
@ -4249,10 +4244,12 @@ static int whereLoopAddBtree(
|
||||
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 */
|
||||
@ -4262,7 +4259,9 @@ static int whereLoopAddBtree(
|
||||
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 ){
|
||||
@ -4295,8 +4294,8 @@ static int whereLoopAddBtree(
|
||||
|
||||
/* 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
|
||||
@ -4356,9 +4355,9 @@ static int whereLoopAddBtree(
|
||||
/* 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;
|
||||
@ -4384,6 +4383,7 @@ static int whereLoopAddVirtual(
|
||||
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 */
|
||||
@ -4401,11 +4401,12 @@ static int whereLoopAddVirtual(
|
||||
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);
|
||||
@ -4532,6 +4533,7 @@ whereLoopAddVtab_exit:
|
||||
** btrees or virtual tables.
|
||||
*/
|
||||
static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
WhereInfo *pWInfo = pBuilder->pWInfo;
|
||||
WhereClause *pWC;
|
||||
WhereLoop *pNew;
|
||||
WhereTerm *pTerm, *pWCEnd;
|
||||
@ -4542,9 +4544,8 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
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;
|
||||
|
||||
@ -4559,7 +4560,7 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
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;
|
||||
@ -4569,11 +4570,9 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
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;
|
||||
@ -4610,14 +4609,15 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
** 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;
|
||||
|
||||
@ -4637,7 +4637,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -4698,7 +4698,6 @@ static int wherePathSatisfiesOrderBy(
|
||||
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 */
|
||||
|
||||
|
||||
/*
|
||||
@ -4739,7 +4738,6 @@ static int wherePathSatisfiesOrderBy(
|
||||
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 );
|
||||
@ -4870,7 +4868,7 @@ static int wherePathSatisfiesOrderBy(
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -5239,9 +5237,6 @@ WhereInfo *sqlite3WhereBegin(
|
||||
|
||||
/* 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
|
||||
@ -5269,11 +5264,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
*/
|
||||
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;
|
||||
@ -5285,12 +5276,11 @@ WhereInfo *sqlite3WhereBegin(
|
||||
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,...) */
|
||||
@ -5300,9 +5290,9 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** 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.
|
||||
@ -5347,7 +5337,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** 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;
|
||||
}
|
||||
@ -5356,7 +5346,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** 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;
|
||||
}
|
||||
@ -5467,7 +5457,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
#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 ){
|
||||
@ -5482,7 +5472,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
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;
|
||||
@ -5495,7 +5485,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user