Merge latest trunk changes into this branch.
FossilOrigin-Name: 373fa21bffd37053bb1a741d3ace2f003a5639bf373c20ea7bb24a31080888b3
This commit is contained in:
+92
-44
@@ -1863,40 +1863,40 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
|
||||
** Free a WhereInfo structure
|
||||
*/
|
||||
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
||||
if( ALWAYS(pWInfo) ){
|
||||
int i;
|
||||
for(i=0; i<pWInfo->nLevel; i++){
|
||||
WhereLevel *pLevel = &pWInfo->a[i];
|
||||
if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){
|
||||
sqlite3DbFree(db, pLevel->u.in.aInLoop);
|
||||
}
|
||||
int i;
|
||||
assert( pWInfo!=0 );
|
||||
for(i=0; i<pWInfo->nLevel; i++){
|
||||
WhereLevel *pLevel = &pWInfo->a[i];
|
||||
if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){
|
||||
sqlite3DbFree(db, pLevel->u.in.aInLoop);
|
||||
}
|
||||
sqlite3WhereClauseClear(&pWInfo->sWC);
|
||||
while( pWInfo->pLoops ){
|
||||
WhereLoop *p = pWInfo->pLoops;
|
||||
pWInfo->pLoops = p->pNextLoop;
|
||||
whereLoopDelete(db, p);
|
||||
}
|
||||
sqlite3DbFreeNN(db, pWInfo);
|
||||
}
|
||||
sqlite3WhereClauseClear(&pWInfo->sWC);
|
||||
while( pWInfo->pLoops ){
|
||||
WhereLoop *p = pWInfo->pLoops;
|
||||
pWInfo->pLoops = p->pNextLoop;
|
||||
whereLoopDelete(db, p);
|
||||
}
|
||||
sqlite3DbFreeNN(db, pWInfo);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if all of the following are true:
|
||||
**
|
||||
** (1) X has the same or lower cost that Y
|
||||
** (2) X is a proper subset of Y
|
||||
** (3) X skips at least as many columns as Y
|
||||
**
|
||||
** By "proper subset" we mean that X uses fewer WHERE clause terms
|
||||
** than Y and that every WHERE clause term used by X is also used
|
||||
** by Y.
|
||||
** (2) X uses fewer WHERE clause terms than Y
|
||||
** (3) Every WHERE clause term used by X is also used by Y
|
||||
** (4) X skips at least as many columns as Y
|
||||
** (5) If X is a covering index, than Y is too
|
||||
**
|
||||
** Conditions (2) and (3) mean that X is a "proper subset" of Y.
|
||||
** If X is a proper subset of Y then Y is a better choice and ought
|
||||
** to have a lower cost. This routine returns TRUE when that cost
|
||||
** relationship is inverted and needs to be adjusted. The third rule
|
||||
** relationship is inverted and needs to be adjusted. Constraint (4)
|
||||
** was added because if X uses skip-scan less than Y it still might
|
||||
** deserve a lower cost even if it is a proper subset of Y.
|
||||
** deserve a lower cost even if it is a proper subset of Y. Constraint (5)
|
||||
** was added because a covering index probably deserves to have a lower cost
|
||||
** than a non-covering index even if it is a proper subset.
|
||||
*/
|
||||
static int whereLoopCheaperProperSubset(
|
||||
const WhereLoop *pX, /* First WhereLoop to compare */
|
||||
@@ -1918,6 +1918,10 @@ static int whereLoopCheaperProperSubset(
|
||||
}
|
||||
if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */
|
||||
}
|
||||
if( (pX->wsFlags&WHERE_IDX_ONLY)!=0
|
||||
&& (pY->wsFlags&WHERE_IDX_ONLY)==0 ){
|
||||
return 0; /* Constraint (5) */
|
||||
}
|
||||
return 1; /* All conditions meet */
|
||||
}
|
||||
|
||||
@@ -2456,7 +2460,7 @@ static int whereLoopAddBtreeIndex(
|
||||
pNew->wsFlags |= WHERE_COLUMN_EQ;
|
||||
assert( saved_nEq==pNew->u.btree.nEq );
|
||||
if( iCol==XN_ROWID
|
||||
|| (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
|
||||
|| (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
|
||||
){
|
||||
if( iCol>=0 && pProbe->uniqNotNull==0 ){
|
||||
pNew->wsFlags |= WHERE_UNQ_WANTED;
|
||||
@@ -2865,9 +2869,11 @@ static int whereLoopAddBtree(
|
||||
}
|
||||
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
|
||||
|
||||
/* Loop over all indices
|
||||
*/
|
||||
for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){
|
||||
/* Loop over all indices. If there was an INDEXED BY clause, then only
|
||||
** consider index pProbe. */
|
||||
for(; rc==SQLITE_OK && pProbe;
|
||||
pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++
|
||||
){
|
||||
if( pProbe->pPartIdxWhere!=0
|
||||
&& !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){
|
||||
testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */
|
||||
@@ -2977,10 +2983,6 @@ static int whereLoopAddBtree(
|
||||
pBuilder->nRecValid = 0;
|
||||
pBuilder->pRec = 0;
|
||||
#endif
|
||||
|
||||
/* If there was an INDEXED BY clause, then only that one index is
|
||||
** considered. */
|
||||
if( pSrc->pIBIndex ) break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -4713,35 +4715,80 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Attempt to omit tables from the join that do not effect the result */
|
||||
|
||||
/* Attempt to omit tables from the join that do not affect the result.
|
||||
** For a table to not affect the result, the following must be true:
|
||||
**
|
||||
** 1) The query must not be an aggregate.
|
||||
** 2) The table must be the RHS of a LEFT JOIN.
|
||||
** 3) Either the query must be DISTINCT, or else the ON or USING clause
|
||||
** must contain a constraint that limits the scan of the table to
|
||||
** at most a single row.
|
||||
** 4) The table must not be referenced by any part of the query apart
|
||||
** from its own USING or ON clause.
|
||||
**
|
||||
** For example, given:
|
||||
**
|
||||
** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
|
||||
** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
|
||||
** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3);
|
||||
**
|
||||
** then table t2 can be omitted from the following:
|
||||
**
|
||||
** SELECT v1, v3 FROM t1
|
||||
** LEFT JOIN t2 USING (t1.ipk=t2.ipk)
|
||||
** LEFT JOIN t3 USING (t1.ipk=t3.ipk)
|
||||
**
|
||||
** or from:
|
||||
**
|
||||
** SELECT DISTINCT v1, v3 FROM t1
|
||||
** LEFT JOIN t2
|
||||
** LEFT JOIN t3 USING (t1.ipk=t3.ipk)
|
||||
*/
|
||||
notReady = ~(Bitmask)0;
|
||||
if( pWInfo->nLevel>=2
|
||||
&& pResultSet!=0
|
||||
&& pResultSet!=0 /* guarantees condition (1) above */
|
||||
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
|
||||
){
|
||||
int i;
|
||||
Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
|
||||
if( sWLB.pOrderBy ){
|
||||
tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
|
||||
}
|
||||
while( pWInfo->nLevel>=2 ){
|
||||
for(i=pWInfo->nLevel-1; i>=1; i--){
|
||||
WhereTerm *pTerm, *pEnd;
|
||||
pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop;
|
||||
if( (pWInfo->pTabList->a[pLoop->iTab].fg.jointype & JT_LEFT)==0 ) break;
|
||||
struct SrcList_item *pItem;
|
||||
pLoop = pWInfo->a[i].pWLoop;
|
||||
pItem = &pWInfo->pTabList->a[pLoop->iTab];
|
||||
if( (pItem->fg.jointype & JT_LEFT)==0 ) continue;
|
||||
if( (wctrlFlags & WHERE_WANT_DISTINCT)==0
|
||||
&& (pLoop->wsFlags & WHERE_ONEROW)==0
|
||||
){
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if( (tabUsed & pLoop->maskSelf)!=0 ) break;
|
||||
if( (tabUsed & pLoop->maskSelf)!=0 ) continue;
|
||||
pEnd = sWLB.pWC->a + sWLB.pWC->nTerm;
|
||||
for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
|
||||
if( (pTerm->prereqAll & pLoop->maskSelf)!=0
|
||||
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
|
||||
){
|
||||
break;
|
||||
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
|
||||
if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
|
||||
|| pTerm->pExpr->iRightJoinTable!=pItem->iCursor
|
||||
){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( pTerm<pEnd ) break;
|
||||
if( pTerm<pEnd ) continue;
|
||||
WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
|
||||
notReady &= ~pLoop->maskSelf;
|
||||
for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
|
||||
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
|
||||
pTerm->wtFlags |= TERM_CODED;
|
||||
}
|
||||
}
|
||||
if( i!=pWInfo->nLevel-1 ){
|
||||
int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
|
||||
memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
|
||||
}
|
||||
pWInfo->nLevel--;
|
||||
nTabList--;
|
||||
}
|
||||
@@ -4896,7 +4943,6 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** loop below generates code for a single nested loop of the VM
|
||||
** program.
|
||||
*/
|
||||
notReady = ~(Bitmask)0;
|
||||
for(ii=0; ii<nTabList; ii++){
|
||||
int addrExplain;
|
||||
int wsFlags;
|
||||
@@ -4960,6 +5006,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
Index *pIdx;
|
||||
int n;
|
||||
if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
|
||||
&& i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */
|
||||
&& (pLoop->wsFlags & WHERE_INDEXED)!=0
|
||||
&& (pIdx = pLoop->u.btree.pIndex)->hasStat1
|
||||
&& (n = pLoop->u.btree.nIdxCol)>0
|
||||
@@ -5026,7 +5073,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
|
||||
assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
|
||||
if( (ws & WHERE_IDX_ONLY)==0 ){
|
||||
sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
|
||||
assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor );
|
||||
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
|
||||
}
|
||||
if( (ws & WHERE_INDEXED)
|
||||
|| ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx)
|
||||
|
||||
Reference in New Issue
Block a user