Commit 420c1661 authored by Tom Lane's avatar Tom Lane

Fix failure to mark all aggregates with appropriate transtype.

In commit 915b703e I gave get_agg_clause_costs() the responsibility of
marking Aggref nodes with the appropriate aggtranstype.  I failed to notice
that where it was being called from, it might see only a subset of the
Aggref nodes that were in the original targetlist.  Specifically, if there
are duplicate aggregate calls in the tlist, either make_sort_input_target
or make_window_input_target might put just a single instance into the
grouping_target, and then only that instance would get marked.  Fix by
moving the call back into grouping_planner(), before we start building
assorted PathTargets from the query tlist.  Per report from Stefan Huehner.

Report: <20160702131056.GD3165@huehner.biz>
parent b54f7a9a
...@@ -114,6 +114,7 @@ static Size estimate_hashagg_tablesize(Path *path, ...@@ -114,6 +114,7 @@ static Size estimate_hashagg_tablesize(Path *path,
static RelOptInfo *create_grouping_paths(PlannerInfo *root, static RelOptInfo *create_grouping_paths(PlannerInfo *root,
RelOptInfo *input_rel, RelOptInfo *input_rel,
PathTarget *target, PathTarget *target,
const AggClauseCosts *agg_costs,
List *rollup_lists, List *rollup_lists,
List *rollup_groupclauses); List *rollup_groupclauses);
static RelOptInfo *create_window_paths(PlannerInfo *root, static RelOptInfo *create_window_paths(PlannerInfo *root,
...@@ -1499,6 +1500,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, ...@@ -1499,6 +1500,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
PathTarget *grouping_target; PathTarget *grouping_target;
PathTarget *scanjoin_target; PathTarget *scanjoin_target;
bool have_grouping; bool have_grouping;
AggClauseCosts agg_costs;
WindowFuncLists *wflists = NULL; WindowFuncLists *wflists = NULL;
List *activeWindows = NIL; List *activeWindows = NIL;
List *rollup_lists = NIL; List *rollup_lists = NIL;
...@@ -1623,6 +1625,28 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, ...@@ -1623,6 +1625,28 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
*/ */
root->processed_tlist = tlist; root->processed_tlist = tlist;
/*
* Collect statistics about aggregates for estimating costs, and mark
* all the aggregates with resolved aggtranstypes. We must do this
* before slicing and dicing the tlist into various pathtargets, else
* some copies of the Aggref nodes might escape being marked with the
* correct transtypes.
*
* Note: currently, we do not detect duplicate aggregates here. This
* may result in somewhat-overestimated cost, which is fine for our
* purposes since all Paths will get charged the same. But at some
* point we might wish to do that detection in the planner, rather
* than during executor startup.
*/
MemSet(&agg_costs, 0, sizeof(AggClauseCosts));
if (parse->hasAggs)
{
get_agg_clause_costs(root, (Node *) tlist, AGGSPLIT_SIMPLE,
&agg_costs);
get_agg_clause_costs(root, parse->havingQual, AGGSPLIT_SIMPLE,
&agg_costs);
}
/* /*
* Locate any window functions in the tlist. (We don't need to look * Locate any window functions in the tlist. (We don't need to look
* anywhere else, since expressions used in ORDER BY will be in there * anywhere else, since expressions used in ORDER BY will be in there
...@@ -1822,6 +1846,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, ...@@ -1822,6 +1846,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
current_rel = create_grouping_paths(root, current_rel = create_grouping_paths(root,
current_rel, current_rel,
grouping_target, grouping_target,
&agg_costs,
rollup_lists, rollup_lists,
rollup_groupclauses); rollup_groupclauses);
} }
...@@ -3244,6 +3269,7 @@ estimate_hashagg_tablesize(Path *path, const AggClauseCosts *agg_costs, ...@@ -3244,6 +3269,7 @@ estimate_hashagg_tablesize(Path *path, const AggClauseCosts *agg_costs,
* *
* input_rel: contains the source-data Paths * input_rel: contains the source-data Paths
* target: the pathtarget for the result Paths to compute * target: the pathtarget for the result Paths to compute
* agg_costs: cost info about all aggregates in query (in AGGSPLIT_SIMPLE mode)
* rollup_lists: list of grouping sets, or NIL if not doing grouping sets * rollup_lists: list of grouping sets, or NIL if not doing grouping sets
* rollup_groupclauses: list of grouping clauses for grouping sets, * rollup_groupclauses: list of grouping clauses for grouping sets,
* or NIL if not doing grouping sets * or NIL if not doing grouping sets
...@@ -3260,6 +3286,7 @@ static RelOptInfo * ...@@ -3260,6 +3286,7 @@ static RelOptInfo *
create_grouping_paths(PlannerInfo *root, create_grouping_paths(PlannerInfo *root,
RelOptInfo *input_rel, RelOptInfo *input_rel,
PathTarget *target, PathTarget *target,
const AggClauseCosts *agg_costs,
List *rollup_lists, List *rollup_lists,
List *rollup_groupclauses) List *rollup_groupclauses)
{ {
...@@ -3267,7 +3294,6 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3267,7 +3294,6 @@ create_grouping_paths(PlannerInfo *root,
Path *cheapest_path = input_rel->cheapest_total_path; Path *cheapest_path = input_rel->cheapest_total_path;
RelOptInfo *grouped_rel; RelOptInfo *grouped_rel;
PathTarget *partial_grouping_target = NULL; PathTarget *partial_grouping_target = NULL;
AggClauseCosts agg_costs;
AggClauseCosts agg_partial_costs; /* parallel only */ AggClauseCosts agg_partial_costs; /* parallel only */
AggClauseCosts agg_final_costs; /* parallel only */ AggClauseCosts agg_final_costs; /* parallel only */
Size hashaggtablesize; Size hashaggtablesize;
...@@ -3364,20 +3390,6 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3364,20 +3390,6 @@ create_grouping_paths(PlannerInfo *root,
return grouped_rel; return grouped_rel;
} }
/*
* Collect statistics about aggregates for estimating costs. Note: we do
* not detect duplicate aggregates here; a somewhat-overestimated cost is
* okay for our purposes.
*/
MemSet(&agg_costs, 0, sizeof(AggClauseCosts));
if (parse->hasAggs)
{
get_agg_clause_costs(root, (Node *) target->exprs, AGGSPLIT_SIMPLE,
&agg_costs);
get_agg_clause_costs(root, parse->havingQual, AGGSPLIT_SIMPLE,
&agg_costs);
}
/* /*
* Estimate number of groups. * Estimate number of groups.
*/ */
...@@ -3414,7 +3426,7 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3414,7 +3426,7 @@ create_grouping_paths(PlannerInfo *root,
*/ */
can_hash = (parse->groupClause != NIL && can_hash = (parse->groupClause != NIL &&
parse->groupingSets == NIL && parse->groupingSets == NIL &&
agg_costs.numOrderedAggs == 0 && agg_costs->numOrderedAggs == 0 &&
grouping_is_hashable(parse->groupClause)); grouping_is_hashable(parse->groupClause));
/* /*
...@@ -3446,7 +3458,7 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3446,7 +3458,7 @@ create_grouping_paths(PlannerInfo *root,
/* We don't know how to do grouping sets in parallel. */ /* We don't know how to do grouping sets in parallel. */
try_parallel_aggregation = false; try_parallel_aggregation = false;
} }
else if (agg_costs.hasNonPartial || agg_costs.hasNonSerial) else if (agg_costs->hasNonPartial || agg_costs->hasNonSerial)
{ {
/* Insufficient support for partial mode. */ /* Insufficient support for partial mode. */
try_parallel_aggregation = false; try_parallel_aggregation = false;
...@@ -3627,7 +3639,7 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3627,7 +3639,7 @@ create_grouping_paths(PlannerInfo *root,
(List *) parse->havingQual, (List *) parse->havingQual,
rollup_lists, rollup_lists,
rollup_groupclauses, rollup_groupclauses,
&agg_costs, agg_costs,
dNumGroups)); dNumGroups));
} }
else if (parse->hasAggs) else if (parse->hasAggs)
...@@ -3645,7 +3657,7 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3645,7 +3657,7 @@ create_grouping_paths(PlannerInfo *root,
AGGSPLIT_SIMPLE, AGGSPLIT_SIMPLE,
parse->groupClause, parse->groupClause,
(List *) parse->havingQual, (List *) parse->havingQual,
&agg_costs, agg_costs,
dNumGroups)); dNumGroups));
} }
else if (parse->groupClause) else if (parse->groupClause)
...@@ -3727,7 +3739,7 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3727,7 +3739,7 @@ create_grouping_paths(PlannerInfo *root,
if (can_hash) if (can_hash)
{ {
hashaggtablesize = estimate_hashagg_tablesize(cheapest_path, hashaggtablesize = estimate_hashagg_tablesize(cheapest_path,
&agg_costs, agg_costs,
dNumGroups); dNumGroups);
/* /*
...@@ -3751,7 +3763,7 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3751,7 +3763,7 @@ create_grouping_paths(PlannerInfo *root,
AGGSPLIT_SIMPLE, AGGSPLIT_SIMPLE,
parse->groupClause, parse->groupClause,
(List *) parse->havingQual, (List *) parse->havingQual,
&agg_costs, agg_costs,
dNumGroups)); dNumGroups));
} }
......
...@@ -296,3 +296,27 @@ order by s2 desc; ...@@ -296,3 +296,27 @@ order by s2 desc;
0 | 0 0 | 0
(3 rows) (3 rows)
-- test for failure to set all aggregates' aggtranstype
explain (verbose, costs off)
select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2
from tenk1 group by thousand order by thousand limit 3;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------
Limit
Output: (sum(tenthous)), (((sum(tenthous))::double precision + (random() * '0'::double precision))), thousand
-> GroupAggregate
Output: sum(tenthous), ((sum(tenthous))::double precision + (random() * '0'::double precision)), thousand
Group Key: tenk1.thousand
-> Index Only Scan using tenk1_thous_tenthous on public.tenk1
Output: thousand, tenthous
(7 rows)
select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2
from tenk1 group by thousand order by thousand limit 3;
s1 | s2
-------+-------
45000 | 45000
45010 | 45010
45020 | 45020
(3 rows)
...@@ -91,3 +91,11 @@ order by s2 desc; ...@@ -91,3 +91,11 @@ order by s2 desc;
select generate_series(0,2) as s1, generate_series((random()*.1)::int,2) as s2 select generate_series(0,2) as s1, generate_series((random()*.1)::int,2) as s2
order by s2 desc; order by s2 desc;
-- test for failure to set all aggregates' aggtranstype
explain (verbose, costs off)
select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2
from tenk1 group by thousand order by thousand limit 3;
select sum(tenthous) as s1, sum(tenthous) + random()*0 as s2
from tenk1 group by thousand order by thousand limit 3;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment