mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-22 20:22:44 +03:00
Where possible, take advantage of the rowid at the end of index records to optimize range constraints (<, >, <=, >=) on the rowid column.
FossilOrigin-Name: 3b58f5f06648205a47e5cace0201269c406e476a
This commit is contained in:
42
src/where.c
42
src/where.c
@@ -604,7 +604,7 @@ static WhereTerm *findTerm(
|
||||
&& pTerm->u.leftColumn==iColumn
|
||||
&& (pTerm->eOperator & op)!=0
|
||||
){
|
||||
if( pIdx && pTerm->eOperator!=WO_ISNULL ){
|
||||
if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){
|
||||
Expr *pX = pTerm->pExpr;
|
||||
CollSeq *pColl;
|
||||
char idxaff;
|
||||
@@ -3052,10 +3052,24 @@ static void bestBtreeIndex(
|
||||
#endif
|
||||
used |= pTerm->prereqRight;
|
||||
}
|
||||
|
||||
/* Determine the value of rangeDiv */
|
||||
if( nEq<pProbe->nColumn && pProbe->bUnordered==0 ){
|
||||
int j = pProbe->aiColumn[nEq];
|
||||
|
||||
/* If the index being considered is UNIQUE, and there is an equality
|
||||
** constraint for all columns in the index, then this search will find
|
||||
** at most a single row. In this case set the WHERE_UNIQUE flag to
|
||||
** indicate this to the caller.
|
||||
**
|
||||
** Otherwise, if the search may find more than one row, test to see if
|
||||
** there is a range constraint on indexed column (nEq+1) that can be
|
||||
** optimized using the index.
|
||||
*/
|
||||
if( nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
|
||||
testcase( wsFlags & WHERE_COLUMN_IN );
|
||||
testcase( wsFlags & WHERE_COLUMN_NULL );
|
||||
if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
|
||||
wsFlags |= WHERE_UNIQUE;
|
||||
}
|
||||
}else if( pProbe->bUnordered==0 ){
|
||||
int j = (nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[nEq]);
|
||||
if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
|
||||
WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx);
|
||||
WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx);
|
||||
@@ -3074,12 +3088,6 @@ static void bestBtreeIndex(
|
||||
}
|
||||
wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
|
||||
}
|
||||
}else if( pProbe->onError!=OE_None ){
|
||||
testcase( wsFlags & WHERE_COLUMN_IN );
|
||||
testcase( wsFlags & WHERE_COLUMN_NULL );
|
||||
if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
|
||||
wsFlags |= WHERE_UNIQUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is an ORDER BY clause and the index being considered will
|
||||
@@ -3690,10 +3698,12 @@ static char *explainIndexRange(sqlite3 *db, WhereLevel *pLevel, Table *pTab){
|
||||
|
||||
j = i;
|
||||
if( pPlan->wsFlags&WHERE_BTM_LIMIT ){
|
||||
explainAppendTerm(&txt, i++, aCol[aiColumn[j]].zName, ">");
|
||||
char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
|
||||
explainAppendTerm(&txt, i++, z, ">");
|
||||
}
|
||||
if( pPlan->wsFlags&WHERE_TOP_LIMIT ){
|
||||
explainAppendTerm(&txt, i, aCol[aiColumn[j]].zName, "<");
|
||||
char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
|
||||
explainAppendTerm(&txt, i, z, "<");
|
||||
}
|
||||
sqlite3StrAccumAppend(&txt, ")", 1);
|
||||
return sqlite3StrAccumFinish(&txt);
|
||||
@@ -4051,7 +4061,7 @@ static Bitmask codeOneLoopStart(
|
||||
|
||||
pIdx = pLevel->plan.u.pIdx;
|
||||
iIdxCur = pLevel->iIdxCur;
|
||||
k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */
|
||||
k = (nEq==pIdx->nColumn ? -1 : pIdx->aiColumn[nEq]);
|
||||
|
||||
/* If this loop satisfies a sort order (pOrderBy) request that
|
||||
** was passed to this function to implement a "SELECT min(x) ..."
|
||||
@@ -4097,7 +4107,9 @@ static Bitmask codeOneLoopStart(
|
||||
** a forward order scan on a descending index, interchange the
|
||||
** start and end terms (pRangeStart and pRangeEnd).
|
||||
*/
|
||||
if( nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){
|
||||
if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
|
||||
|| (bRev && pIdx->nColumn==nEq)
|
||||
){
|
||||
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user