mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Use the estimated number of rows computed for subqueries in the cost
computations for outer queries. FossilOrigin-Name: 56bbc539246a6dc9f1ae1edb898db7a4f6f6d322
This commit is contained in:
20
src/select.c
20
src/select.c
@@ -1433,6 +1433,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
||||
VdbeComment((v, "LIMIT counter"));
|
||||
if( n==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
|
||||
}else{
|
||||
if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n;
|
||||
}
|
||||
}else{
|
||||
sqlite3ExprCode(pParse, p->pLimit, iLimit);
|
||||
@@ -1594,6 +1596,7 @@ static int multiSelect(
|
||||
switch( p->op ){
|
||||
case TK_ALL: {
|
||||
int addr = 0;
|
||||
int nLimit;
|
||||
assert( !pPrior->pLimit );
|
||||
pPrior->pLimit = p->pLimit;
|
||||
pPrior->pOffset = p->pOffset;
|
||||
@@ -1616,6 +1619,13 @@ static int multiSelect(
|
||||
testcase( rc!=SQLITE_OK );
|
||||
pDelete = p->pPrior;
|
||||
p->pPrior = pPrior;
|
||||
p->nSelectRow += pPrior->nSelectRow;
|
||||
if( pPrior->pLimit
|
||||
&& sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
|
||||
&& p->nSelectRow > (double)nLimit
|
||||
){
|
||||
p->nSelectRow = (double)nLimit;
|
||||
}
|
||||
if( addr ){
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
@@ -1688,6 +1698,7 @@ static int multiSelect(
|
||||
pDelete = p->pPrior;
|
||||
p->pPrior = pPrior;
|
||||
p->pOrderBy = 0;
|
||||
if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow;
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
p->pLimit = pLimit;
|
||||
p->pOffset = pOffset;
|
||||
@@ -1767,6 +1778,7 @@ static int multiSelect(
|
||||
testcase( rc!=SQLITE_OK );
|
||||
pDelete = p->pPrior;
|
||||
p->pPrior = pPrior;
|
||||
if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
|
||||
sqlite3ExprDelete(db, p->pLimit);
|
||||
p->pLimit = pLimit;
|
||||
p->pOffset = pOffset;
|
||||
@@ -2353,6 +2365,7 @@ static int multiSelectOrderBy(
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
|
||||
p->nSelectRow += pPrior->nSelectRow;
|
||||
}
|
||||
|
||||
/* Generate a subroutine to run when the results from select B
|
||||
@@ -2360,6 +2373,7 @@ static int multiSelectOrderBy(
|
||||
*/
|
||||
if( op==TK_INTERSECT ){
|
||||
addrEofB = addrEofA;
|
||||
if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
|
||||
}else{
|
||||
VdbeNoopComment((v, "eof-B subroutine"));
|
||||
addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
|
||||
@@ -3754,6 +3768,7 @@ int sqlite3Select(
|
||||
explainSetInteger(pItem->iSelectId, pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->isPopulated = 1;
|
||||
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
|
||||
}
|
||||
if( /*pParse->nErr ||*/ db->mallocFailed ){
|
||||
goto select_end;
|
||||
@@ -3846,6 +3861,7 @@ int sqlite3Select(
|
||||
/* Set the limiter.
|
||||
*/
|
||||
iEnd = sqlite3VdbeMakeLabel(v);
|
||||
p->nSelectRow = (double)LARGEST_INT64;
|
||||
computeLimitRegisters(pParse, p, iEnd);
|
||||
|
||||
/* Open a virtual index to use for the distinct set.
|
||||
@@ -3869,6 +3885,7 @@ int sqlite3Select(
|
||||
*/
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
|
||||
|
||||
/* If sorting index that was created by a prior OP_OpenEphemeral
|
||||
** instruction ended up not being needed, then change the OP_OpenEphemeral
|
||||
@@ -3913,6 +3930,9 @@ int sqlite3Select(
|
||||
for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
|
||||
pItem->iAlias = 0;
|
||||
}
|
||||
if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100;
|
||||
}else{
|
||||
p->nSelectRow = (double)1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user