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

Activate the one-pass optimization. Update comments, especially the

descriptions of the various objects.

FossilOrigin-Name: e120c558a5bafc0f0d2cc12ee5c9d36e20cc642d
This commit is contained in:
drh
2013-06-12 20:18:16 +00:00
parent 95ed68df55
commit 3b48e8c91a
3 changed files with 105 additions and 87 deletions

View File

@@ -1,5 +1,5 @@
C Bug\sfixes\sin\sthe\shandling\sof\svirtual\stables. C Activate\sthe\sone-pass\soptimization.\s\sUpdate\scomments,\sespecially\sthe\ndescriptions\sof\sthe\svarious\sobjects.
D 2013-06-12T17:55:50.456 D 2013-06-12T20:18:16.225
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -289,7 +289,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 568aef7548e2cad24f03b6099f07aa66b2fa269c F src/where.c 4209851115ec883e004f0e0ec496215c9df10e33
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
@@ -1095,7 +1095,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/wherecosttest.c 4d0393bdbe7230adb712e925863744dd2b7ffc5b F tool/wherecosttest.c 4d0393bdbe7230adb712e925863744dd2b7ffc5b
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
P f2e15b1974e55373b5819e3b2326653f890f409f P 25c0f7292a20c0db6ef176966d9987f29c7d73e5
R 6fa5c9c088caf080e0b4a5ec6cf7a456 R abdb63c5ef041b9c2f729e7a4c7abdae
U drh U drh
Z 738850606e13a26064a82bd0faf55587 Z 9e2bd249132b4bdcba34d19dbfd465f2

View File

@@ -1 +1 @@
25c0f7292a20c0db6ef176966d9987f29c7d73e5 e120c558a5bafc0f0d2cc12ee5c9d36e20cc642d

View File

