aboutsummaryrefslogtreecommitdiff
path: root/src/where.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2016-03-16 01:16:30 +0000
committerdrh <drh@noemail.net>2016-03-16 01:16:30 +0000
commit47e1842e5bd5c5f467b0290f3fde9df69fa42a25 (patch)
tree69786029a35258e2ee2a76f5d023764e19a074f0 /src/where.c
parentc5c67abb9ab2c58d41f75a41a1693e4b30e00bd5 (diff)
parent32f57d4c373c8f49b59f4a40149c136ef8a5632b (diff)
downloadsqlite-47e1842e5bd5c5f467b0290f3fde9df69fa42a25.tar.gz
sqlite-47e1842e5bd5c5f467b0290f3fde9df69fa42a25.zip
Merge all recent enhancements from trunk.
FossilOrigin-Name: 6a7ee04b0ddac36a87d5ed2ac89a53e537f4d5a3
Diffstat (limited to 'src/where.c')
-rw-r--r--src/where.c123
1 files changed, 68 insertions, 55 deletions
diff --git a/src/where.c b/src/where.c
index ea62617c5..83d72ee39 100644
--- a/src/where.c
+++ b/src/where.c
@@ -934,7 +934,6 @@ static sqlite3_index_info *allocateIndexInfo(
*/
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
- int i;
int rc;
TRACE_IDX_INPUTS(p);
@@ -953,12 +952,16 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
sqlite3_free(pVtab->zErrMsg);
pVtab->zErrMsg = 0;
+#if 0
+ /* This error is now caught by the caller.
+ ** Search for "xBestIndex malfunction" below */
for(i=0; i<p->nConstraint; i++){
if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
sqlite3ErrorMsg(pParse,
"table %s: xBestIndex returned an invalid plan", pTab->zName);
}
}
+#endif
return pParse->nErr;
}
@@ -1976,6 +1979,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
WhereLoop **ppPrev, *p;
WhereInfo *pWInfo = pBuilder->pWInfo;
sqlite3 *db = pWInfo->pParse->db;
+ int rc;
/* If pBuilder->pOrSet is defined, then only keep track of the costs
** and prereqs.
@@ -2058,14 +2062,14 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
whereLoopDelete(db, pToDel);
}
}
- whereLoopXfer(db, p, pTemplate);
+ rc = whereLoopXfer(db, p, pTemplate);
if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
Index *pIndex = p->u.btree.pIndex;
if( pIndex && pIndex->tnum==0 ){
p->u.btree.pIndex = 0;
}
}
- return SQLITE_OK;
+ return rc;
}
/*
@@ -2554,7 +2558,7 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
*/
static int whereLoopAddBtree(
WhereLoopBuilder *pBuilder, /* WHERE clause information */
- Bitmask mExtra /* Extra prerequesites for using this table */
+ Bitmask mPrereq /* Extra prerequesites for using this table */
){
WhereInfo *pWInfo; /* WHERE analysis context */
Index *pProbe; /* An index we are evaluating */
@@ -2654,7 +2658,7 @@ static int whereLoopAddBtree(
pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
pNew->wsFlags = WHERE_AUTO_INDEX;
- pNew->prereq = mExtra | pTerm->prereqRight;
+ pNew->prereq = mPrereq | pTerm->prereqRight;
rc = whereLoopInsert(pBuilder, pNew);
}
}
@@ -2675,7 +2679,7 @@ static int whereLoopAddBtree(
pNew->nLTerm = 0;
pNew->iSortIdx = 0;
pNew->rSetup = 0;
- pNew->prereq = mExtra;
+ pNew->prereq = mPrereq;
pNew->nOut = rSize;
pNew->u.btree.pIndex = pProbe;
b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
@@ -2762,7 +2766,7 @@ static int whereLoopAddBtree(
** * It is not one of the operators specified in the mExclude mask passed
** as the fourth argument (which in practice is either WO_IN or 0).
**
-** Argument mExtra is a mask of tables that must be scanned before the
+** Argument mPrereq is a mask of tables that must be scanned before the
** virtual table in question. These are added to the plans prerequisites
** before it is added to pBuilder.
**
@@ -2771,9 +2775,9 @@ static int whereLoopAddBtree(
*/
static int whereLoopAddVirtualOne(
WhereLoopBuilder *pBuilder,
- Bitmask mExtra, /* Mask of tables that must be used. */
- Bitmask mUsable, /* Mask of usable prereqs */
- u16 mExclude, /* Exclude terms for this operator */
+ Bitmask mPrereq, /* Mask of tables that must be used. */
+ Bitmask mUsable, /* Mask of usable tables */
+ u16 mExclude, /* Exclude terms using these operators */
sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */
int *pbIn /* OUT: True if plan uses an IN(...) op */
){
@@ -2788,9 +2792,9 @@ static int whereLoopAddVirtualOne(
struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
int nConstraint = pIdxInfo->nConstraint;
- assert( (mUsable & mExtra)==mExtra );
+ assert( (mUsable & mPrereq)==mPrereq );
*pbIn = 0;
- pNew->prereq = mExtra;
+ pNew->prereq = mPrereq;
/* Set the usable flag on the subset of constraints identified by
** arguments mUsable and mExclude. */
@@ -2807,10 +2811,9 @@ static int whereLoopAddVirtualOne(
/* Initialize the output fields of the sqlite3_index_info structure */
memset(pUsage, 0, sizeof(pUsage[0])*nConstraint);
- if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
+ assert( pIdxInfo->needToFreeIdxStr==0 );
pIdxInfo->idxStr = 0;
pIdxInfo->idxNum = 0;
- pIdxInfo->needToFreeIdxStr = 0;
pIdxInfo->orderByConsumed = 0;
pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
pIdxInfo->estimatedRows = 25;
@@ -2835,9 +2838,10 @@ static int whereLoopAddVirtualOne(
|| j<0
|| j>=pWC->nTerm
|| pNew->aLTerm[iTerm]!=0
+ || pIdxCons->usable==0
){
rc = SQLITE_ERROR;
- sqlite3ErrorMsg(pParse,"%s.xBestIndex() malfunction",pSrc->pTab->zName);
+ sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
return rc;
}
testcase( iTerm==nConstraint-1 );
@@ -2859,7 +2863,7 @@ static int whereLoopAddVirtualOne(
** together. */
pIdxInfo->orderByConsumed = 0;
pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
- *pbIn = 1;
+ *pbIn = 1; assert( (mExclude & WO_IN)==0 );
}
}
}
@@ -2883,13 +2887,16 @@ static int whereLoopAddVirtualOne(
}else{
pNew->wsFlags &= ~WHERE_ONEROW;
}
- whereLoopInsert(pBuilder, pNew);
+ rc = whereLoopInsert(pBuilder, pNew);
if( pNew->u.vtab.needFree ){
sqlite3_free(pNew->u.vtab.idxStr);
pNew->u.vtab.needFree = 0;
}
+ WHERETRACE(0xffff, (" bIn=%d prereqIn=%04llx prereqOut=%04llx\n",
+ *pbIn, (sqlite3_uint64)mPrereq,
+ (sqlite3_uint64)(pNew->prereq & ~mPrereq)));
- return SQLITE_OK;
+ return rc;
}
@@ -2897,8 +2904,8 @@ static int whereLoopAddVirtualOne(
** Add all WhereLoop objects for a table of the join identified by
** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
**
-** If there are no LEFT or CROSS JOIN joins in the query, both mExtra and
-** mUnusable are set to 0. Otherwise, mExtra is a mask of all FROM clause
+** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and
+** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause
** entries that occur before the virtual table in the FROM clause and are
** separated from it by at least one LEFT or CROSS JOIN. Similarly, the
** mUnusable mask contains all FROM clause entries that occur after the
@@ -2909,18 +2916,18 @@ static int whereLoopAddVirtualOne(
**
** ... FROM t1, t2 LEFT JOIN t3, t4, vt CROSS JOIN t5, t6;
**
-** then mExtra corresponds to (t1, t2) and mUnusable to (t5, t6).
+** then mPrereq corresponds to (t1, t2) and mUnusable to (t5, t6).
**
-** All the tables in mExtra must be scanned before the current virtual
+** All the tables in mPrereq must be scanned before the current virtual
** table. So any terms for which all prerequisites are satisfied by
-** mExtra may be specified as "usable" in all calls to xBestIndex.
+** mPrereq may be specified as "usable" in all calls to xBestIndex.
** Conversely, all tables in mUnusable must be scanned after the current
** virtual table, so any terms for which the prerequisites overlap with
** mUnusable should always be configured as "not-usable" for xBestIndex.
*/
static int whereLoopAddVirtual(
WhereLoopBuilder *pBuilder, /* WHERE clause information */
- Bitmask mExtra, /* Tables that must be scanned before this one */
+ Bitmask mPrereq, /* Tables that must be scanned before this one */
Bitmask mUnusable /* Tables that must be scanned after this one */
){
int rc = SQLITE_OK; /* Return code */
@@ -2934,14 +2941,14 @@ static int whereLoopAddVirtual(
WhereLoop *pNew;
Bitmask mBest; /* Tables used by best possible plan */
- assert( (mExtra & mUnusable)==0 );
+ assert( (mPrereq & mUnusable)==0 );
pWInfo = pBuilder->pWInfo;
pParse = pWInfo->pParse;
pWC = pBuilder->pWC;
pNew = pBuilder->pNew;
pSrc = &pWInfo->pTabList->a[pNew->iTab];
assert( IsVirtual(pSrc->pTab) );
- p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc,pBuilder->pOrderBy);
+ p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy);
if( p==0 ) return SQLITE_NOMEM_BKPT;
pNew->rSetup = 0;
pNew->wsFlags = WHERE_VIRTUALTABLE;
@@ -2954,15 +2961,15 @@ static int whereLoopAddVirtual(
}
/* First call xBestIndex() with all constraints usable. */
- rc = whereLoopAddVirtualOne(pBuilder, mExtra, (Bitmask)(-1), 0, p, &bIn);
- mBest = pNew->prereq & ~mExtra;
+ WHERETRACE(0x40, (" VirtualOne: all usable\n"));
+ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, &bIn);
/* If the call to xBestIndex() with all terms enabled produced a plan
- ** that does not require any source tables, there is no point in making
- ** any further calls - if the xBestIndex() method is sane they will all
- ** return the same plan anyway.
- */
- if( mBest ){
+ ** that does not require any source tables (IOW: a plan with mBest==0),
+ ** then there is no point in making any further calls to xBestIndex()
+ ** since they will all return the same result (if the xBestIndex()
+ ** implementation is sane). */
+ if( rc==SQLITE_OK && (mBest = (pNew->prereq & ~mPrereq))!=0 ){
int seenZero = 0; /* True if a plan with no prereqs seen */
int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */
Bitmask mPrev = 0;
@@ -2970,32 +2977,36 @@ static int whereLoopAddVirtual(
/* If the plan produced by the earlier call uses an IN(...) term, call
** xBestIndex again, this time with IN(...) terms disabled. */
- if( rc==SQLITE_OK && bIn ){
- rc = whereLoopAddVirtualOne(pBuilder, mExtra, (Bitmask)-1, WO_IN, p,&bIn);
- mBestNoIn = pNew->prereq & ~mExtra;
+ if( bIn ){
+ WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n"));
+ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, WO_IN, p, &bIn);
+ assert( bIn==0 );
+ mBestNoIn = pNew->prereq & ~mPrereq;
if( mBestNoIn==0 ){
seenZero = 1;
- if( bIn==0 ) seenZeroNoIN = 1;
+ seenZeroNoIN = 1;
}
}
- /* Call xBestIndex once for each distinct value of (prereqRight & ~mExtra)
+ /* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq)
** in the set of terms that apply to the current virtual table. */
while( rc==SQLITE_OK ){
int i;
- Bitmask mNext = (Bitmask)(-1);
+ Bitmask mNext = ALLBITS;
assert( mNext>0 );
for(i=0; i<nConstraint; i++){
Bitmask mThis = (
- pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mExtra
+ pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
);
if( mThis>mPrev && mThis<mNext ) mNext = mThis;
}
mPrev = mNext;
- if( mNext==(Bitmask)(-1) ) break;
+ if( mNext==ALLBITS ) break;
if( mNext==mBest || mNext==mBestNoIn ) continue;
- rc = whereLoopAddVirtualOne(pBuilder, mExtra, mNext|mExtra, 0, p, &bIn);
- if( pNew->prereq==mExtra ){
+ WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n",
+ (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext));
+ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mNext|mPrereq, 0, p, &bIn);
+ if( pNew->prereq==mPrereq ){
seenZero = 1;
if( bIn==0 ) seenZeroNoIN = 1;
}
@@ -3005,7 +3016,8 @@ static int whereLoopAddVirtual(
** that requires no source tables at all (i.e. one guaranteed to be
** usable), make a call here with all source tables disabled */
if( rc==SQLITE_OK && seenZero==0 ){
- rc = whereLoopAddVirtualOne(pBuilder, mExtra, mExtra, 0, p, &bIn);
+ WHERETRACE(0x40, (" VirtualOne: all disabled\n"));
+ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, 0, p, &bIn);
if( bIn==0 ) seenZeroNoIN = 1;
}
@@ -3013,7 +3025,8 @@ static int whereLoopAddVirtual(
** that requires no source tables at all and does not use an IN(...)
** operator, make a final call to obtain one here. */
if( rc==SQLITE_OK && seenZeroNoIN==0 ){
- rc = whereLoopAddVirtualOne(pBuilder, mExtra, mExtra, WO_IN, p, &bIn);
+ WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n"));
+ rc = whereLoopAddVirtualOne(pBuilder, mPrereq, mPrereq, WO_IN, p, &bIn);
}
}
@@ -3029,7 +3042,7 @@ static int whereLoopAddVirtual(
*/
static int whereLoopAddOr(
WhereLoopBuilder *pBuilder,
- Bitmask mExtra,
+ Bitmask mPrereq,
Bitmask mUnusable
){
WhereInfo *pWInfo = pBuilder->pWInfo;
@@ -3090,14 +3103,14 @@ static int whereLoopAddOr(
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
- rc = whereLoopAddVirtual(&sSubBuild, mExtra, mUnusable);
+ rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable);
}else
#endif
{
- rc = whereLoopAddBtree(&sSubBuild, mExtra);
+ rc = whereLoopAddBtree(&sSubBuild, mPrereq);
}
if( rc==SQLITE_OK ){
- rc = whereLoopAddOr(&sSubBuild, mExtra, mUnusable);
+ rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
}
assert( rc==SQLITE_OK || sCur.n==0 );
if( sCur.n==0 ){
@@ -3154,7 +3167,7 @@ static int whereLoopAddOr(
*/
static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
WhereInfo *pWInfo = pBuilder->pWInfo;
- Bitmask mExtra = 0;
+ Bitmask mPrereq = 0;
Bitmask mPrior = 0;
int iTab;
SrcList *pTabList = pWInfo->pTabList;
@@ -3175,7 +3188,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
/* This condition is true when pItem is the FROM clause term on the
** right-hand-side of a LEFT or CROSS JOIN. */
- mExtra = mPrior;
+ mPrereq = mPrior;
}
priorJointype = pItem->fg.jointype;
if( IsVirtual(pItem->pTab) ){
@@ -3185,12 +3198,12 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
}
}
- rc = whereLoopAddVirtual(pBuilder, mExtra, mUnusable);
+ rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable);
}else{
- rc = whereLoopAddBtree(pBuilder, mExtra);
+ rc = whereLoopAddBtree(pBuilder, mPrereq);
}
if( rc==SQLITE_OK ){
- rc = whereLoopAddOr(pBuilder, mExtra, mUnusable);
+ rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable);
}
mPrior |= pNew->maskSelf;
if( rc || db->mallocFailed ) break;
@@ -4280,7 +4293,7 @@ WhereInfo *sqlite3WhereBegin(
}
}
if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
- pWInfo->revMask = (Bitmask)(-1);
+ pWInfo->revMask = ALLBITS;
}
if( pParse->nErr || NEVER(db->mallocFailed) ){
goto whereBeginError;