From: drh Date: Fri, 10 May 2013 20:26:22 +0000 (+0000) Subject: Now generating OR-clause plans. X-Git-Tag: version-3.8.0~130^2~79 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf8fa7a65b5562d92c19cb4267cbd4ed9989a2b6;p=thirdparty%2Fsqlite.git Now generating OR-clause plans. FossilOrigin-Name: e17003fcfec0c0b524b1b9ff8e15e7ee83efa571 --- diff --git a/manifest b/manifest index 180d5b5b51..5d695c8a7f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\sNGQP\sso\sthat\sit\scan\sproduce\splans\sthat\sinclude\sautomatic\sindices. -D 2013-05-10T15:16:30.669 +C Now\sgenerating\sOR-clause\splans. +D 2013-05-10T20:26:22.071 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in ce81671efd6223d19d4c8c6b88ac2c4134427111 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -264,7 +264,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 f96b2602fd2da89873ed5a210608c58bf80d7c0e +F src/where.c 374f50ced988b23addabd3c351f1c18d8652d394 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1062,7 +1062,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 0278e420614e02fb2d8474ed99b0904275882dfe -R 69dec67361636bd352a6f82f3ef9f1cb +P 586b55d8d7722de1c0530b3b832bae0511e6d05c +R a9f14f7930497f93900a124a55885f20 U drh -Z ef95f556fc74affef6b6df28ead69ff3 +Z 9615c6567bc86000a51d8e76292d6ef0 diff --git a/manifest.uuid b/manifest.uuid index 0143fae8fc..250be95162 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -586b55d8d7722de1c0530b3b832bae0511e6d05c \ No newline at end of file +e17003fcfec0c0b524b1b9ff8e15e7ee83efa571 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 40653d7c51..fdadc3e738 100644 --- a/src/where.c +++ b/src/where.c @@ -289,6 +289,7 @@ struct WhereLoopBuilder { 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 */ }; @@ -5162,10 +5163,27 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ ** fewer dependencies than the template. Otherwise a new WhereLoop is ** 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; 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 ** priority over pTemplate. @@ -5210,11 +5228,13 @@ static int whereLoopInsert(WhereInfo *pWInfo, WhereLoop *pTemplate){ p->pNextLoop = pNext; *ppPrev = p; p->aTerm = paTerm; - if( pTemplate->nTerm ){ - memcpy(p->aTerm, pTemplate->aTerm, pTemplate->nTerm*sizeof(p->aTerm[0])); + if( p->nTerm ){ + memcpy(p->aTerm, pTemplate->aTerm, p->nTerm*sizeof(p->aTerm[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{ pTemplate->u.vtab.needFree = 0; } @@ -5305,7 +5325,7 @@ static int whereLoopAddBtreeIndex( } /* TBD: Adjust nOut and rRun for STAT3 range values */ /* TBD: Adjust nOut for additional constraints */ - rc = whereLoopInsert(pBuilder->pWInfo, pNew); + rc = whereLoopInsert(pBuilder, pNew); if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 && pNew->u.btree.nEqnColumn ){ @@ -5366,7 +5386,8 @@ static int whereLoopAddBtree( rLogSize = estLog(rSize); /* Automatic indexes */ - if( (pBuilder->pParse->db->flags & SQLITE_AutoIndex)!=0 + if( !pBuilder->pBest + && (pBuilder->pParse->db->flags & SQLITE_AutoIndex)!=0 && !pSrc->viaCoroutine && !pSrc->notIndexed && !pSrc->isCorrelated @@ -5385,7 +5406,7 @@ static int whereLoopAddBtree( pNew->rRun = rLogSize + pNew->nOut; pNew->wsFlags = WHERE_TEMP_INDEX; 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->rRun = rSize + rLogSize; /* TBD: Reduce nOut using constraints */ - rc = whereLoopInsert(pBuilder->pWInfo, pNew); + rc = whereLoopInsert(pBuilder, pNew); /* Loop over all indices */ @@ -5565,7 +5586,7 @@ static int whereLoopAddVirtual( pNew->rSetup = (double)0; pNew->rRun = pIdxInfo->estimatedCost; pNew->nOut = (double)25; - whereLoopInsert(pBuilder->pWInfo, pNew); + whereLoopInsert(pBuilder, pNew); if( pNew->u.vtab.needFree ){ sqlite3_free(pNew->u.vtab.idxStr); pNew->u.vtab.needFree = 0; @@ -5579,6 +5600,84 @@ whereLoopAddVtab_exit: 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; pTermeOperator & 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; pOrTermeOperator& 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 */ @@ -5619,11 +5718,9 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ }else{ rc = whereLoopAddBtree(pBuilder, mExtra); } -#if 0 if( rc==SQLITE_OK ){ rc = whereLoopAddOr(pBuilder, mExtra); } -#endif mPrior |= pNew->maskSelf; if( rc || db->mallocFailed ) break; }