-C Ensure\sthat\sthe\ssqlite3_scrub_backup()\sextension\screates\sa\sbackup\sdatabase\sat\sleast\sas\slarge\sas\sindicated\sby\sthe\sdatabase\sheader,\seven\sif\sthe\slast\spage\sof\sthe\sinput\sdatabase\sis\sa\sfree-list\sleaf.
-D 2016-07-26T10:46:21.988
+C When\sestimating\sthe\scost\sof\san\sindex\sscan,\sfactor\sin\sthe\scost\ssavings\sof\nbeing\sable\sto\suse\sthe\sindex\sto\sevaluate\ssome\sWHERE\sclause\sterms\swithout\nhaving\sto\sdo\sa\stable\slookup.
+D 2016-07-27T18:27:02.556
F Makefile.in 6c20d44f72d4564f11652b26291a214c8367e5db
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a
F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39
F src/dbstat.c 4f6f7f52b49beb9636ffbd517cfe44a402ba4ad0
F src/delete.c 4aba4214a377ce8ddde2d2e609777bcc8235200f
-F src/expr.c 21b153e1046c624e9387a17d3261f69b461e700c
+F src/expr.c 3347e66d4e27ec5f3ec7573b9a5f899bbd7d1df8
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c bc4145347595b7770f9a598cff1c848302cf5413
F src/func.c 61a4114cf7004f10c542cfabbab9f2bcb9033045
F src/sqlite.h.in c6e68a4a47610631822a4f8f83a44c9f75339331
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 46f300b6e300e0fa916d7d58c44b53415b8471a9
-F src/sqliteInt.h 49081ceab08eda9943d555aee57392c5b35d1c60
+F src/sqliteInt.h d25c18c1272a7811e2569c39bfc2fca96156eead
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c 5b18f9526900f61189ab0b83f1ef41d9f871a2ab
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
F src/wal.c 02eeecc265f6ffd0597378f5d8ae9070b62a406a
F src/wal.h 6dd221ed384afdc204bc61e25c23ef7fd5a511f2
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
-F src/where.c 48eed8ebe319c6cbc7bf7682018f32af0f5189f5
+F src/where.c 7e4d676b5ac4434e5f93606a744d396dc40d9977
F src/whereInt.h e5b939701a7ceffc5a3a8188a37f9746416ebcd0
F src/wherecode.c 99707d11907c71d289ee9553d2d1a22f1fd8ba41
F src/whereexpr.c d7dcbf14ce1b5876c1f76496162c30fcba669563
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P c0e7d98ef2a13ede5ae865083ede1aaffdf43310
-R 783c6677056c1c6297ef166e24fadbce
-U dan
-Z 42a389186c57610d077ea553714cade1
+P 483994a54dee3c7a3801e0e9d3c96fa9dbd8d2fd
+R 9e4bd013f5c2cf2171d472668aed0d1c
+T *branch * improved-index-scan
+T *sym-improved-index-scan *
+T -sym-trunk *
+U drh
+Z 8f3398744130761f466da0e8b7212fe4
-483994a54dee3c7a3801e0e9d3c96fa9dbd8d2fd
\ No newline at end of file
+a59b5622f7cc6e502d71aabc12c053582cd03609
\ No newline at end of file
return 0;
}
+/*
+** An instance of the following structure is used by the tree walker
+** to determine if an expression can be evaluated by reference to the
+** index only, without having to do a search for the corresponding
+** table entry. The IdxCover.pIdx field is the index. IdxCover.iCur
+** is the cursor for the table.
+*/
+struct IdxCover {
+ Index *pIdx; /* The index to be tested for coverage */
+ int iCur; /* Cursor number for the table corresponding to the index */
+};
+
+/*
+** Check to see if there are references to columns in table
+** pWalker->u.pIdxCover->iCur can be satisfied using the index
+** pWalker->u.pIdxCover->pIdx.
+*/
+static int exprIdxCover(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_COLUMN
+ && pExpr->iTable==pWalker->u.pIdxCover->iCur
+ && sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
+ ){
+ pWalker->eCode = 1;
+ return WRC_Abort;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Determine if an index on table iCur that contains the columns in
+** Bitmask m will cover the expression pExpr. Return true if the index
+** does cover the expression and false if the expression references
+** table columns that are not found in the index.
+**
+** An index covering an expression means that the expression can be
+** evaluated using only the index and without having to lookup the
+** corresponding table entry.
+*/
+int sqlite3ExprCoveredByIndex(
+ Expr *pExpr, /* The index to be tested */
+ int iCur, /* The cursor number for the corresponding table */
+ Index *pIdx /* The index that might be used for coverage */
+){
+ Walker w;
+ struct IdxCover xcov;
+ memset(&w, 0, sizeof(w));
+ xcov.iCur = iCur;
+ xcov.pIdx = pIdx;
+ w.xExprCallback = exprIdxCover;
+ w.u.pIdxCover = &xcov;
+ sqlite3WalkExpr(&w, pExpr);
+ return !w.eCode;
+}
+
+
/*
** An instance of the following structure is used by the tree walker
** to count references to table columns in the arguments of an
struct SrcCount *pSrcCount; /* Counting column references */
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
int *aiCol; /* array of column indexes */
+ struct IdxCover *pIdxCover; /* Check for index coverage */
} u;
};
int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
+int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
Vdbe *sqlite3GetVdbe(Parse*);
#ifndef SQLITE_OMIT_BUILTIN_TEST
/* The cost of visiting the index rows is N*K, where K is
** between 1.1 and 3.0, depending on the relative sizes of the
- ** index and table rows. If this is a non-covering index scan,
- ** also add the cost of visiting table rows (N*3.0). */
+ ** index and table rows. */
pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
if( m!=0 ){
- pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
+ /* If this is a non-covering index scan, add in the cost of
+ ** doing table lookups. The cost will be 3x the number of
+ ** lookups. Take into account WHERE clause terms that can be
+ ** satisfied using just the index, and that do not require a
+ ** table lookup. */
+ LogEst nLookup = rSize + 16; /* Base cost: N*3 */
+ int ii;
+ int iCur = pSrc->iCursor;
+ WhereClause *pWC = &pWInfo->sWC;
+ for(ii=0; ii<pWC->nTerm; ii++){
+ WhereTerm *pTerm = &pWC->a[ii];
+ if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){
+ break;
+ }
+ /* pTerm can be evaluated using just the index. So reduce
+ ** the expected number of table lookups accordingly */
+ if( pTerm->truthProb<=0 ){
+ nLookup += pTerm->truthProb;
+ }else{
+ nLookup--;
+ if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19;
+ }
+ }
+
+ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup);
}
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);