aboutsummaryrefslogtreecommitdiff
path: root/src/where.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2014-10-31 14:53:32 +0000
committerdrh <drh@noemail.net>2014-10-31 14:53:32 +0000
commitca3e10ea37c4808fa84063f06b02229801b28cc0 (patch)
tree25f7d9b2ab4ff71311882bcee951b6e9ab1cb62f /src/where.c
parentbc2866ca7abc2ad7cbb6878d65cd18e584cff8f5 (diff)
parent0fb5daed34ba6f16d761b8ad02b944ec59cf5c03 (diff)
downloadsqlite-ca3e10ea37c4808fa84063f06b02229801b28cc0.tar.gz
sqlite-ca3e10ea37c4808fa84063f06b02229801b28cc0.zip
Merge recent trunk enhancements, and in particular the improvements to
the b-tree balancing logic, into the sessions branch. FossilOrigin-Name: 28b044a51215a3f64dafb2cf3b6cb7d2029580ef
Diffstat (limited to 'src/where.c')
-rw-r--r--src/where.c199
1 files changed, 108 insertions, 91 deletions
diff --git a/src/where.c b/src/where.c
index bc0110779..feccf2d11 100644
--- a/src/where.c
+++ b/src/where.c
@@ -225,7 +225,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
}
pTerm = &pWC->a[idx = pWC->nTerm++];
if( p && ExprHasProperty(p, EP_Unlikely) ){
- pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
+ pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
}else{
pTerm->truthProb = 1;
}
@@ -756,6 +756,15 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
}
}
+/*
+** Mark term iChild as being a child of term iParent
+*/
+static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
+ pWC->a[iChild].iParent = iParent;
+ pWC->a[iChild].truthProb = pWC->a[iParent].truthProb;
+ pWC->a[iParent].nChild++;
+}
+
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
/*
** Analyze a term that consists of two or more OR-connected
@@ -1053,8 +1062,7 @@ static void exprAnalyzeOrTerm(
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
pTerm = &pWC->a[idxTerm];
- pWC->a[idxNew].iParent = idxTerm;
- pTerm->nChild = 1;
+ markTermAsChild(pWC, idxNew, idxTerm);
}else{
sqlite3ExprListDelete(db, pList);
}
@@ -1156,9 +1164,8 @@ static void exprAnalyze(
idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
if( idxNew==0 ) return;
pNew = &pWC->a[idxNew];
- pNew->iParent = idxTerm;
+ markTermAsChild(pWC, idxNew, idxTerm);
pTerm = &pWC->a[idxTerm];
- pTerm->nChild = 1;
pTerm->wtFlags |= TERM_COPIED;
if( pExpr->op==TK_EQ
&& !ExprHasProperty(pExpr, EP_FromJoin)
@@ -1215,9 +1222,8 @@ static void exprAnalyze(
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
pTerm = &pWC->a[idxTerm];
- pWC->a[idxNew].iParent = idxTerm;
+ markTermAsChild(pWC, idxNew, idxTerm);
}
- pTerm->nChild = 2;
}
#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */
@@ -1292,9 +1298,8 @@ static void exprAnalyze(
exprAnalyze(pSrc, pWC, idxNew2);
pTerm = &pWC->a[idxTerm];
if( isComplete ){
- pWC->a[idxNew1].iParent = idxTerm;
- pWC->a[idxNew2].iParent = idxTerm;
- pTerm->nChild = 2;
+ markTermAsChild(pWC, idxNew1, idxTerm);
+ markTermAsChild(pWC, idxNew2, idxTerm);
}
}
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
@@ -1327,9 +1332,8 @@ static void exprAnalyze(
pNewTerm->leftCursor = pLeft->iTable;
pNewTerm->u.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_MATCH;
- pNewTerm->iParent = idxTerm;
+ markTermAsChild(pWC, idxNew, idxTerm);
pTerm = &pWC->a[idxTerm];
- pTerm->nChild = 1;
pTerm->wtFlags |= TERM_COPIED;
pNewTerm->prereqAll = pTerm->prereqAll;
}
@@ -1350,7 +1354,7 @@ static void exprAnalyze(
if( pExpr->op==TK_NOTNULL
&& pExpr->pLeft->op==TK_COLUMN
&& pExpr->pLeft->iColumn>=0
- && OptimizationEnabled(db, SQLITE_Stat3)
+ && OptimizationEnabled(db, SQLITE_Stat34)
){
Expr *pNewExpr;
Expr *pLeft = pExpr->pLeft;
@@ -1369,9 +1373,8 @@ static void exprAnalyze(
pNewTerm->leftCursor = pLeft->iTable;
pNewTerm->u.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_GT;
- pNewTerm->iParent = idxTerm;
+ markTermAsChild(pWC, idxNew, idxTerm);
pTerm = &pWC->a[idxTerm];
- pTerm->nChild = 1;
pTerm->wtFlags |= TERM_COPIED;
pNewTerm->prereqAll = pTerm->prereqAll;
}
@@ -1591,6 +1594,8 @@ static void constructAutomaticIndex(
Bitmask idxCols; /* Bitmap of columns used for indexing */
Bitmask extraCols; /* Bitmap of additional columns */
u8 sentWarning = 0; /* True if a warnning has been issued */
+ Expr *pPartial = 0; /* Partial Index Expression */
+ int iContinue = 0; /* Jump here to skip excluded rows */
/* Generate code to skip over the creation and initialization of the
** transient index on 2nd and subsequent iterations of the loop. */
@@ -1606,6 +1611,12 @@ static void constructAutomaticIndex(
pLoop = pLevel->pWLoop;
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
+ if( pLoop->prereq==0
+ && (pTerm->wtFlags & TERM_VIRTUAL)==0
+ && sqlite3ExprIsTableConstant(pTerm->pExpr, pSrc->iCursor) ){
+ pPartial = sqlite3ExprAnd(pParse->db, pPartial,
+ sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
+ }
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
int iCol = pTerm->u.leftColumn;
Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
@@ -1618,7 +1629,9 @@ static void constructAutomaticIndex(
sentWarning = 1;
}
if( (idxCols & cMask)==0 ){
- if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ) return;
+ if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){
+ goto end_auto_index_create;
+ }
pLoop->aLTerm[nKeyCol++] = pTerm;
idxCols |= cMask;
}
@@ -1638,7 +1651,7 @@ static void constructAutomaticIndex(
** if they go out of sync.
*/
extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
- mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol;
+ mxBitCol = MIN(BMS-1,pTable->nCol);
testcase( pTable->nCol==BMS-1 );
testcase( pTable->nCol==BMS-2 );
for(i=0; i<mxBitCol; i++){
@@ -1647,11 +1660,10 @@ static void constructAutomaticIndex(
if( pSrc->colUsed & MASKBIT(BMS-1) ){
nKeyCol += pTable->nCol - BMS + 1;
}
- pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY;
/* Construct the Index object to describe this index */
pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed);
- if( pIdx==0 ) return;
+ if( pIdx==0 ) goto end_auto_index_create;
pLoop->u.btree.pIndex = pIdx;
pIdx->zName = "auto-index";
pIdx->pTable = pTable;
@@ -1703,18 +1715,29 @@ static void constructAutomaticIndex(
VdbeComment((v, "for %s", pTable->zName));
/* Fill the automatic index with content */
+ sqlite3ExprCachePush(pParse);
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
+ if( pPartial ){
+ iContinue = sqlite3VdbeMakeLabel(v);
+ sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL);
+ pLoop->wsFlags |= WHERE_PARTIALIDX;
+ }
regRecord = sqlite3GetTempReg(pParse);
sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
sqlite3VdbeJumpHere(v, addrTop);
sqlite3ReleaseTempReg(pParse, regRecord);
+ sqlite3ExprCachePop(pParse);
/* Jump here when skipping the initialization */
sqlite3VdbeJumpHere(v, addrInit);
+
+end_auto_index_create:
+ sqlite3ExprDelete(pParse->db, pPartial);
}
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
@@ -2159,7 +2182,6 @@ static int whereRangeScanEst(
if( p->nSample>0
&& nEq<p->nSampleCol
- && OptimizationEnabled(pParse->db, SQLITE_Stat3)
){
if( nEq==pBuilder->nRecValid ){
UnpackedRecord *pRec = pBuilder->pRec;
@@ -2198,7 +2220,7 @@ static int whereRangeScanEst(
/* Determine iLower and iUpper using ($P) only. */
if( nEq==0 ){
iLower = 0;
- iUpper = sqlite3LogEstToInt(p->aiRowLogEst[0]);
+ iUpper = p->nRowEst0;
}else{
/* Note: this call could be optimized away - since the same values must
** have been requested when testing key $P in whereEqualScanEst(). */
@@ -2273,12 +2295,15 @@ static int whereRangeScanEst(
nNew = whereRangeAdjust(pLower, nOut);
nNew = whereRangeAdjust(pUpper, nNew);
- /* TUNING: If there is both an upper and lower limit, assume the range is
+ /* TUNING: If there is both an upper and lower limit and neither limit
+ ** has an application-defined likelihood(), assume the range is
** reduced by an additional 75%. This means that, by default, an open-ended
** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the
** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to
** match 1/64 of the index. */
- if( pLower && pUpper ) nNew -= 20;
+ if( pLower && pLower->truthProb>0 && pUpper && pUpper->truthProb>0 ){
+ nNew -= 20;
+ }
nOut -= (pLower!=0) + (pUpper!=0);
if( nNew<10 ) nNew = 10;
@@ -2638,7 +2663,7 @@ static int codeAllEqualityTerms(
pLoop = pLevel->pWLoop;
assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
nEq = pLoop->u.btree.nEq;
- nSkip = pLoop->u.btree.nSkip;
+ nSkip = pLoop->nSkip;
pIdx = pLoop->u.btree.pIndex;
assert( pIdx!=0 );
@@ -2752,7 +2777,7 @@ static void explainAppendTerm(
static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop, Table *pTab){
Index *pIndex = pLoop->u.btree.pIndex;
u16 nEq = pLoop->u.btree.nEq;
- u16 nSkip = pLoop->u.btree.nSkip;
+ u16 nSkip = pLoop->nSkip;
int i, j;
Column *aCol = pTab->aCol;
i16 *aiColumn = pIndex->aiColumn;
@@ -2841,6 +2866,8 @@ static void explainOneScan(
if( isSearch ){
zFmt = "PRIMARY KEY";
}
+ }else if( flags & WHERE_PARTIALIDX ){
+ zFmt = "AUTOMATIC PARTIAL COVERING INDEX";
}else if( flags & WHERE_AUTO_INDEX ){
zFmt = "AUTOMATIC COVERING INDEX";
}else if( flags & WHERE_IDX_ONLY ){
@@ -3189,7 +3216,7 @@ static Bitmask codeOneLoopStart(
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
- assert( nEq>=pLoop->u.btree.nSkip );
+ assert( nEq>=pLoop->nSkip );
/* If this loop satisfies a sort order (pOrderBy) request that
** was passed to this function to implement a "SELECT min(x) ..."
@@ -3206,7 +3233,7 @@ static Bitmask codeOneLoopStart(
&& pWInfo->nOBSat>0
&& (pIdx->nKeyCol>nEq)
){
- assert( pLoop->u.btree.nSkip==0 );
+ assert( pLoop->nSkip==0 );
bSeekPastNull = 1;
nExtraReg = 1;
}
@@ -3827,7 +3854,7 @@ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
sqlite3_free(z);
}
if( p->wsFlags & WHERE_SKIPSCAN ){
- sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->u.btree.nSkip);
+ sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->nSkip);
}else{
sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm);
}
@@ -3956,12 +3983,15 @@ static int whereLoopCheaperProperSubset(
const WhereLoop *pY /* Compare against this WhereLoop */
){
int i, j;
- if( pX->nLTerm >= pY->nLTerm ) return 0; /* X is not a subset of Y */
+ if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){
+ return 0; /* X is not a subset of Y */
+ }
if( pX->rRun >= pY->rRun ){
if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */
if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */
}
for(i=pX->nLTerm-1; i>=0; i--){
+ if( pX->aLTerm[i]==0 ) continue;
for(j=pY->nLTerm-1; j>=0; j--){
if( pY->aLTerm[j]==pX->aLTerm[i] ) break;
}
@@ -3983,33 +4013,26 @@ static int whereLoopCheaperProperSubset(
** To say "WhereLoop X is a proper subset of Y" means that X uses fewer
** WHERE clause terms than Y and that every WHERE clause term used by X is
** also used by Y.
-**
-** This adjustment is omitted for SKIPSCAN loops. In a SKIPSCAN loop, the
-** WhereLoop.nLTerm field is not an accurate measure of the number of WHERE
-** clause terms covered, since some of the first nLTerm entries in aLTerm[]
-** will be NULL (because they are skipped). That makes it more difficult
-** to compare the loops. We could add extra code to do the comparison, and
-** perhaps we will someday. But SKIPSCAN is sufficiently uncommon, and this
-** adjustment is sufficient minor, that it is very difficult to construct
-** a test case where the extra code would improve the query plan. Better
-** to avoid the added complexity and just omit cost adjustments to SKIPSCAN
-** loops.
*/
static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return;
- if( (pTemplate->wsFlags & WHERE_SKIPSCAN)!=0 ) return;
for(; p; p=p->pNextLoop){
if( p->iTab!=pTemplate->iTab ) continue;
if( (p->wsFlags & WHERE_INDEXED)==0 ) continue;
- if( (p->wsFlags & WHERE_SKIPSCAN)!=0 ) continue;
if( whereLoopCheaperProperSubset(p, pTemplate) ){
/* Adjust pTemplate cost downward so that it is cheaper than its
- ** subset p */
+ ** subset p. Except, do not adjust the cost estimate downward for
+ ** a loop that skips more columns. */
+ if( pTemplate->nSkip>p->nSkip ) continue;
+ WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n",
+ pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut-1));
pTemplate->rRun = p->rRun;
pTemplate->nOut = p->nOut - 1;
}else if( whereLoopCheaperProperSubset(pTemplate, p) ){
/* Adjust pTemplate cost upward so that it is costlier than p since
** pTemplate is a proper subset of p */
+ WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n",
+ pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut+1));
pTemplate->rRun = p->rRun;
pTemplate->nOut = p->nOut + 1;
}
@@ -4295,7 +4318,7 @@ static int whereLoopAddBtreeIndex(
Bitmask saved_prereq; /* Original value of pNew->prereq */
u16 saved_nLTerm; /* Original value of pNew->nLTerm */
u16 saved_nEq; /* Original value of pNew->u.btree.nEq */
- u16 saved_nSkip; /* Original value of pNew->u.btree.nSkip */
+ u16 saved_nSkip; /* Original value of pNew->nSkip */
u32 saved_wsFlags; /* Original value of pNew->wsFlags */
LogEst saved_nOut; /* Original value of pNew->nOut */
int iCol; /* Index of the column in the table */
@@ -4324,7 +4347,7 @@ static int whereLoopAddBtreeIndex(
pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol,
opMask, pProbe);
saved_nEq = pNew->u.btree.nEq;
- saved_nSkip = pNew->u.btree.nSkip;
+ saved_nSkip = pNew->nSkip;
saved_nLTerm = pNew->nLTerm;
saved_wsFlags = pNew->wsFlags;
saved_prereq = pNew->prereq;
@@ -4332,44 +4355,6 @@ static int whereLoopAddBtreeIndex(
pNew->rSetup = 0;
rSize = pProbe->aiRowLogEst[0];
rLogSize = estLog(rSize);
-
- /* Consider using a skip-scan if there are no WHERE clause constraints
- ** available for the left-most terms of the index, and if the average
- ** number of repeats in the left-most terms is at least 18.
- **
- ** The magic number 18 is selected on the basis that scanning 17 rows
- ** is almost always quicker than an index seek (even though if the index
- ** contains fewer than 2^17 rows we assume otherwise in other parts of
- ** the code). And, even if it is not, it should not be too much slower.
- ** On the other hand, the extra seeks could end up being significantly
- ** more expensive. */
- assert( 42==sqlite3LogEst(18) );
- if( saved_nEq==saved_nSkip
- && saved_nEq+1<pProbe->nKeyCol
- && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */
- && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
- ){
- LogEst nIter;
- pNew->u.btree.nEq++;
- pNew->u.btree.nSkip++;
- pNew->aLTerm[pNew->nLTerm++] = 0;
- pNew->wsFlags |= WHERE_SKIPSCAN;
- nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1];
- if( pTerm ){
- /* TUNING: When estimating skip-scan for a term that is also indexable,
- ** multiply the cost of the skip-scan by 2.0, to make it a little less
- ** desirable than the regular index lookup. */
- nIter += 10; assert( 10==sqlite3LogEst(2) );
- }
- pNew->nOut -= nIter;
- /* TUNING: Because uncertainties in the estimates for skip-scan queries,
- ** add a 1.375 fudge factor to make skip-scan slightly less likely. */
- nIter += 5;
- whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul);
- pNew->nOut = saved_nOut;
- pNew->u.btree.nEq = saved_nEq;
- pNew->u.btree.nSkip = saved_nSkip;
- }
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
u16 eOp = pTerm->eOperator; /* Shorthand for pTerm->eOperator */
LogEst rCostIdx;
@@ -4464,7 +4449,6 @@ static int whereLoopAddBtreeIndex(
if( nInMul==0
&& pProbe->nSample
&& pNew->u.btree.nEq<=pProbe->nSampleCol
- && OptimizationEnabled(db, SQLITE_Stat3)
&& ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
){
Expr *pExpr = pTerm->pExpr;
@@ -4532,10 +4516,44 @@ static int whereLoopAddBtreeIndex(
}
pNew->prereq = saved_prereq;
pNew->u.btree.nEq = saved_nEq;
- pNew->u.btree.nSkip = saved_nSkip;
+ pNew->nSkip = saved_nSkip;
pNew->wsFlags = saved_wsFlags;
pNew->nOut = saved_nOut;
pNew->nLTerm = saved_nLTerm;
+
+ /* Consider using a skip-scan if there are no WHERE clause constraints
+ ** available for the left-most terms of the index, and if the average
+ ** number of repeats in the left-most terms is at least 18.
+ **
+ ** The magic number 18 is selected on the basis that scanning 17 rows
+ ** is almost always quicker than an index seek (even though if the index
+ ** contains fewer than 2^17 rows we assume otherwise in other parts of
+ ** the code). And, even if it is not, it should not be too much slower.
+ ** On the other hand, the extra seeks could end up being significantly
+ ** more expensive. */
+ assert( 42==sqlite3LogEst(18) );
+ if( saved_nEq==saved_nSkip
+ && saved_nEq+1<pProbe->nKeyCol
+ && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */
+ && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
+ ){
+ LogEst nIter;
+ pNew->u.btree.nEq++;
+ pNew->nSkip++;
+ pNew->aLTerm[pNew->nLTerm++] = 0;
+ pNew->wsFlags |= WHERE_SKIPSCAN;
+ nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1];
+ pNew->nOut -= nIter;
+ /* TUNING: Because uncertainties in the estimates for skip-scan queries,
+ ** add a 1.375 fudge factor to make skip-scan slightly less likely. */
+ nIter += 5;
+ whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul);
+ pNew->nOut = saved_nOut;
+ pNew->u.btree.nEq = saved_nEq;
+ pNew->nSkip = saved_nSkip;
+ pNew->wsFlags = saved_wsFlags;
+ }
+
return rc;
}
@@ -4714,7 +4732,7 @@ static int whereLoopAddBtree(
if( pTerm->prereqRight & pNew->maskSelf ) continue;
if( termCanDriveIndex(pTerm, pSrc, 0) ){
pNew->u.btree.nEq = 1;
- pNew->u.btree.nSkip = 0;
+ pNew->nSkip = 0;
pNew->u.btree.pIndex = 0;
pNew->nLTerm = 1;
pNew->aLTerm[0] = pTerm;
@@ -4755,7 +4773,7 @@ static int whereLoopAddBtree(
}
rSize = pProbe->aiRowLogEst[0];
pNew->u.btree.nEq = 0;
- pNew->u.btree.nSkip = 0;
+ pNew->nSkip = 0;
pNew->nLTerm = 0;
pNew->iSortIdx = 0;
pNew->rSetup = 0;
@@ -5305,7 +5323,7 @@ static i8 wherePathSatisfiesOrderBy(
/* Skip over == and IS NULL terms */
if( j<pLoop->u.btree.nEq
- && pLoop->u.btree.nSkip==0
+ && pLoop->nSkip==0
&& ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0
){
if( i & WO_ISNULL ){
@@ -5759,7 +5777,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
}
#ifdef WHERETRACE_ENABLED /* >=2 */
- if( sqlite3WhereTrace>=2 ){
+ if( sqlite3WhereTrace & 0x02 ){
sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
@@ -5878,7 +5896,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
pWC = &pWInfo->sWC;
pLoop = pBuilder->pNew;
pLoop->wsFlags = 0;
- pLoop->u.btree.nSkip = 0;
+ pLoop->nSkip = 0;
pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0);
if( pTerm ){
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
@@ -5890,7 +5908,6 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
}else{
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pLoop->aLTermSpace==pLoop->aLTerm );
- assert( ArraySize(pLoop->aLTermSpace)==4 );
if( !IsUniqueIndex(pIdx)
|| pIdx->pPartIdxWhere!=0
|| pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace)