mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-30 19:00:29 +08:00
Planner wasn't correctly handling adjustment of tuple_fraction for the
case of LIMIT in a sub-select.
This commit is contained in:
parent
7db692ceb6
commit
2ef99ee708
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.102 2001/03/22 03:59:37 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.103 2001/04/01 22:37:19 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -874,9 +874,9 @@ grouping_planner(Query *parse, double tuple_fraction)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out whether we expect to retrieve all the tuples that
|
* Figure out whether we expect to retrieve all the tuples that
|
||||||
* the plan can generate, or to stop early due to a LIMIT or other
|
* the plan can generate, or to stop early due to outside factors
|
||||||
* factors. If the caller passed a value >= 0, believe that
|
* such as a cursor. If the caller passed a value >= 0, believe
|
||||||
* value, else do our own examination of the query context.
|
* that value, else do our own examination of the query context.
|
||||||
*/
|
*/
|
||||||
if (tuple_fraction < 0.0)
|
if (tuple_fraction < 0.0)
|
||||||
{
|
{
|
||||||
@ -884,74 +884,118 @@ grouping_planner(Query *parse, double tuple_fraction)
|
|||||||
tuple_fraction = 0.0;
|
tuple_fraction = 0.0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for a LIMIT clause.
|
* Check for retrieve-into-portal, ie DECLARE CURSOR.
|
||||||
*/
|
|
||||||
if (parse->limitCount != NULL)
|
|
||||||
{
|
|
||||||
if (IsA(parse->limitCount, Const))
|
|
||||||
{
|
|
||||||
Const *limitc = (Const *) parse->limitCount;
|
|
||||||
int32 count = DatumGetInt32(limitc->constvalue);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A NULL-constant LIMIT represents "LIMIT ALL", which
|
|
||||||
* we treat the same as no limit (ie, expect to
|
|
||||||
* retrieve all the tuples).
|
|
||||||
*/
|
|
||||||
if (!limitc->constisnull && count > 0)
|
|
||||||
{
|
|
||||||
tuple_fraction = (double) count;
|
|
||||||
/* We must also consider the OFFSET, if present */
|
|
||||||
if (parse->limitOffset != NULL)
|
|
||||||
{
|
|
||||||
if (IsA(parse->limitOffset, Const))
|
|
||||||
{
|
|
||||||
int32 offset;
|
|
||||||
|
|
||||||
limitc = (Const *) parse->limitOffset;
|
|
||||||
offset = DatumGetInt32(limitc->constvalue);
|
|
||||||
if (!limitc->constisnull && offset > 0)
|
|
||||||
tuple_fraction += (double) offset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* It's an expression ... punt ... */
|
|
||||||
tuple_fraction = 0.10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* COUNT is an expression ... don't know exactly what
|
|
||||||
* the limit will be, but for lack of a better idea
|
|
||||||
* assume 10% of the plan's result is wanted.
|
|
||||||
*/
|
|
||||||
tuple_fraction = 0.10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If no LIMIT, check for retrieve-into-portal, ie DECLARE
|
|
||||||
* CURSOR.
|
|
||||||
*
|
*
|
||||||
* We have no real idea how many tuples the user will ultimately
|
* We have no real idea how many tuples the user will ultimately
|
||||||
* FETCH from a cursor, but it seems a good bet that he
|
* FETCH from a cursor, but it seems a good bet that he
|
||||||
* doesn't want 'em all. Optimize for 10% retrieval (you
|
* doesn't want 'em all. Optimize for 10% retrieval (you
|
||||||
* gotta better number?)
|
* gotta better number? Should this be a SETtable parameter?)
|
||||||
*/
|
*/
|
||||||
else if (parse->isPortal)
|
if (parse->isPortal)
|
||||||
tuple_fraction = 0.10;
|
tuple_fraction = 0.10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust tuple_fraction if we see that we are going to apply
|
* Adjust tuple_fraction if we see that we are going to apply
|
||||||
* grouping/aggregation/etc. This is not overridable by the
|
* limiting/grouping/aggregation/etc. This is not overridable by
|
||||||
* caller, since it reflects plan actions that this routine will
|
* the caller, since it reflects plan actions that this routine
|
||||||
* certainly take, not assumptions about context.
|
* will certainly take, not assumptions about context.
|
||||||
*/
|
*/
|
||||||
|
if (parse->limitCount != NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* A LIMIT clause limits the absolute number of tuples returned.
|
||||||
|
* However, if it's not a constant LIMIT then we have to punt;
|
||||||
|
* for lack of a better idea, assume 10% of the plan's result
|
||||||
|
* is wanted.
|
||||||
|
*/
|
||||||
|
double limit_fraction = 0.0;
|
||||||
|
|
||||||
|
if (IsA(parse->limitCount, Const))
|
||||||
|
{
|
||||||
|
Const *limitc = (Const *) parse->limitCount;
|
||||||
|
int32 count = DatumGetInt32(limitc->constvalue);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A NULL-constant LIMIT represents "LIMIT ALL", which
|
||||||
|
* we treat the same as no limit (ie, expect to
|
||||||
|
* retrieve all the tuples).
|
||||||
|
*/
|
||||||
|
if (!limitc->constisnull && count > 0)
|
||||||
|
{
|
||||||
|
limit_fraction = (double) count;
|
||||||
|
/* We must also consider the OFFSET, if present */
|
||||||
|
if (parse->limitOffset != NULL)
|
||||||
|
{
|
||||||
|
if (IsA(parse->limitOffset, Const))
|
||||||
|
{
|
||||||
|
int32 offset;
|
||||||
|
|
||||||
|
limitc = (Const *) parse->limitOffset;
|
||||||
|
offset = DatumGetInt32(limitc->constvalue);
|
||||||
|
if (!limitc->constisnull && offset > 0)
|
||||||
|
limit_fraction += (double) offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* OFFSET is an expression ... punt ... */
|
||||||
|
limit_fraction = 0.10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* LIMIT is an expression ... punt ... */
|
||||||
|
limit_fraction = 0.10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit_fraction > 0.0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If we have absolute limits from both caller and LIMIT,
|
||||||
|
* use the smaller value; if one is fractional and the other
|
||||||
|
* absolute, treat the fraction as a fraction of the absolute
|
||||||
|
* value; else we can multiply the two fractions together.
|
||||||
|
*/
|
||||||
|
if (tuple_fraction >= 1.0)
|
||||||
|
{
|
||||||
|
if (limit_fraction >= 1.0)
|
||||||
|
{
|
||||||
|
/* both absolute */
|
||||||
|
tuple_fraction = Min(tuple_fraction, limit_fraction);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* caller absolute, limit fractional */
|
||||||
|
tuple_fraction *= limit_fraction;
|
||||||
|
if (tuple_fraction < 1.0)
|
||||||
|
tuple_fraction = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tuple_fraction > 0.0)
|
||||||
|
{
|
||||||
|
if (limit_fraction >= 1.0)
|
||||||
|
{
|
||||||
|
/* caller fractional, limit absolute */
|
||||||
|
tuple_fraction *= limit_fraction;
|
||||||
|
if (tuple_fraction < 1.0)
|
||||||
|
tuple_fraction = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* both fractional */
|
||||||
|
tuple_fraction *= limit_fraction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no info from caller, just use limit */
|
||||||
|
tuple_fraction = limit_fraction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (parse->groupClause)
|
if (parse->groupClause)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user