1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-21 09:00:59 +03:00

Now generating OR-clause plans.

FossilOrigin-Name: e17003fcfec0c0b524b1b9ff8e15e7ee83efa571
This commit is contained in:
drh
2013-05-10 20:26:22 +00:00
parent eb04de3224
commit cf8fa7a65b
3 changed files with 116 additions and 19 deletions

View File

@@ -1,5 +1,5 @@
C Update\sthe\sNGQP\sso\sthat\sit\scan\sproduce\splans\sthat\sinclude\sautomatic\sindices. C Now\sgenerating\sOR-clause\splans.
D 2013-05-10T15:16:30.669 D 2013-05-10T20:26:22.071
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in ce81671efd6223d19d4c8c6b88ac2c4134427111 F Makefile.in ce81671efd6223d19d4c8c6b88ac2c4134427111
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -264,7 +264,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
F src/where.c f96b2602fd2da89873ed5a210608c58bf80d7c0e F src/where.c 374f50ced988b23addabd3c351f1c18d8652d394
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -1062,7 +1062,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
P 0278e420614e02fb2d8474ed99b0904275882dfe P 586b55d8d7722de1c0530b3b832bae0511e6d05c
R 69dec67361636bd352a6f82f3ef9f1cb R a9f14f7930497f93900a124a55885f20
U drh U drh
Z ef95f556fc74affef6b6df28ead69ff3 Z 9615c6567bc86000a51d8e76292d6ef0

View File

@@ -1 +1 @@
586b55d8d7722de1c0530b3b832bae0511e6d05c e17003fcfec0c0b524b1b9ff8e15e7ee83efa571

View File

