diff options
author | drh <drh@noemail.net> | 2013-06-11 01:50:08 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2013-06-11 01:50:08 +0000 |
commit | 8636e9c55cb46f8923ebbb8a1014010d9c813472 (patch) | |
tree | 0a4bcf91d647442779cd35967ed7bacbf6b5c7a8 /src | |
parent | 5822d6feb28aa9023abe7133b32d40e91eb3e943 (diff) | |
download | sqlite-8636e9c55cb46f8923ebbb8a1014010d9c813472.tar.gz sqlite-8636e9c55cb46f8923ebbb8a1014010d9c813472.zip |
Handle virtual tables correctly when using logarithmic costs. Fixes
to test cases.
FossilOrigin-Name: e612664aa2e24ed5e222be2c7fe16e210ac9bded
Diffstat (limited to 'src')
-rw-r--r-- | src/where.c | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/src/where.c b/src/where.c index 2b0049b9c..4a27b9e38 100644 --- a/src/where.c +++ b/src/where.c @@ -1882,6 +1882,23 @@ static WhereCost whereCostFromInt(tRowcnt x){ return a[x&7] + y - 10; } +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Convert a double (as received from xBestIndex of a virtual table) +** into a WhereCost +*/ +static WhereCost whereCostFromDouble(double x){ + u64 a; + WhereCost e; + assert( sizeof(x)==8 && sizeof(a)==8 ); + if( x<=1 ) return 0; + if( x<=2000000000 ) return whereCostFromInt((tRowcnt)x); + memcpy(&a, &x, 8); + e = (a>>52) - 1022; + return e*10; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + /* ** Prepare a crude estimate of the logarithm of the input value. ** The results need not be exact. This is only used for estimating @@ -4088,6 +4105,14 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ ** more terms of the index */ pNext = p->pNextLoop; break; + }else if( p->nOut>pTemplate->nOut + && p->rSetup==pTemplate->rSetup + && p->rRun==pTemplate->rRun + ){ + /* Overwrite an existing WhereLoop with the same cost but more + ** outputs */ + pNext = p->pNextLoop; + break; }else{ /* pTemplate is not helpful. ** Return without changing or adding anything */ @@ -4263,7 +4288,7 @@ static int whereLoopAddBtreeIndex( WhereCost rDiv; whereRangeScanEst(pParse, pProbe, pNew->u.btree.nEq, pBtm, pTop, &rDiv); - pNew->nOut = saved_nOut - rDiv; + pNew->nOut = saved_nOut>rDiv+10 ? saved_nOut - rDiv : 10; } #ifdef SQLITE_ENABLE_STAT3 if( pNew->u.btree.nEq==1 && pProbe->nSample ){ @@ -4482,6 +4507,7 @@ static int whereLoopAddBtree( return rc; } +#ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Add all WhereLoop objects for a table of the join identified by ** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table. @@ -4569,8 +4595,7 @@ static int whereLoopAddVirtual( pIdxInfo->idxNum = 0; pIdxInfo->needToFreeIdxStr = 0; pIdxInfo->orderByConsumed = 0; - /* ((WhereCost)2) In case of SQLITE_OMIT_FLOATING_POINT... */ - pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((WhereCost)2); + pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2; rc = vtabBestIndex(pParse, pTab, pIdxInfo); if( rc ) goto whereLoopAddVtab_exit; pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; @@ -4624,7 +4649,7 @@ static int whereLoopAddVirtual( pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0) && pIdxInfo->orderByConsumed); pNew->rSetup = 0; - pNew->rRun = whereCostFromInt((tRowcnt)pIdxInfo->estimatedCost); + pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost); pNew->nOut = 46; assert( 46 == whereCostFromInt(25) ); whereLoopInsert(pBuilder, pNew); if( pNew->u.vtab.needFree ){ @@ -4639,6 +4664,7 @@ whereLoopAddVtab_exit: sqlite3DbFree(db, pIdxInfo); return rc; } +#endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Add WhereLoop entries to handle OR terms. This works for either @@ -4695,9 +4721,12 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){ sBest.maskSelf = 0; sBest.rSetup = 0; sBest.rRun = 0; +#ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pItem->pTab) ){ rc = whereLoopAddVirtual(&sSubBuild, mExtra); - }else{ + }else +#endif + { rc = whereLoopAddBtree(&sSubBuild, mExtra); } if( sBest.maskSelf==0 ) break; |