mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Take the LIMIT clause into account when estimating the cost of sorting.
FossilOrigin-Name: d491745cab951e0de70f1f79b7640ea8aff6e8bb
This commit is contained in:
35
src/select.c
35
src/select.c
@@ -105,7 +105,7 @@ Select *sqlite3SelectNew(
|
||||
ExprList *pGroupBy, /* the GROUP BY clause */
|
||||
Expr *pHaving, /* the HAVING clause */
|
||||
ExprList *pOrderBy, /* the ORDER BY clause */
|
||||
u16 selFlags, /* Flag parameters, such as SF_Distinct */
|
||||
u32 selFlags, /* Flag parameters, such as SF_Distinct */
|
||||
Expr *pLimit, /* LIMIT value. NULL means not used */
|
||||
Expr *pOffset /* OFFSET value. NULL means no offset */
|
||||
){
|
||||
@@ -1845,8 +1845,9 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
||||
VdbeComment((v, "LIMIT counter"));
|
||||
if( n==0 ){
|
||||
sqlite3VdbeGoto(v, iBreak);
|
||||
}else if( n>=0 && p->nSelectRow>(u64)n ){
|
||||
p->nSelectRow = n;
|
||||
}else if( n>=0 && p->nSelectRow>sqlite3LogEst((u64)n) ){
|
||||
p->nSelectRow = sqlite3LogEst((u64)n);
|
||||
p->selFlags |= SF_FixedLimit;
|
||||
}
|
||||
}else{
|
||||
sqlite3ExprCode(pParse, p->pLimit, iLimit);
|
||||
@@ -2287,12 +2288,12 @@ static int multiSelect(
|
||||
testcase( rc!=SQLITE_OK );
|
||||
pDelete = p->pPrior;
|
||||
p->pPrior = pPrior;
|
||||
p->nSelectRow += pPrior->nSelectRow;
|
||||
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
|
||||
if( pPrior->pLimit
|
||||
&& sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
|
||||
&& nLimit>0 && p->nSelectRow > (u64)nLimit
|
||||
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
|
||||
){
|
||||
p->nSelectRow = nLimit;
|
||||
p->nSelectRow = sqlite3LogEst((u64)nLimit);
|
||||
}
|
||||
if( addr ){
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
@@ -2364,7 +2365,9 @@ static int multiSelect(
|
||||
pDelete = p->pPrior;
|
||||
p->pPrior = pPrior;
|
||||
p->pOrderBy = 0;
|
||||
if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow;
|
||||
if( p->op==TK_UNION ){
|
||||
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
|
||||
}
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
p->pLimit = pLimit;
|
||||
p->pOffset = pOffset;
|
||||
@@ -3001,7 +3004,7 @@ static int multiSelectOrderBy(
|
||||
addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeGoto(v, addrEofA);
|
||||
p->nSelectRow += pPrior->nSelectRow;
|
||||
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
|
||||
}
|
||||
|
||||
/* Generate a subroutine to run when the results from select B
|
||||
@@ -4987,7 +4990,7 @@ int sqlite3Select(
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
pItem->pTab->nRowLogEst = pSub->nSelectRow;
|
||||
pItem->fg.viaCoroutine = 1;
|
||||
pItem->regResult = dest.iSdst;
|
||||
sqlite3VdbeEndCoroutine(v, pItem->regReturn);
|
||||
@@ -5018,7 +5021,7 @@ int sqlite3Select(
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
pItem->pTab->nRowLogEst = pSub->nSelectRow;
|
||||
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
|
||||
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
|
||||
VdbeComment((v, "end %s", pItem->pTab->zName));
|
||||
@@ -5101,7 +5104,7 @@ int sqlite3Select(
|
||||
/* Set the limiter.
|
||||
*/
|
||||
iEnd = sqlite3VdbeMakeLabel(v);
|
||||
p->nSelectRow = LARGEST_INT64;
|
||||
p->nSelectRow = 320; /* 4 billion rows */
|
||||
computeLimitRegisters(pParse, p, iEnd);
|
||||
if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
|
||||
sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen);
|
||||
@@ -5125,10 +5128,12 @@ int sqlite3Select(
|
||||
if( !isAgg && pGroupBy==0 ){
|
||||
/* No aggregate functions and no GROUP BY clause */
|
||||
u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
|
||||
assert( WHERE_USE_LIMIT==SF_FixedLimit );
|
||||
wctrlFlags |= p->selFlags & SF_FixedLimit;
|
||||
|
||||
/* Begin the database scan. */
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
|
||||
p->pEList, wctrlFlags, 0);
|
||||
p->pEList, wctrlFlags, p->nSelectRow);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
|
||||
p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
|
||||
@@ -5188,9 +5193,11 @@ int sqlite3Select(
|
||||
for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
|
||||
pItem->u.x.iAlias = 0;
|
||||
}
|
||||
if( p->nSelectRow>100 ) p->nSelectRow = 100;
|
||||
assert( 66==sqlite3LogEst(100) );
|
||||
if( p->nSelectRow>66 ) p->nSelectRow = 66;
|
||||
}else{
|
||||
p->nSelectRow = 1;
|
||||
assert( 0==sqlite3LogEst(1) );
|
||||
p->nSelectRow = 0;
|
||||
}
|
||||
|
||||
/* If there is both a GROUP BY and an ORDER BY clause and they are
|
||||
|
||||
Reference in New Issue
Block a user