@@ -289,6 +289,7 @@ struct WhereLoopBuilder {
SrcList *pTabList; /* FROM clause */ SrcList *pTabList; /* FROM clause */
ExprList *pOrderBy; /* ORDER BY clause */ ExprList *pOrderBy; /* ORDER BY clause */
WhereLoop *pNew; /* Template WhereLoop */ WhereLoop *pNew; /* Template WhereLoop */
WhereLoop *pBest; /* If non-NULL, store single best loop here */
int mxTerm; /* Maximum number of aTerm[] entries on pNew */ int mxTerm; /* Maximum number of aTerm[] entries on pNew */
}; };
@@ -5162,10 +5163,27 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
** fewer dependencies than the template. Otherwise a new WhereLoop is ** fewer dependencies than the template. Otherwise a new WhereLoop is
** added based no the template. ** added based no the template.
*/ */
static int whereLoopInsert(WhereInfo *pWInfo, WhereLoop *pTemplate){ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
WhereLoop **ppPrev, *p, *pNext = 0, *pToFree = 0; WhereLoop **ppPrev, *p, *pNext = 0, *pToFree = 0;
WhereTerm **paTerm = 0; WhereTerm **paTerm = 0;
sqlite3 *db = pWInfo->pParse->db; sqlite3 *db = pBuilder->db;
WhereInfo *pWInfo = pBuilder->pWInfo;
if( (p = pBuilder->pBest)!=0 ){
if( p->maskSelf!=0 ){
if( p->rRun+p->rSetup < pTemplate->rRun+pTemplate->rSetup ){
return SQLITE_OK;
}
if( p->rRun+p->rSetup == pTemplate->rRun+pTemplate->rSetup
&& p->prereq <= pTemplate->prereq ){
return SQLITE_OK;
}
}
*p = *pTemplate;
p->aTerm = 0;
p->u.vtab.needFree = 0;
return SQLITE_OK;
}
/* Search for an existing WhereLoop to overwrite, or which takes /* Search for an existing WhereLoop to overwrite, or which takes
** priority over pTemplate. ** priority over pTemplate.
@@ -5210,11 +5228,13 @@ static int whereLoopInsert(WhereInfo *pWInfo, WhereLoop *pTemplate){
p->pNextLoop = pNext; p->pNextLoop = pNext;
*ppPrev = p; *ppPrev = p;
p->aTerm = paTerm; p->aTerm = paTerm;
if( pTemplate->nTerm ){ if( p->nTerm ){
memcpy(p->aTerm, pTemplate->aTerm, pTemplate->nTerm*sizeof(p->aTerm[0])); memcpy(p->aTerm, pTemplate->aTerm, p->nTerm*sizeof(p->aTerm[0]));
} }
if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
if( p->u.btree.pIndex && p->u.btree.pIndex->tnum==0 ) p->u.btree.pIndex = 0; if( p->u.btree.pIndex && p->u.btree.pIndex->tnum==0 ){
p->u.btree.pIndex = 0;
}
}else{ }else{
pTemplate->u.vtab.needFree = 0; pTemplate->u.vtab.needFree = 0;
} }
@@ -5305,7 +5325,7 @@ static int whereLoopAddBtreeIndex(
} }
/* TBD: Adjust nOut and rRun for STAT3 range values */ /* TBD: Adjust nOut and rRun for STAT3 range values */
/* TBD: Adjust nOut for additional constraints */ /* TBD: Adjust nOut for additional constraints */
rc = whereLoopInsert(pBuilder->pWInfo, pNew); rc = whereLoopInsert(pBuilder, pNew);
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<pProbe->nColumn && pNew->u.btree.nEq<pProbe->nColumn
){ ){
@@ -5366,7 +5386,8 @@ static int whereLoopAddBtree(
rLogSize = estLog(rSize); rLogSize = estLog(rSize);
/* Automatic indexes */ /* Automatic indexes */
if( (pBuilder->pParse->db->flags & SQLITE_AutoIndex)!=0 if( !pBuilder->pBest
&& (pBuilder->pParse->db->flags & SQLITE_AutoIndex)!=0
&& !pSrc->viaCoroutine && !pSrc->viaCoroutine
&& !pSrc->notIndexed && !pSrc->notIndexed
&& !pSrc->isCorrelated && !pSrc->isCorrelated
@@ -5385,7 +5406,7 @@ static int whereLoopAddBtree(
pNew->rRun = rLogSize + pNew->nOut; pNew->rRun = rLogSize + pNew->nOut;
pNew->wsFlags = WHERE_TEMP_INDEX; pNew->wsFlags = WHERE_TEMP_INDEX;
pNew->prereq = mExtra | pTerm->prereqRight; pNew->prereq = mExtra | pTerm->prereqRight;
rc = whereLoopInsert(pBuilder->pWInfo, pNew); rc = whereLoopInsert(pBuilder, pNew);
} }
} }
} }
@@ -5400,7 +5421,7 @@ static int whereLoopAddBtree(
pNew->nOut = rSize; pNew->nOut = rSize;
pNew->rRun = rSize + rLogSize; pNew->rRun = rSize + rLogSize;
/* TBD: Reduce nOut using constraints */ /* TBD: Reduce nOut using constraints */
rc = whereLoopInsert(pBuilder->pWInfo, pNew); rc = whereLoopInsert(pBuilder, pNew);
/* Loop over all indices /* Loop over all indices
*/ */
@@ -5565,7 +5586,7 @@ static int whereLoopAddVirtual(
pNew->rSetup = (double)0; pNew->rSetup = (double)0;
pNew->rRun = pIdxInfo->estimatedCost; pNew->rRun = pIdxInfo->estimatedCost;
pNew->nOut = (double)25; pNew->nOut = (double)25;
whereLoopInsert(pBuilder->pWInfo, pNew); whereLoopInsert(pBuilder, pNew);
if( pNew->u.vtab.needFree ){ if( pNew->u.vtab.needFree ){
sqlite3_free(pNew->u.vtab.idxStr); sqlite3_free(pNew->u.vtab.idxStr);
pNew->u.vtab.needFree = 0; pNew->u.vtab.needFree = 0;
@@ -5579,6 +5600,84 @@ whereLoopAddVtab_exit:
return rc; return rc;
} }
/*
** Add WhereLoop entries to handle OR terms. This works for either
** btrees or virtual tables.
*/
static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
WhereClause *pWC;
WhereLoop *pNew;
WhereTerm *pTerm, *pWCEnd;
int rc = SQLITE_OK;
int iCur;
WhereClause tempWC;
WhereLoopBuilder sSubBuild;
WhereLoop sBest;
struct SrcList_item *pItem;
pWC = pBuilder->pWC;
if( pWC->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
pWCEnd = pWC->a + pWC->nTerm;
pNew = pBuilder->pNew;
pItem = pBuilder->pTabList->a + pNew->iTab;
iCur = pItem->iCursor;
sSubBuild = *pBuilder;
sSubBuild.pOrderBy = 0;
sSubBuild.pBest = &sBest;
tempWC.pParse = pWC->pParse;
tempWC.pMaskSet = pWC->pMaskSet;
tempWC.pOuter = pWC;
tempWC.op = TK_AND;
tempWC.wctrlFlags = 0;
tempWC.nTerm = 1;
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
if( (pTerm->eOperator & WO_OR)!=0
&& (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
){
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
WhereTerm *pOrTerm;
double rTotal = 0;
double nRow = 0;
Bitmask prereq = mExtra;
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
if( (pOrTerm->eOperator& WO_AND)!=0 ){
sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
}else if( pOrTerm->leftCursor==iCur ){
tempWC.a = pOrTerm;
sSubBuild.pWC = &tempWC;
}else{
continue;
}
sBest.maskSelf = 0;
if( IsVirtual(pItem->pTab) ){
rc = whereLoopAddVirtual(&sSubBuild, mExtra);
}else{
rc = whereLoopAddBtree(&sSubBuild, mExtra);
}
if( sBest.maskSelf==0 ) break;
assert( sBest.rSetup==(double)0 );
rTotal += sBest.rRun;
nRow += sBest.nOut;
prereq |= sBest.prereq;
}
pNew->nTerm = 1;
pNew->aTerm[0] = pTerm;
pNew->wsFlags = WHERE_MULTI_OR;
pNew->rSetup = (double)0;
pNew->rRun = rTotal;
pNew->nOut = nRow;
pNew->prereq = prereq;
rc = whereLoopInsert(pBuilder, pNew);
}
}
return rc;
}
/* /*
** Add all WhereLoop objects for all tables ** Add all WhereLoop objects for all tables
*/ */
@@ -5619,11 +5718,9 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
}else{ }else{
rc = whereLoopAddBtree(pBuilder, mExtra); rc = whereLoopAddBtree(pBuilder, mExtra);
} }
#if 0
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = whereLoopAddOr(pBuilder, mExtra); rc = whereLoopAddOr(pBuilder, mExtra);
} }
#endif
mPrior |= pNew->maskSelf; mPrior |= pNew->maskSelf;
if( rc || db->mallocFailed ) break; if( rc || db->mallocFailed ) break;
} }