@@ -27,10 +27,10 @@
#endif #endif
#if defined(SQLITE_DEBUG) \ #if defined(SQLITE_DEBUG) \
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
# define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X # define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
# define WHERETRACE_ENABLED 1 # define WHERETRACE_ENABLED 1
#else #else
# define WHERETRACE(X) # define WHERETRACE(K,X)
#endif #endif
/* Forward reference /* Forward reference
@@ -48,23 +48,32 @@ typedef struct WhereScan WhereScan;
/* /*
** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
** maximum cost is 64*(2**63) which becomes 6900. So all costs can be ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
** be stored in a 16-bit unsigned integer without risk of overflow. ** (Virtual tables can return a larger cost, but let's assume they do not.)
** So all costs can be stored in a 16-bit unsigned integer without risk
** of overflow.
**
** Costs are estimates, so don't go to the computational trouble to compute
** 10*log2(X) exactly. Instead, a close estimate is used. Any value of
** X<=1 is stored as 0. X=2 is 10. X=3 is 16. X=1000 is 99. etc.
**
*/ */
typedef unsigned short int WhereCost; typedef unsigned short int WhereCost;
/* /*
** For each nested loop in a WHERE clause implementation, the WhereInfo ** This object contains information needed to implement a single nestd
** structure contains a single instance of this structure. This structure ** loop in WHERE clause.
** is intended to be private to the where.c module and should not be
** access or modified by other modules.
** **
** The pIdxInfo field is used to help pick the best index on a ** Contrast this object with WhereLoop. This object describes the
** virtual table. The pIdxInfo pointer contains indexing ** implementation of the loop. WhereLoop describes the algorithm.
** information for the i-th table in the FROM clause before reordering. ** This object contains a pointer to the WhereLoop algorithm as one of
** All the pIdxInfo pointers are freed by whereInfoFree() in where.c. ** its elements.
** All other information in the i-th WhereLevel object for the i-th table **
** after FROM clause ordering. ** The WhereInfo object contains a single instance of this object for
** each term in the FROM clause (which is to say, for each of the
** nested loops as implemented). The order of WhereLevel objects determines
** the loop nested order, with WhereInfo.a[0] being the outer loop and
** WhereInfo.a[WhereInfo.nLevel-1] being the inner loop.
*/ */
struct WhereLevel { struct WhereLevel {
int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */ int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
@@ -92,10 +101,18 @@ struct WhereLevel {
}; };
/* /*
** Each instance of this object represents a way of evaluating one ** Each instance of this object represents an algorithm for evaluating one
** term of a join. The WhereClause object holds a table of these ** term of a join. Every term of the FROM clause will have at least
** objects using (maskSelf,prereq,) as the primary key. Note that the ** one corresponding WhereLoop object (unless INDEXED BY constraints
** same join term might have multiple associated WhereLoop objects. ** prevent a query solution - which is an error) and many terms of the
** FROM clause will have multiple WhereLoop objects, each describing a
** potential way of implementing that FROM-clause term, together with
** dependencies and cost estimates for using the chosen algorithm.
**
** Query planning consists of building up a collection of these WhereLoop
** objects, then computing a particular sequence of WhereLoop objects, with
** one WhereLoop object per FROM clause term, that satisfy all dependencies
** and that minimize the overall cost.
*/ */
struct WhereLoop { struct WhereLoop {
Bitmask prereq; /* Bitmask of other loops that must run first */ Bitmask prereq; /* Bitmask of other loops that must run first */
@@ -136,7 +153,21 @@ static int whereLoopResize(sqlite3*, WhereLoop*, int);
/* /*
** Each instance of this object holds a sequence of WhereLoop objects ** Each instance of this object holds a sequence of WhereLoop objects
** that implement some or all of the entire query plan. ** that implement some or all of a query plan.
**
** Think of each WhereLoop objects as a node in a graph, which arcs
** showing dependences and costs for travelling between nodes. (That is
** not a completely accurate description because WhereLoop costs are a
** vector, not a scalar, and because dependences are many-to-one, not
** one-to-one as are graph nodes. But it is a useful visualization aid.)
** Then a WherePath object is a path through the graph that visits some
** or all of the WhereLoop objects once.
**
** The "solver" works by creating the N best WherePath objects of length
** 1. Then using those as a basis to compute the N best WherePath objects
** of length 2. And so forth until the length of WherePaths equals the
** number of nodes in the FROM clause. The best (lowest cost) WherePath
** at the end is the choosen query plan.
*/ */
struct WherePath { struct WherePath {
Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */ Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
@@ -323,7 +354,8 @@ struct WhereMaskSet {
}; };
/* /*
** This object is a factory for WhereLoop objects for a particular query. ** This object is a convenience wrapper holding all information needed
** to construct WhereLoop objects for a particular query.
*/ */
struct WhereLoopBuilder { struct WhereLoopBuilder {
WhereInfo *pWInfo; /* Information about this WHERE */ WhereInfo *pWInfo; /* Information about this WHERE */
@@ -339,6 +371,9 @@ struct WhereLoopBuilder {
** half does the tail of the WHERE loop. An instance of ** half does the tail of the WHERE loop. An instance of
** this structure is returned by the first half and passed ** this structure is returned by the first half and passed
** into the second half to give some continuity. ** into the second half to give some continuity.
**
** An instance of this object holds the complete state of the query
** planner.
*/ */
struct WhereInfo { struct WhereInfo {
Parse *pParse; /* Parsing and code generating context */ Parse *pParse; /* Parsing and code generating context */
@@ -364,9 +399,10 @@ struct WhereInfo {
}; };
/* /*
** Bitmasks for the operators that indices are able to exploit. An ** Bitmasks for the operators on WhereTerm objects. These are all
** operators that are of interest to the query planner. An
** OR-ed combination of these values can be used when searching for ** OR-ed combination of these values can be used when searching for
** terms in the where clause. ** particular WhereTerms within a WhereClause.
*/ */
#define WO_IN 0x001 #define WO_IN 0x001
#define WO_EQ 0x002 #define WO_EQ 0x002
@@ -385,9 +421,9 @@ struct WhereInfo {
#define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */
/* /*
** Value for wsFlags returned by bestIndex() and stored in ** These are definitions of bits in the WhereLoop.wsFlags field.
** WhereLevel.wsFlags. These flags determine which search ** The particular combination of bits in each WhereLoop help to
** strategies are appropriate. ** determine the algorithm that WhereLoop represents.
*/ */
#define WHERE_COLUMN_EQ 0x00000001 /* x=EXPR or x IN (...) or x IS NULL */ #define WHERE_COLUMN_EQ 0x00000001 /* x=EXPR or x IN (...) or x IS NULL */
#define WHERE_COLUMN_RANGE 0x00000002 /* x<EXPR and/or x>EXPR */ #define WHERE_COLUMN_RANGE 0x00000002 /* x<EXPR and/or x>EXPR */
@@ -409,6 +445,7 @@ struct WhereInfo {
/* Convert a WhereCost value (10 times log2(X)) into its integer value X. /* Convert a WhereCost value (10 times log2(X)) into its integer value X.
** A rough approximation is used. The value returned is not exact.
*/ */
static u64 whereCostToInt(WhereCost x){ static u64 whereCostToInt(WhereCost x){
u64 n; u64 n;
@@ -602,7 +639,7 @@ static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
} }
/* /*
** Initialize an expression mask set (a WhereMaskSet object) ** Initialize a WhereMaskSet object
*/ */
#define initMaskSet(P) (P)->n=0 #define initMaskSet(P) (P)->n=0
@@ -635,18 +672,9 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
} }
/* /*
** This routine walks (recursively) an expression tree and generates ** These routine walk (recursively) an expression tree and generates
** a bitmask indicating which tables are used in that expression ** a bitmask indicating which tables are used in that expression
** tree. ** tree.
**
** In order for this routine to work, the calling function must have
** previously invoked sqlite3ResolveExprNames() on the expression. See
** the header comment on that routine for additional information.
** The sqlite3ResolveExprNames() routines looks for column names and
** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
** the VDBE cursor number of the table. This routine just has to
** translate the cursor numbers into bitmask values and OR all
** the bitmasks together.
*/ */
static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*); static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*);
static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*); static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*);
@@ -700,7 +728,7 @@ static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
/* /*
** Return TRUE if the given operator is one of the operators that is ** Return TRUE if the given operator is one of the operators that is
** allowed for an indexable WHERE clause term. The allowed operators are ** allowed for an indexable WHERE clause term. The allowed operators are
** "=", "<", ">", "<=", ">=", and "IN". ** "=", "<", ">", "<=", ">=", "IN", and "IS NULL"
** **
** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be ** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be
** of one of the following forms: column = expression column > expression ** of one of the following forms: column = expression column > expression
@@ -727,10 +755,9 @@ static int allowedOp(int op){
** are converted into "Y op X". ** are converted into "Y op X".
** **
** If left/right precedence rules come into play when determining the ** If left/right precedence rules come into play when determining the
** collating ** collating sequence, then COLLATE operators are adjusted to ensure
** side of the comparison, it remains associated with the same side after ** that the collating sequence does not change. For example:
** the commutation. So "Y collate NOCASE op X" becomes ** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on
** "X op Y". This is because any collation sequence on
** the left hand side of a comparison overrides any collation sequence ** the left hand side of a comparison overrides any collation sequence
** attached to the right. For the same reason the EP_Collate flag ** attached to the right. For the same reason the EP_Collate flag
** is not commuted. ** is not commuted.
@@ -871,6 +898,11 @@ WhereTerm *whereScanNext(WhereScan *pScan){
** for terms of the form "X <op> <expr>" where X is column iColumn of table ** for terms of the form "X <op> <expr>" where X is column iColumn of table
** iCur. The <op> must be one of the operators described by opMask. ** iCur. The <op> must be one of the operators described by opMask.
** **
** If the search is for X and the WHERE clause contains terms of the
** form X=Y then this routine might also return terms of the form
** "Y <op> <expr>". The number of levels of transitivity is limited,
** but is enough to handle most commonly occurring SQL statements.
**
** If X is not the INTEGER PRIMARY KEY then X must be compatible with ** If X is not the INTEGER PRIMARY KEY then X must be compatible with
** index pIdx. ** index pIdx.
*/ */
@@ -959,8 +991,6 @@ static void exprAnalyze(SrcList*, WhereClause*, int);
/* /*
** Call exprAnalyze on all terms in a WHERE clause. ** Call exprAnalyze on all terms in a WHERE clause.
**
**
*/ */
static void exprAnalyzeAll( static void exprAnalyzeAll(
SrcList *pTabList, /* the FROM clause */ SrcList *pTabList, /* the FROM clause */
@@ -1739,11 +1769,8 @@ static void exprAnalyze(
} }
/* /*
** This function searches the expression list passed as the second argument ** This function searches pList for a entry that matches the iCol-th column
** for an expression of type TK_COLUMN that refers to the same column and ** of index pIdx.
** uses the same collation sequence as the iCol'th column of index pIdx.
** Argument iBase is the cursor number used for the table that pIdx refers
** to.
** **
** If such an expression is found, its index in pList->a[] is returned. If ** If such an expression is found, its index in pList->a[] is returned. If
** no expression is found, -1 is returned. ** no expression is found, -1 is returned.
@@ -1778,7 +1805,7 @@ static int findIndexCol(
** Return true if the DISTINCT expression-list passed as the third argument ** Return true if the DISTINCT expression-list passed as the third argument
** is redundant. ** is redundant.
** **
** A DISTINCT list is redundant if the database contains some set of ** A DISTINCT list is redundant if the database contains some subset of
** columns that are unique and non-null. ** columns that are unique and non-null.
*/ */
static int isDistinctRedundant( static int isDistinctRedundant(
@@ -1842,7 +1869,10 @@ static int isDistinctRedundant(
} }
/* /*
** The sum of two WhereCosts ** The (an approximate) sum of two WhereCosts. This computation is
** not a simple "+" operator because WhereCost is stored as a logarithmic
** value.
**
*/ */
static WhereCost whereCostAdd(WhereCost a, WhereCost b){ static WhereCost whereCostAdd(WhereCost a, WhereCost b){
static const unsigned char x[] = { static const unsigned char x[] = {
@@ -1868,7 +1898,8 @@ static WhereCost whereCostAdd(WhereCost a, WhereCost b){
} }
/* /*
** Convert an integer into a WhereCost ** Convert an integer into a WhereCost. In other words, compute a
** good approximatation for 10*log2(x).
*/ */
static WhereCost whereCostFromInt(tRowcnt x){ static WhereCost whereCostFromInt(tRowcnt x){
static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 }; static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
@@ -1886,7 +1917,8 @@ static WhereCost whereCostFromInt(tRowcnt x){
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
/* /*
** Convert a double (as received from xBestIndex of a virtual table) ** Convert a double (as received from xBestIndex of a virtual table)
** into a WhereCost ** into a WhereCost. In other words, compute an approximation for
** 10*log2(x).
*/ */
static WhereCost whereCostFromDouble(double x){ static WhereCost whereCostFromDouble(double x){
u64 a; u64 a;
@@ -1901,11 +1933,7 @@ static WhereCost whereCostFromDouble(double x){
#endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* SQLITE_OMIT_VIRTUALTABLE */
/* /*
** Prepare a crude estimate of the logarithm of the input value. ** Estimate the logarithm of the input value to base 2.
** The results need not be exact. This is only used for estimating
** the total cost of performing operations with O(logN) or O(NlogN)
** complexity. Because N is just a guess, it is no great tragedy if
** logN is a little off.
*/ */
static WhereCost estLog(WhereCost N){ static WhereCost estLog(WhereCost N){
WhereCost x = whereCostFromInt(N); WhereCost x = whereCostFromInt(N);
@@ -2158,8 +2186,6 @@ static sqlite3_index_info *allocateIndexInfo(
int nOrderBy; int nOrderBy;
sqlite3_index_info *pIdxInfo; sqlite3_index_info *pIdxInfo;
/*WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName));*/
/* Count the number of possible WHERE clause constraints referring /* Count the number of possible WHERE clause constraints referring
** to this virtual table */ ** to this virtual table */
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
@@ -2250,8 +2276,8 @@ static sqlite3_index_info *allocateIndexInfo(
/* /*
** The table object reference passed as the second argument to this function ** The table object reference passed as the second argument to this function
** must represent a virtual table. This function invokes the xBestIndex() ** must represent a virtual table. This function invokes the xBestIndex()
** method of the virtual table with the sqlite3_index_info pointer passed ** method of the virtual table with the sqlite3_index_info object that
** as the argument. ** comes in as the 3rd argument to this function.
** **
** If an error occurs, pParse is populated with an error message and a ** If an error occurs, pParse is populated with an error message and a
** non-zero value is returned. Otherwise, 0 is returned and the output ** non-zero value is returned. Otherwise, 0 is returned and the output
@@ -2266,7 +2292,6 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
int i; int i;
int rc; int rc;
/*WHERETRACE(("xBestIndex for %s\n", pTab->zName));*/
TRACE_IDX_INPUTS(p); TRACE_IDX_INPUTS(p);
rc = pVtab->pModule->xBestIndex(pVtab, p); rc = pVtab->pModule->xBestIndex(pVtab, p);
TRACE_IDX_OUTPUTS(p); TRACE_IDX_OUTPUTS(p);
@@ -2578,8 +2603,8 @@ static int whereRangeScanEst(
iBase -= whereCostFromInt(iUpper - iLower); iBase -= whereCostFromInt(iUpper - iLower);
} }
*pRangeDiv = iBase; *pRangeDiv = iBase;
/*WHERETRACE(("range scan regions: %u..%u div=%g\n", WHERETRACE(0x100, ("range scan regions: %u..%u div=%d\n",
(u32)iLower, (u32)iUpper, *pRangeDiv));*/ (u32)iLower, (u32)iUpper, *pRangeDiv));
return SQLITE_OK; return SQLITE_OK;
} }
} }
@@ -2640,7 +2665,7 @@ static int whereEqualScanEst(
if( pRhs==0 ) return SQLITE_NOTFOUND; if( pRhs==0 ) return SQLITE_NOTFOUND;
rc = whereKeyStats(pParse, p, pRhs, 0, a); rc = whereKeyStats(pParse, p, pRhs, 0, a);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
/*WHERETRACE(("equality scan regions: %d\n", (int)a[1]));*/ WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1]));
*pnRow = a[1]; *pnRow = a[1];
} }
whereEqualScanEst_cancel: whereEqualScanEst_cancel:
@@ -2686,7 +2711,7 @@ static int whereInScanEst(
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0]; if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
*pnRow = nRowEst; *pnRow = nRowEst;
/*WHERETRACE(("IN row estimate: est=%g\n", nRowEst));*/ WHERETRACE(0x100,("IN row estimate: est=%g\n", nRowEst));
} }
return rc; return rc;
} }
@@ -5060,9 +5085,7 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
nLoop = pWInfo->nLevel; nLoop = pWInfo->nLevel;
mxChoice = (nLoop==1) ? 1 : (nLoop==2 ? 5 : 10); mxChoice = (nLoop==1) ? 1 : (nLoop==2 ? 5 : 10);
assert( nLoop<=pWInfo->pTabList->nSrc ); assert( nLoop<=pWInfo->pTabList->nSrc );
#ifdef WHERETRACE_ENABLED WHERETRACE(0x002, ("---- begin solver\n"));
if( sqlite3WhereTrace>=2 ) sqlite3DebugPrintf("---- begin solver\n");
#endif
/* Allocate and initialize space for aTo and aFrom */ /* Allocate and initialize space for aTo and aFrom */
ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
@@ -5088,11 +5111,7 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
}else{ }else{
/* Compute an estimate on the cost to sort the entire result set */ /* Compute an estimate on the cost to sort the entire result set */
rSortCost = nRowEst + estLog(nRowEst); rSortCost = nRowEst + estLog(nRowEst);
#ifdef WHERETRACE_ENABLED WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
if( sqlite3WhereTrace>=2 ){
sqlite3DebugPrintf("---- sort cost=%-3d\n", rSortCost);
}
#endif
} }
/* Compute successively longer WherePaths using the previous generation /* Compute successively longer WherePaths using the previous generation
@@ -5605,7 +5624,7 @@ WhereInfo *sqlite3WhereBegin(
} }
/* Construct the WhereLoop objects */ /* Construct the WhereLoop objects */
WHERETRACE(("*** Optimizer Start ***\n")); WHERETRACE(0xffff,("*** Optimizer Start ***\n"));
if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
rc = whereLoopAddAll(&sWLB); rc = whereLoopAddAll(&sWLB);
if( rc ) goto whereBeginError; if( rc ) goto whereBeginError;
@@ -5664,21 +5683,20 @@ WhereInfo *sqlite3WhereBegin(
} }
} }
#endif #endif
WHERETRACE(("*** Optimizer Finished ***\n")); WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
#if 0 /* FIXME: Add this back in? */
/* If the caller is an UPDATE or DELETE statement that is requesting /* If the caller is an UPDATE or DELETE statement that is requesting
** to use a one-pass algorithm, determine if this is appropriate. ** to use a one-pass algorithm, determine if this is appropriate.
** The one-pass algorithm only works if the WHERE clause constraints ** The one-pass algorithm only works if the WHERE clause constraints
** the statement to update a single row. ** the statement to update a single row.
*/ */
assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_ONEROW)!=0 ){ if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
&& (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
pWInfo->okOnePass = 1; pWInfo->okOnePass = 1;
pWInfo->a[0].plan.wsFlags &= ~WHERE_IDX_ONLY; pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY;
} }
#endif
/* Open all tables in the pTabList and any indices selected for /* Open all tables in the pTabList and any indices selected for
** searching those tables. ** searching those tables.