-C Factor\sout\scommon\soperations\sinto\swhereLoopAddAll().\s\sAdd\sstubs\sfor\nmissing\sfeatures.
-D 2013-05-10T03:30:49.076
+C Update\sthe\sNGQP\sso\sthat\sit\scan\sproduce\splans\sthat\sinclude\sautomatic\sindices.
+D 2013-05-10T15:16:30.669
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in ce81671efd6223d19d4c8c6b88ac2c4134427111
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
-F src/where.c 31160bacc36e1fa5818caf091d5559d55eae7a5d
+F src/where.c f96b2602fd2da89873ed5a210608c58bf80d7c0e
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P 5ed31c8279a4f465b982df5dc20cefc286928b93
-R 6a6b39040b040f90ce4281cc062a3caa
+P 0278e420614e02fb2d8474ed99b0904275882dfe
+R 69dec67361636bd352a6f82f3ef9f1cb
U drh
-Z ca90367b6425b581381608ce8a76b4fa
+Z ef95f556fc74affef6b6df28ead69ff3
SrcList *pTabList; /* FROM clause */
ExprList *pOrderBy; /* ORDER BY clause */
WhereLoop *pNew; /* Template WhereLoop */
+ int mxTerm; /* Maximum number of aTerm[] entries on pNew */
};
/*
WhereLoop savedLoop; /* Saved original content of pNew[] */
int iCol; /* Index of the column in the table */
int rc = SQLITE_OK; /* Return code */
+ double rLogSize; /* Logarithm of table size */
db = pBuilder->db;
pNew = pBuilder->pNew;
opMask, iCol>=0 ? pProbe : 0);
savedLoop = *pNew;
pNew->rSetup = (double)0;
+ rLogSize = estLog(pProbe->aiRowEst[0]);
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
int nIn = 1;
pNew->u.btree.nEq = savedLoop.u.btree.nEq;
pNew->nTerm = savedLoop.nTerm;
+ if( pNew->nTerm>=pBuilder->mxTerm ) break; /* Repeated column in index */
pNew->aTerm[pNew->nTerm++] = pTerm;
pNew->prereq = (savedLoop.prereq | pTerm->prereqRight) & ~pNew->maskSelf;
if( pTerm->eOperator & WO_IN ){
pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
pNew->nOut = savedLoop.nOut/3;
}
- pNew->rRun = pNew->nOut + estLog(pProbe->aiRowEst[0])*nIn;
+ pNew->rRun = rLogSize*nIn; /* Cost for nIn binary searches */
+ if( pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK) ){
+ pNew->rRun += pNew->nOut; /* Unit step cost to reach each row */
+ }else{
+ /* Each row involves a step of the index, then a binary search of
+ ** the main table */
+ pNew->rRun += pNew->nOut*(1 + rLogSize);
+ }
+ /* TBD: Adjust nOut and rRun for STAT3 range values */
+ /* TBD: Adjust nOut for additional constraints */
rc = whereLoopInsert(pBuilder->pWInfo, pNew);
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<pProbe->nColumn
struct SrcList_item *pSrc; /* The FROM clause btree term to add */
WhereLoop *pNew; /* Template WhereLoop object */
int rc = SQLITE_OK; /* Return code */
+ double rSize; /* number of rows in the table */
+ double rLogSize; /* Logarithm of the number of rows in the table */
pNew = pBuilder->pNew;
pSrc = pBuilder->pTabList->a + pNew->iTab;
}
pProbe = &sPk;
}
+ rSize = (double)pSrc->pTab->nRowEst;
+ rLogSize = estLog(rSize);
+
+ /* Automatic indexes */
+ if( (pBuilder->pParse->db->flags & SQLITE_AutoIndex)!=0
+ && !pSrc->viaCoroutine
+ && !pSrc->notIndexed
+ && !pSrc->isCorrelated
+ ){
+ /* Generate auto-index WhereLoops */
+ WhereClause *pWC = pBuilder->pWC;
+ WhereTerm *pTerm;
+ WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
+ for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
+ if( termCanDriveIndex(pTerm, pSrc, 0) ){
+ pNew->u.btree.nEq = 1;
+ pNew->nTerm = 1;
+ pNew->aTerm[0] = pTerm;
+ pNew->rSetup = 2*rLogSize*pSrc->pTab->nRowEst;
+ pNew->nOut = (double)10;
+ pNew->rRun = rLogSize + pNew->nOut;
+ pNew->wsFlags = WHERE_TEMP_INDEX;
+ pNew->prereq = mExtra | pTerm->prereqRight;
+ rc = whereLoopInsert(pBuilder->pWInfo, pNew);
+ }
+ }
+ }
/* Insert a full table scan */
pNew->u.btree.nEq = 0;
pNew->prereq = mExtra;
pNew->u.btree.pIndex = 0;
pNew->wsFlags = 0;
- pNew->rRun = (double)pSrc->pTab->nRowEst;
- pNew->nOut = (double)pSrc->pTab->nRowEst;
+ pNew->nOut = rSize;
+ pNew->rRun = rSize + rLogSize;
+ /* TBD: Reduce nOut using constraints */
rc = whereLoopInsert(pBuilder->pWInfo, pNew);
- /* TBD: Insert automatic index opportunities */
-
/* Loop over all indices
*/
for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext){
if( rc ) goto whereLoopAddVtab_exit;
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
pNew->prereq = 0;
+ assert( pIdxInfo->nConstraint<=pBuilder->mxTerm );
for(i=0; i<pIdxInfo->nConstraint; i++) pNew->aTerm[i] = 0;
mxTerm = -1;
for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
/* Loop over the tables in the join, from left to right */
pBuilder->pNew = pNew = sqlite3DbMallocZero(db, sizeof(WhereLoop));
if( pNew==0 ) return SQLITE_NOMEM;
- pNew->aTerm = sqlite3DbMallocZero(db, (pWC->nTerm+1)*sizeof(pNew->aTerm[0]));
+ pBuilder->mxTerm = pWC->nTerm+1;
+ while( pWC->pOuter ){
+ pWC = pWC->pOuter;
+ pBuilder->mxTerm += pWC->nTerm;
+ }
+ pWC = pBuilder->pWC;
+ pNew->aTerm = sqlite3DbMallocZero(db,pBuilder->mxTerm*sizeof(pNew->aTerm[0]));
if( pNew->aTerm==0 ){
rc = SQLITE_NOMEM;
goto whereLoopAddAll_end;
pWInfo->a[0].plan.wsFlags &= ~WHERE_IDX_ONLY;
}
+#if 0
+ /* Scaffolding: Check the new query plan against the old. Report any
+ ** discrepencies */
+ for(ii=0; ii<nTabList; ii++){
+ if( pWInfo->a[ii].iFrom!=pWInfo->a[ii].pWLoop->iTab ){
+ sqlite3DebugPrintf("(QP-Mismatch)");
+ break;
+ }
+ }
+#endif
+
/* Open all tables in the pTabList and any indices selected for
** searching those tables.
*/