Commit 19e972d5 authored by Tom Lane's avatar Tom Lane

Rethink node-level representation of partial-aggregation modes.

The original coding had three separate booleans representing partial
aggregation behavior, which was confusing, unreadable, and error-prone,
not least because the booleans weren't always listed in the same order.
It was also inadequate for the allegedly-desirable future extension to
support intermediate partial aggregation, because we'd need separate
markers for serialization and deserialization in such a case.

Merge these bools into an enum "AggSplit" to provide symbolic names for
the supported operating modes (and document what those are).  By assigning
the values of the enum constants carefully, we can treat AggSplit values
as options bitmasks so that tests of what to do aren't noticeably more
expensive than before.

While at it, get rid of Aggref.aggoutputtype.  That's not needed since
commit 59a3795c got rid of setrefs.c's special-purpose Aggref comparison
code, and it likewise seemed more confusing than helpful.

Assorted comment cleanup as well (there's still more that I want to do
in that line).

catversion bump for change in Aggref node contents.  Should be the last
one for partial-aggregation changes.

Discussion: <29309.1466699160@sss.pgh.pa.us>
parent 59a3795c
...@@ -947,9 +947,9 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -947,9 +947,9 @@ ExplainNode(PlanState *planstate, List *ancestors,
{ {
Agg *agg = (Agg *) plan; Agg *agg = (Agg *) plan;
if (agg->finalizeAggs == false) if (DO_AGGSPLIT_SKIPFINAL(agg->aggsplit))
operation = "Partial"; operation = "Partial";
else if (agg->combineStates == true) else if (DO_AGGSPLIT_COMBINE(agg->aggsplit))
operation = "Finalize"; operation = "Finalize";
switch (agg->aggstrategy) switch (agg->aggstrategy)
......
...@@ -4510,35 +4510,20 @@ ExecInitExpr(Expr *node, PlanState *parent) ...@@ -4510,35 +4510,20 @@ ExecInitExpr(Expr *node, PlanState *parent)
case T_Aggref: case T_Aggref:
{ {
AggrefExprState *astate = makeNode(AggrefExprState); AggrefExprState *astate = makeNode(AggrefExprState);
AggState *aggstate = (AggState *) parent;
Aggref *aggref = (Aggref *) node;
astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalAggref; astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalAggref;
if (!aggstate || !IsA(aggstate, AggState)) if (parent && IsA(parent, AggState))
{ {
/* planner messed up */ AggState *aggstate = (AggState *) parent;
elog(ERROR, "Aggref found in non-Agg plan node");
}
if (aggref->aggpartial == aggstate->finalizeAggs)
{
/* planner messed up */
if (aggref->aggpartial)
elog(ERROR, "partial Aggref found in finalize agg plan node");
else
elog(ERROR, "non-partial Aggref found in non-finalize agg plan node");
}
if (aggref->aggcombine != aggstate->combineStates) aggstate->aggs = lcons(astate, aggstate->aggs);
aggstate->numaggs++;
}
else
{ {
/* planner messed up */ /* planner messed up */
if (aggref->aggcombine) elog(ERROR, "Aggref found in non-Agg plan node");
elog(ERROR, "combine Aggref found in non-combine agg plan node");
else
elog(ERROR, "non-combine Aggref found in combine agg plan node");
} }
aggstate->aggs = lcons(astate, aggstate->aggs);
aggstate->numaggs++;
state = (ExprState *) astate; state = (ExprState *) astate;
} }
break; break;
......
This diff is collapsed.
...@@ -870,9 +870,7 @@ _copyAgg(const Agg *from) ...@@ -870,9 +870,7 @@ _copyAgg(const Agg *from)
CopyPlanFields((const Plan *) from, (Plan *) newnode); CopyPlanFields((const Plan *) from, (Plan *) newnode);
COPY_SCALAR_FIELD(aggstrategy); COPY_SCALAR_FIELD(aggstrategy);
COPY_SCALAR_FIELD(combineStates); COPY_SCALAR_FIELD(aggsplit);
COPY_SCALAR_FIELD(finalizeAggs);
COPY_SCALAR_FIELD(serialStates);
COPY_SCALAR_FIELD(numCols); COPY_SCALAR_FIELD(numCols);
if (from->numCols > 0) if (from->numCols > 0)
{ {
...@@ -1235,7 +1233,6 @@ _copyAggref(const Aggref *from) ...@@ -1235,7 +1233,6 @@ _copyAggref(const Aggref *from)
COPY_SCALAR_FIELD(aggfnoid); COPY_SCALAR_FIELD(aggfnoid);
COPY_SCALAR_FIELD(aggtype); COPY_SCALAR_FIELD(aggtype);
COPY_SCALAR_FIELD(aggoutputtype);
COPY_SCALAR_FIELD(aggcollid); COPY_SCALAR_FIELD(aggcollid);
COPY_SCALAR_FIELD(inputcollid); COPY_SCALAR_FIELD(inputcollid);
COPY_SCALAR_FIELD(aggtranstype); COPY_SCALAR_FIELD(aggtranstype);
...@@ -1247,10 +1244,9 @@ _copyAggref(const Aggref *from) ...@@ -1247,10 +1244,9 @@ _copyAggref(const Aggref *from)
COPY_NODE_FIELD(aggfilter); COPY_NODE_FIELD(aggfilter);
COPY_SCALAR_FIELD(aggstar); COPY_SCALAR_FIELD(aggstar);
COPY_SCALAR_FIELD(aggvariadic); COPY_SCALAR_FIELD(aggvariadic);
COPY_SCALAR_FIELD(aggcombine);
COPY_SCALAR_FIELD(aggpartial);
COPY_SCALAR_FIELD(aggkind); COPY_SCALAR_FIELD(aggkind);
COPY_SCALAR_FIELD(agglevelsup); COPY_SCALAR_FIELD(agglevelsup);
COPY_SCALAR_FIELD(aggsplit);
COPY_LOCATION_FIELD(location); COPY_LOCATION_FIELD(location);
return newnode; return newnode;
......
...@@ -192,7 +192,6 @@ _equalAggref(const Aggref *a, const Aggref *b) ...@@ -192,7 +192,6 @@ _equalAggref(const Aggref *a, const Aggref *b)
{ {
COMPARE_SCALAR_FIELD(aggfnoid); COMPARE_SCALAR_FIELD(aggfnoid);
COMPARE_SCALAR_FIELD(aggtype); COMPARE_SCALAR_FIELD(aggtype);
COMPARE_SCALAR_FIELD(aggoutputtype);
COMPARE_SCALAR_FIELD(aggcollid); COMPARE_SCALAR_FIELD(aggcollid);
COMPARE_SCALAR_FIELD(inputcollid); COMPARE_SCALAR_FIELD(inputcollid);
/* ignore aggtranstype since it might not be set yet */ /* ignore aggtranstype since it might not be set yet */
...@@ -204,10 +203,9 @@ _equalAggref(const Aggref *a, const Aggref *b) ...@@ -204,10 +203,9 @@ _equalAggref(const Aggref *a, const Aggref *b)
COMPARE_NODE_FIELD(aggfilter); COMPARE_NODE_FIELD(aggfilter);
COMPARE_SCALAR_FIELD(aggstar); COMPARE_SCALAR_FIELD(aggstar);
COMPARE_SCALAR_FIELD(aggvariadic); COMPARE_SCALAR_FIELD(aggvariadic);
COMPARE_SCALAR_FIELD(aggcombine);
COMPARE_SCALAR_FIELD(aggpartial);
COMPARE_SCALAR_FIELD(aggkind); COMPARE_SCALAR_FIELD(aggkind);
COMPARE_SCALAR_FIELD(agglevelsup); COMPARE_SCALAR_FIELD(agglevelsup);
COMPARE_SCALAR_FIELD(aggsplit);
COMPARE_LOCATION_FIELD(location); COMPARE_LOCATION_FIELD(location);
return true; return true;
......
...@@ -58,7 +58,7 @@ exprType(const Node *expr) ...@@ -58,7 +58,7 @@ exprType(const Node *expr)
type = ((const Param *) expr)->paramtype; type = ((const Param *) expr)->paramtype;
break; break;
case T_Aggref: case T_Aggref:
type = ((const Aggref *) expr)->aggoutputtype; type = ((const Aggref *) expr)->aggtype;
break; break;
case T_GroupingFunc: case T_GroupingFunc:
type = INT4OID; type = INT4OID;
......
...@@ -705,9 +705,7 @@ _outAgg(StringInfo str, const Agg *node) ...@@ -705,9 +705,7 @@ _outAgg(StringInfo str, const Agg *node)
_outPlanInfo(str, (const Plan *) node); _outPlanInfo(str, (const Plan *) node);
WRITE_ENUM_FIELD(aggstrategy, AggStrategy); WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
WRITE_BOOL_FIELD(combineStates); WRITE_ENUM_FIELD(aggsplit, AggSplit);
WRITE_BOOL_FIELD(finalizeAggs);
WRITE_BOOL_FIELD(serialStates);
WRITE_INT_FIELD(numCols); WRITE_INT_FIELD(numCols);
appendStringInfoString(str, " :grpColIdx"); appendStringInfoString(str, " :grpColIdx");
...@@ -1031,7 +1029,6 @@ _outAggref(StringInfo str, const Aggref *node) ...@@ -1031,7 +1029,6 @@ _outAggref(StringInfo str, const Aggref *node)
WRITE_OID_FIELD(aggfnoid); WRITE_OID_FIELD(aggfnoid);
WRITE_OID_FIELD(aggtype); WRITE_OID_FIELD(aggtype);
WRITE_OID_FIELD(aggoutputtype);
WRITE_OID_FIELD(aggcollid); WRITE_OID_FIELD(aggcollid);
WRITE_OID_FIELD(inputcollid); WRITE_OID_FIELD(inputcollid);
WRITE_OID_FIELD(aggtranstype); WRITE_OID_FIELD(aggtranstype);
...@@ -1043,10 +1040,9 @@ _outAggref(StringInfo str, const Aggref *node) ...@@ -1043,10 +1040,9 @@ _outAggref(StringInfo str, const Aggref *node)
WRITE_NODE_FIELD(aggfilter); WRITE_NODE_FIELD(aggfilter);
WRITE_BOOL_FIELD(aggstar); WRITE_BOOL_FIELD(aggstar);
WRITE_BOOL_FIELD(aggvariadic); WRITE_BOOL_FIELD(aggvariadic);
WRITE_BOOL_FIELD(aggcombine);
WRITE_BOOL_FIELD(aggpartial);
WRITE_CHAR_FIELD(aggkind); WRITE_CHAR_FIELD(aggkind);
WRITE_UINT_FIELD(agglevelsup); WRITE_UINT_FIELD(agglevelsup);
WRITE_ENUM_FIELD(aggsplit, AggSplit);
WRITE_LOCATION_FIELD(location); WRITE_LOCATION_FIELD(location);
} }
...@@ -1854,6 +1850,7 @@ _outAggPath(StringInfo str, const AggPath *node) ...@@ -1854,6 +1850,7 @@ _outAggPath(StringInfo str, const AggPath *node)
WRITE_NODE_FIELD(subpath); WRITE_NODE_FIELD(subpath);
WRITE_ENUM_FIELD(aggstrategy, AggStrategy); WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
WRITE_ENUM_FIELD(aggsplit, AggSplit);
WRITE_FLOAT_FIELD(numGroups, "%.0f"); WRITE_FLOAT_FIELD(numGroups, "%.0f");
WRITE_NODE_FIELD(groupClause); WRITE_NODE_FIELD(groupClause);
WRITE_NODE_FIELD(qual); WRITE_NODE_FIELD(qual);
......
...@@ -546,7 +546,6 @@ _readAggref(void) ...@@ -546,7 +546,6 @@ _readAggref(void)
READ_OID_FIELD(aggfnoid); READ_OID_FIELD(aggfnoid);
READ_OID_FIELD(aggtype); READ_OID_FIELD(aggtype);
READ_OID_FIELD(aggoutputtype);
READ_OID_FIELD(aggcollid); READ_OID_FIELD(aggcollid);
READ_OID_FIELD(inputcollid); READ_OID_FIELD(inputcollid);
READ_OID_FIELD(aggtranstype); READ_OID_FIELD(aggtranstype);
...@@ -558,10 +557,9 @@ _readAggref(void) ...@@ -558,10 +557,9 @@ _readAggref(void)
READ_NODE_FIELD(aggfilter); READ_NODE_FIELD(aggfilter);
READ_BOOL_FIELD(aggstar); READ_BOOL_FIELD(aggstar);
READ_BOOL_FIELD(aggvariadic); READ_BOOL_FIELD(aggvariadic);
READ_BOOL_FIELD(aggcombine);
READ_BOOL_FIELD(aggpartial);
READ_CHAR_FIELD(aggkind); READ_CHAR_FIELD(aggkind);
READ_UINT_FIELD(agglevelsup); READ_UINT_FIELD(agglevelsup);
READ_ENUM_FIELD(aggsplit, AggSplit);
READ_LOCATION_FIELD(location); READ_LOCATION_FIELD(location);
READ_DONE(); READ_DONE();
...@@ -1989,9 +1987,7 @@ _readAgg(void) ...@@ -1989,9 +1987,7 @@ _readAgg(void)
ReadCommonPlan(&local_node->plan); ReadCommonPlan(&local_node->plan);
READ_ENUM_FIELD(aggstrategy, AggStrategy); READ_ENUM_FIELD(aggstrategy, AggStrategy);
READ_BOOL_FIELD(combineStates); READ_ENUM_FIELD(aggsplit, AggSplit);
READ_BOOL_FIELD(finalizeAggs);
READ_BOOL_FIELD(serialStates);
READ_INT_FIELD(numCols); READ_INT_FIELD(numCols);
READ_ATTRNUMBER_ARRAY(grpColIdx, local_node->numCols); READ_ATTRNUMBER_ARRAY(grpColIdx, local_node->numCols);
READ_OID_ARRAY(grpOperators, local_node->numCols); READ_OID_ARRAY(grpOperators, local_node->numCols);
......
...@@ -1304,9 +1304,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags) ...@@ -1304,9 +1304,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
plan = (Plan *) make_agg(build_path_tlist(root, &best_path->path), plan = (Plan *) make_agg(build_path_tlist(root, &best_path->path),
NIL, NIL,
AGG_HASHED, AGG_HASHED,
false, AGGSPLIT_SIMPLE,
true,
false,
numGroupCols, numGroupCols,
groupColIdx, groupColIdx,
groupOperators, groupOperators,
...@@ -1610,9 +1608,7 @@ create_agg_plan(PlannerInfo *root, AggPath *best_path) ...@@ -1610,9 +1608,7 @@ create_agg_plan(PlannerInfo *root, AggPath *best_path)
plan = make_agg(tlist, quals, plan = make_agg(tlist, quals,
best_path->aggstrategy, best_path->aggstrategy,
best_path->combineStates, best_path->aggsplit,
best_path->finalizeAggs,
best_path->serialStates,
list_length(best_path->groupClause), list_length(best_path->groupClause),
extract_grouping_cols(best_path->groupClause, extract_grouping_cols(best_path->groupClause,
subplan->targetlist), subplan->targetlist),
...@@ -1765,9 +1761,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path) ...@@ -1765,9 +1761,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
agg_plan = (Plan *) make_agg(NIL, agg_plan = (Plan *) make_agg(NIL,
NIL, NIL,
AGG_SORTED, AGG_SORTED,
false, AGGSPLIT_SIMPLE,
true,
false,
list_length((List *) linitial(gsets)), list_length((List *) linitial(gsets)),
new_grpColIdx, new_grpColIdx,
extract_grouping_ops(groupClause), extract_grouping_ops(groupClause),
...@@ -1802,9 +1796,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path) ...@@ -1802,9 +1796,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
plan = make_agg(build_path_tlist(root, &best_path->path), plan = make_agg(build_path_tlist(root, &best_path->path),
best_path->qual, best_path->qual,
(numGroupCols > 0) ? AGG_SORTED : AGG_PLAIN, (numGroupCols > 0) ? AGG_SORTED : AGG_PLAIN,
false, AGGSPLIT_SIMPLE,
true,
false,
numGroupCols, numGroupCols,
top_grpColIdx, top_grpColIdx,
extract_grouping_ops(groupClause), extract_grouping_ops(groupClause),
...@@ -5652,8 +5644,7 @@ materialize_finished_plan(Plan *subplan) ...@@ -5652,8 +5644,7 @@ materialize_finished_plan(Plan *subplan)
Agg * Agg *
make_agg(List *tlist, List *qual, make_agg(List *tlist, List *qual,
AggStrategy aggstrategy, AggStrategy aggstrategy, AggSplit aggsplit,
bool combineStates, bool finalizeAggs, bool serialStates,
int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators,
List *groupingSets, List *chain, List *groupingSets, List *chain,
double dNumGroups, Plan *lefttree) double dNumGroups, Plan *lefttree)
...@@ -5666,9 +5657,7 @@ make_agg(List *tlist, List *qual, ...@@ -5666,9 +5657,7 @@ make_agg(List *tlist, List *qual,
numGroups = (long) Min(dNumGroups, (double) LONG_MAX); numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
node->aggstrategy = aggstrategy; node->aggstrategy = aggstrategy;
node->combineStates = combineStates; node->aggsplit = aggsplit;
node->finalizeAggs = finalizeAggs;
node->serialStates = serialStates;
node->numCols = numGroupCols; node->numCols = numGroupCols;
node->grpColIdx = grpColIdx; node->grpColIdx = grpColIdx;
node->grpOperators = grpOperators; node->grpOperators = grpOperators;
......
...@@ -3391,10 +3391,10 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3391,10 +3391,10 @@ create_grouping_paths(PlannerInfo *root,
MemSet(&agg_costs, 0, sizeof(AggClauseCosts)); MemSet(&agg_costs, 0, sizeof(AggClauseCosts));
if (parse->hasAggs) if (parse->hasAggs)
{ {
count_agg_clauses(root, (Node *) target->exprs, &agg_costs, true, get_agg_clause_costs(root, (Node *) target->exprs, AGGSPLIT_SIMPLE,
false, false); &agg_costs);
count_agg_clauses(root, parse->havingQual, &agg_costs, true, false, get_agg_clause_costs(root, parse->havingQual, AGGSPLIT_SIMPLE,
false); &agg_costs);
} }
/* /*
...@@ -3480,14 +3480,17 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3480,14 +3480,17 @@ create_grouping_paths(PlannerInfo *root,
if (parse->hasAggs) if (parse->hasAggs)
{ {
/* partial phase */ /* partial phase */
count_agg_clauses(root, (Node *) partial_grouping_target->exprs, get_agg_clause_costs(root, (Node *) partial_grouping_target->exprs,
&agg_partial_costs, false, false, true); AGGSPLIT_INITIAL_SERIAL,
&agg_partial_costs);
/* final phase */ /* final phase */
count_agg_clauses(root, (Node *) target->exprs, &agg_final_costs, get_agg_clause_costs(root, (Node *) target->exprs,
true, true, true); AGGSPLIT_FINAL_DESERIAL,
count_agg_clauses(root, parse->havingQual, &agg_final_costs, true, &agg_final_costs);
true, true); get_agg_clause_costs(root, parse->havingQual,
AGGSPLIT_FINAL_DESERIAL,
&agg_final_costs);
} }
if (can_sort) if (can_sort)
...@@ -3523,13 +3526,11 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3523,13 +3526,11 @@ create_grouping_paths(PlannerInfo *root,
path, path,
partial_grouping_target, partial_grouping_target,
parse->groupClause ? AGG_SORTED : AGG_PLAIN, parse->groupClause ? AGG_SORTED : AGG_PLAIN,
AGGSPLIT_INITIAL_SERIAL,
parse->groupClause, parse->groupClause,
NIL, NIL,
&agg_partial_costs, &agg_partial_costs,
dNumPartialGroups, dNumPartialGroups));
false,
false,
true));
else else
add_partial_path(grouped_rel, (Path *) add_partial_path(grouped_rel, (Path *)
create_group_path(root, create_group_path(root,
...@@ -3565,13 +3566,11 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3565,13 +3566,11 @@ create_grouping_paths(PlannerInfo *root,
cheapest_partial_path, cheapest_partial_path,
partial_grouping_target, partial_grouping_target,
AGG_HASHED, AGG_HASHED,
AGGSPLIT_INITIAL_SERIAL,
parse->groupClause, parse->groupClause,
NIL, NIL,
&agg_partial_costs, &agg_partial_costs,
dNumPartialGroups, dNumPartialGroups));
false,
false,
true));
} }
} }
} }
...@@ -3630,13 +3629,11 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3630,13 +3629,11 @@ create_grouping_paths(PlannerInfo *root,
path, path,
target, target,
parse->groupClause ? AGG_SORTED : AGG_PLAIN, parse->groupClause ? AGG_SORTED : AGG_PLAIN,
AGGSPLIT_SIMPLE,
parse->groupClause, parse->groupClause,
(List *) parse->havingQual, (List *) parse->havingQual,
&agg_costs, &agg_costs,
dNumGroups, dNumGroups));
false,
true,
false));
} }
else if (parse->groupClause) else if (parse->groupClause)
{ {
...@@ -3697,13 +3694,11 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3697,13 +3694,11 @@ create_grouping_paths(PlannerInfo *root,
path, path,
target, target,
parse->groupClause ? AGG_SORTED : AGG_PLAIN, parse->groupClause ? AGG_SORTED : AGG_PLAIN,
AGGSPLIT_FINAL_DESERIAL,
parse->groupClause, parse->groupClause,
(List *) parse->havingQual, (List *) parse->havingQual,
&agg_final_costs, &agg_final_costs,
dNumGroups, dNumGroups));
true,
true,
true));
else else
add_path(grouped_rel, (Path *) add_path(grouped_rel, (Path *)
create_group_path(root, create_group_path(root,
...@@ -3740,13 +3735,11 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3740,13 +3735,11 @@ create_grouping_paths(PlannerInfo *root,
cheapest_path, cheapest_path,
target, target,
AGG_HASHED, AGG_HASHED,
AGGSPLIT_SIMPLE,
parse->groupClause, parse->groupClause,
(List *) parse->havingQual, (List *) parse->havingQual,
&agg_costs, &agg_costs,
dNumGroups, dNumGroups));
false,
true,
false));
} }
/* /*
...@@ -3779,13 +3772,11 @@ create_grouping_paths(PlannerInfo *root, ...@@ -3779,13 +3772,11 @@ create_grouping_paths(PlannerInfo *root,
path, path,
target, target,
AGG_HASHED, AGG_HASHED,
AGGSPLIT_FINAL_DESERIAL,
parse->groupClause, parse->groupClause,
(List *) parse->havingQual, (List *) parse->havingQual,
&agg_final_costs, &agg_final_costs,
dNumGroups, dNumGroups));
true,
true,
true));
} }
} }
} }
...@@ -4123,13 +4114,11 @@ create_distinct_paths(PlannerInfo *root, ...@@ -4123,13 +4114,11 @@ create_distinct_paths(PlannerInfo *root,
cheapest_input_path, cheapest_input_path,
cheapest_input_path->pathtarget, cheapest_input_path->pathtarget,
AGG_HASHED, AGG_HASHED,
AGGSPLIT_SIMPLE,
parse->distinctClause, parse->distinctClause,
NIL, NIL,
NULL, NULL,
numDistinctRows, numDistinctRows));
false,
true,
false));
} }
/* Give a helpful error if we failed to find any implementation */ /* Give a helpful error if we failed to find any implementation */
...@@ -4414,8 +4403,8 @@ make_partial_grouping_target(PlannerInfo *root, PathTarget *grouping_target) ...@@ -4414,8 +4403,8 @@ make_partial_grouping_target(PlannerInfo *root, PathTarget *grouping_target)
newaggref = makeNode(Aggref); newaggref = makeNode(Aggref);
memcpy(newaggref, aggref, sizeof(Aggref)); memcpy(newaggref, aggref, sizeof(Aggref));
/* XXX assume serialization required */ /* For now, assume serialization is required */
mark_partial_aggref(newaggref, true); mark_partial_aggref(newaggref, AGGSPLIT_INITIAL_SERIAL);
lfirst(lc) = newaggref; lfirst(lc) = newaggref;
} }
...@@ -4431,27 +4420,33 @@ make_partial_grouping_target(PlannerInfo *root, PathTarget *grouping_target) ...@@ -4431,27 +4420,33 @@ make_partial_grouping_target(PlannerInfo *root, PathTarget *grouping_target)
/* /*
* mark_partial_aggref * mark_partial_aggref
* Adjust an Aggref to make it represent the output of partial aggregation. * Adjust an Aggref to make it represent a partial-aggregation step.
* *
* The Aggref node is modified in-place; caller must do any copying required. * The Aggref node is modified in-place; caller must do any copying required.
*/ */
void void
mark_partial_aggref(Aggref *agg, bool serialize) mark_partial_aggref(Aggref *agg, AggSplit aggsplit)
{ {
/* aggtranstype should be computed by this point */ /* aggtranstype should be computed by this point */
Assert(OidIsValid(agg->aggtranstype)); Assert(OidIsValid(agg->aggtranstype));
/* ... but aggsplit should still be as the parser left it */
Assert(agg->aggsplit == AGGSPLIT_SIMPLE);
/* Mark the Aggref with the intended partial-aggregation mode */
agg->aggsplit = aggsplit;
/* /*
* Normally, a partial aggregate returns the aggregate's transition type; * Adjust result type if needed. Normally, a partial aggregate returns
* but if that's INTERNAL and we're serializing, it returns BYTEA instead. * the aggregate's transition type; but if that's INTERNAL and we're
* serializing, it returns BYTEA instead.
*/ */
if (agg->aggtranstype == INTERNALOID && serialize) if (DO_AGGSPLIT_SKIPFINAL(aggsplit))
agg->aggoutputtype = BYTEAOID; {
else if (agg->aggtranstype == INTERNALOID && DO_AGGSPLIT_SERIALIZE(aggsplit))
agg->aggoutputtype = agg->aggtranstype; agg->aggtype = BYTEAOID;
else
/* flag it as partial */ agg->aggtype = agg->aggtranstype;
agg->aggpartial = true; }
} }
/* /*
......
...@@ -679,7 +679,7 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) ...@@ -679,7 +679,7 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
* partial-aggregate subexpressions that will be available * partial-aggregate subexpressions that will be available
* from the child plan node. * from the child plan node.
*/ */
if (agg->combineStates) if (DO_AGGSPLIT_COMBINE(agg->aggsplit))
{ {
plan->targetlist = (List *) plan->targetlist = (List *)
convert_combining_aggrefs((Node *) plan->targetlist, convert_combining_aggrefs((Node *) plan->targetlist,
...@@ -1772,16 +1772,16 @@ convert_combining_aggrefs(Node *node, void *context) ...@@ -1772,16 +1772,16 @@ convert_combining_aggrefs(Node *node, void *context)
/* /*
* Now, set up child_agg to represent the first phase of partial * Now, set up child_agg to represent the first phase of partial
* aggregation. XXX assume serialization required. * aggregation. For now, assume serialization is required.
*/ */
mark_partial_aggref(child_agg, true); mark_partial_aggref(child_agg, AGGSPLIT_INITIAL_SERIAL);
/* /*
* And set up parent_agg to represent the second phase. * And set up parent_agg to represent the second phase.
*/ */
parent_agg->args = list_make1(makeTargetEntry((Expr *) child_agg, parent_agg->args = list_make1(makeTargetEntry((Expr *) child_agg,
1, NULL, false)); 1, NULL, false));
parent_agg->aggcombine = true; mark_partial_aggref(parent_agg, AGGSPLIT_FINAL_DESERIAL);
return (Node *) parent_agg; return (Node *) parent_agg;
} }
......
...@@ -861,13 +861,11 @@ make_union_unique(SetOperationStmt *op, Path *path, List *tlist, ...@@ -861,13 +861,11 @@ make_union_unique(SetOperationStmt *op, Path *path, List *tlist,
path, path,
create_pathtarget(root, tlist), create_pathtarget(root, tlist),
AGG_HASHED, AGG_HASHED,
AGGSPLIT_SIMPLE,
groupList, groupList,
NIL, NIL,
NULL, NULL,
dNumGroups, dNumGroups);
false,
true,
false);
} }
else else
{ {
......
...@@ -60,11 +60,9 @@ typedef struct ...@@ -60,11 +60,9 @@ typedef struct
typedef struct typedef struct
{ {
PlannerInfo *root; PlannerInfo *root;
AggSplit aggsplit;
AggClauseCosts *costs; AggClauseCosts *costs;
bool finalizeAggs; } get_agg_clause_costs_context;
bool combineStates;
bool serialStates;
} count_agg_clauses_context;
typedef struct typedef struct
{ {
...@@ -103,8 +101,8 @@ typedef struct ...@@ -103,8 +101,8 @@ typedef struct
static bool aggregates_allow_partial_walker(Node *node, static bool aggregates_allow_partial_walker(Node *node,
partial_agg_context *context); partial_agg_context *context);
static bool contain_agg_clause_walker(Node *node, void *context); static bool contain_agg_clause_walker(Node *node, void *context);
static bool count_agg_clauses_walker(Node *node, static bool get_agg_clause_costs_walker(Node *node,
count_agg_clauses_context *context); get_agg_clause_costs_context *context);
static bool find_window_functions_walker(Node *node, WindowFuncLists *lists); static bool find_window_functions_walker(Node *node, WindowFuncLists *lists);
static bool expression_returns_set_rows_walker(Node *node, double *count); static bool expression_returns_set_rows_walker(Node *node, double *count);
static bool contain_subplans_walker(Node *node, void *context); static bool contain_subplans_walker(Node *node, void *context);
...@@ -519,44 +517,43 @@ contain_agg_clause_walker(Node *node, void *context) ...@@ -519,44 +517,43 @@ contain_agg_clause_walker(Node *node, void *context)
} }
/* /*
* count_agg_clauses * get_agg_clause_costs
* Recursively count the Aggref nodes in an expression tree, and * Recursively find the Aggref nodes in an expression tree, and
* accumulate other information about them too. * accumulate cost information about them.
* *
* Note: this also checks for nested aggregates, which are an error. * 'aggsplit' tells us the expected partial-aggregation mode, which affects
* the cost estimates.
* *
* We not only count the nodes, but estimate their execution costs, and * NOTE that the counts/costs are ADDED to those already in *costs ... so
* attempt to estimate the total space needed for their transition state * the caller is responsible for zeroing the struct initially.
* values if all are evaluated in parallel (as would be done in a HashAgg *
* plan). See AggClauseCosts for the exact set of statistics collected. * We count the nodes, estimate their execution costs, and estimate the total
* space needed for their transition state values if all are evaluated in
* parallel (as would be done in a HashAgg plan). See AggClauseCosts for
* the exact set of statistics collected.
* *
* In addition, we mark Aggref nodes with the correct aggtranstype, so * In addition, we mark Aggref nodes with the correct aggtranstype, so
* that that doesn't need to be done repeatedly. (That makes this function's * that that doesn't need to be done repeatedly. (That makes this function's
* name a bit of a misnomer.) * name a bit of a misnomer.)
* *
* NOTE that the counts/costs are ADDED to those already in *costs ... so
* the caller is responsible for zeroing the struct initially.
*
* This does not descend into subqueries, and so should be used only after * This does not descend into subqueries, and so should be used only after
* reduction of sublinks to subplans, or in contexts where it's known there * reduction of sublinks to subplans, or in contexts where it's known there
* are no subqueries. There mustn't be outer-aggregate references either. * are no subqueries. There mustn't be outer-aggregate references either.
*/ */
void void
count_agg_clauses(PlannerInfo *root, Node *clause, AggClauseCosts *costs, get_agg_clause_costs(PlannerInfo *root, Node *clause, AggSplit aggsplit,
bool finalizeAggs, bool combineStates, bool serialStates) AggClauseCosts *costs)
{ {
count_agg_clauses_context context; get_agg_clause_costs_context context;
context.root = root; context.root = root;
context.aggsplit = aggsplit;
context.costs = costs; context.costs = costs;
context.finalizeAggs = finalizeAggs; (void) get_agg_clause_costs_walker(clause, &context);
context.combineStates = combineStates;
context.serialStates = serialStates;
(void) count_agg_clauses_walker(clause, &context);
} }
static bool static bool
count_agg_clauses_walker(Node *node, count_agg_clauses_context *context) get_agg_clause_costs_walker(Node *node, get_agg_clause_costs_context *context)
{ {
if (node == NULL) if (node == NULL)
return false; return false;
...@@ -628,34 +625,28 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context) ...@@ -628,34 +625,28 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
* Add the appropriate component function execution costs to * Add the appropriate component function execution costs to
* appropriate totals. * appropriate totals.
*/ */
if (context->combineStates) if (DO_AGGSPLIT_COMBINE(context->aggsplit))
{ {
/* charge for combining previously aggregated states */ /* charge for combining previously aggregated states */
costs->transCost.per_tuple += get_func_cost(aggcombinefn) * cpu_operator_cost; costs->transCost.per_tuple += get_func_cost(aggcombinefn) * cpu_operator_cost;
/* charge for deserialization, when appropriate */
if (context->serialStates && OidIsValid(aggdeserialfn))
costs->transCost.per_tuple += get_func_cost(aggdeserialfn) * cpu_operator_cost;
} }
else else
costs->transCost.per_tuple += get_func_cost(aggtransfn) * cpu_operator_cost; costs->transCost.per_tuple += get_func_cost(aggtransfn) * cpu_operator_cost;
if (DO_AGGSPLIT_DESERIALIZE(context->aggsplit) &&
if (context->finalizeAggs) OidIsValid(aggdeserialfn))
{ costs->transCost.per_tuple += get_func_cost(aggdeserialfn) * cpu_operator_cost;
if (OidIsValid(aggfinalfn)) if (DO_AGGSPLIT_SERIALIZE(context->aggsplit) &&
costs->finalCost += get_func_cost(aggfinalfn) * cpu_operator_cost; OidIsValid(aggserialfn))
} costs->finalCost += get_func_cost(aggserialfn) * cpu_operator_cost;
else if (context->serialStates) if (!DO_AGGSPLIT_SKIPFINAL(context->aggsplit) &&
{ OidIsValid(aggfinalfn))
if (OidIsValid(aggserialfn)) costs->finalCost += get_func_cost(aggfinalfn) * cpu_operator_cost;
costs->finalCost += get_func_cost(aggserialfn) * cpu_operator_cost;
}
/* /*
* Some costs will already have been incurred by the initial aggregate * These costs are incurred only by the initial aggregate node, so we
* node, so we mustn't include these again. * mustn't include them again at upper levels.
*/ */
if (!context->combineStates) if (!DO_AGGSPLIT_COMBINE(context->aggsplit))
{ {
/* add the input expressions' cost to per-input-row costs */ /* add the input expressions' cost to per-input-row costs */
cost_qual_eval_node(&argcosts, (Node *) aggref->args, context->root); cost_qual_eval_node(&argcosts, (Node *) aggref->args, context->root);
...@@ -747,14 +738,12 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context) ...@@ -747,14 +738,12 @@ count_agg_clauses_walker(Node *node, count_agg_clauses_context *context)
/* /*
* We assume that the parser checked that there are no aggregates (of * We assume that the parser checked that there are no aggregates (of
* this level anyway) in the aggregated arguments, direct arguments, * this level anyway) in the aggregated arguments, direct arguments,
* or filter clause. Hence, we need not recurse into any of them. (If * or filter clause. Hence, we need not recurse into any of them.
* either the parser or the planner screws up on this point, the
* executor will still catch it; see ExecInitExpr.)
*/ */
return false; return false;
} }
Assert(!IsA(node, SubLink)); Assert(!IsA(node, SubLink));
return expression_tree_walker(node, count_agg_clauses_walker, return expression_tree_walker(node, get_agg_clause_costs_walker,
(void *) context); (void *) context);
} }
......
...@@ -2466,12 +2466,11 @@ create_upper_unique_path(PlannerInfo *root, ...@@ -2466,12 +2466,11 @@ create_upper_unique_path(PlannerInfo *root,
* 'subpath' is the path representing the source of data * 'subpath' is the path representing the source of data
* 'target' is the PathTarget to be computed * 'target' is the PathTarget to be computed
* 'aggstrategy' is the Agg node's basic implementation strategy * 'aggstrategy' is the Agg node's basic implementation strategy
* 'aggsplit' is the Agg node's aggregate-splitting mode
* 'groupClause' is a list of SortGroupClause's representing the grouping * 'groupClause' is a list of SortGroupClause's representing the grouping
* 'qual' is the HAVING quals if any * 'qual' is the HAVING quals if any
* 'aggcosts' contains cost info about the aggregate functions to be computed * 'aggcosts' contains cost info about the aggregate functions to be computed
* 'numGroups' is the estimated number of groups (1 if not grouping) * 'numGroups' is the estimated number of groups (1 if not grouping)
* 'combineStates' is set to true if the Agg node should combine agg states
* 'finalizeAggs' is set to false if the Agg node should not call the finalfn
*/ */
AggPath * AggPath *
create_agg_path(PlannerInfo *root, create_agg_path(PlannerInfo *root,
...@@ -2479,13 +2478,11 @@ create_agg_path(PlannerInfo *root, ...@@ -2479,13 +2478,11 @@ create_agg_path(PlannerInfo *root,
Path *subpath, Path *subpath,
PathTarget *target, PathTarget *target,
AggStrategy aggstrategy, AggStrategy aggstrategy,
AggSplit aggsplit,
List *groupClause, List *groupClause,
List *qual, List *qual,
const AggClauseCosts *aggcosts, const AggClauseCosts *aggcosts,
double numGroups, double numGroups)
bool combineStates,
bool finalizeAggs,
bool serialStates)
{ {
AggPath *pathnode = makeNode(AggPath); AggPath *pathnode = makeNode(AggPath);
...@@ -2505,12 +2502,10 @@ create_agg_path(PlannerInfo *root, ...@@ -2505,12 +2502,10 @@ create_agg_path(PlannerInfo *root,
pathnode->subpath = subpath; pathnode->subpath = subpath;
pathnode->aggstrategy = aggstrategy; pathnode->aggstrategy = aggstrategy;
pathnode->aggsplit = aggsplit;
pathnode->numGroups = numGroups; pathnode->numGroups = numGroups;
pathnode->groupClause = groupClause; pathnode->groupClause = groupClause;
pathnode->qual = qual; pathnode->qual = qual;
pathnode->finalizeAggs = finalizeAggs;
pathnode->combineStates = combineStates;
pathnode->serialStates = serialStates;
cost_agg(&pathnode->path, root, cost_agg(&pathnode->path, root,
aggstrategy, aggcosts, aggstrategy, aggcosts,
......
...@@ -647,8 +647,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, ...@@ -647,8 +647,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
Aggref *aggref = makeNode(Aggref); Aggref *aggref = makeNode(Aggref);
aggref->aggfnoid = funcid; aggref->aggfnoid = funcid;
/* default the outputtype to be the same as aggtype */ aggref->aggtype = rettype;
aggref->aggtype = aggref->aggoutputtype = rettype;
/* aggcollid and inputcollid will be set by parse_collate.c */ /* aggcollid and inputcollid will be set by parse_collate.c */
aggref->aggtranstype = InvalidOid; /* will be set by planner */ aggref->aggtranstype = InvalidOid; /* will be set by planner */
/* aggargtypes will be set by transformAggregateCall */ /* aggargtypes will be set by transformAggregateCall */
...@@ -657,10 +656,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, ...@@ -657,10 +656,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
aggref->aggfilter = agg_filter; aggref->aggfilter = agg_filter;
aggref->aggstar = agg_star; aggref->aggstar = agg_star;
aggref->aggvariadic = func_variadic; aggref->aggvariadic = func_variadic;
/* at this point, the Aggref is never partial or combining */
aggref->aggcombine = aggref->aggpartial = false;
aggref->aggkind = aggkind; aggref->aggkind = aggkind;
/* agglevelsup will be set by transformAggregateCall */ /* agglevelsup will be set by transformAggregateCall */
aggref->aggsplit = AGGSPLIT_SIMPLE; /* planner might change this */
aggref->location = location; aggref->location = location;
/* /*
......
...@@ -8285,7 +8285,7 @@ get_agg_expr(Aggref *aggref, deparse_context *context, ...@@ -8285,7 +8285,7 @@ get_agg_expr(Aggref *aggref, deparse_context *context,
* one element, which will point to a partial Aggref that supplies us with * one element, which will point to a partial Aggref that supplies us with
* transition states to combine. * transition states to combine.
*/ */
if (aggref->aggcombine) if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
{ {
TargetEntry *tle = linitial(aggref->args); TargetEntry *tle = linitial(aggref->args);
...@@ -8296,8 +8296,11 @@ get_agg_expr(Aggref *aggref, deparse_context *context, ...@@ -8296,8 +8296,11 @@ get_agg_expr(Aggref *aggref, deparse_context *context,
return; return;
} }
/* Mark as PARTIAL, if appropriate. */ /*
if (original_aggref->aggpartial) * Mark as PARTIAL, if appropriate. We look to the original aggref so as
* to avoid printing this when recursing from the code just above.
*/
if (DO_AGGSPLIT_SKIPFINAL(original_aggref->aggsplit))
appendStringInfoString(buf, "PARTIAL "); appendStringInfoString(buf, "PARTIAL ");
/* Extract the argument types as seen by the parser */ /* Extract the argument types as seen by the parser */
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201606221 #define CATALOG_VERSION_NO 201606261
#endif #endif
...@@ -1823,6 +1823,7 @@ typedef struct AggState ...@@ -1823,6 +1823,7 @@ typedef struct AggState
List *aggs; /* all Aggref nodes in targetlist & quals */ List *aggs; /* all Aggref nodes in targetlist & quals */
int numaggs; /* length of list (could be zero!) */ int numaggs; /* length of list (could be zero!) */
int numtrans; /* number of pertrans items */ int numtrans; /* number of pertrans items */
AggSplit aggsplit; /* agg-splitting mode, see nodes.h */
AggStatePerPhase phase; /* pointer to current phase data */ AggStatePerPhase phase; /* pointer to current phase data */
int numphases; /* number of phases */ int numphases; /* number of phases */
int current_phase; /* current phase number */ int current_phase; /* current phase number */
...@@ -1834,9 +1835,6 @@ typedef struct AggState ...@@ -1834,9 +1835,6 @@ typedef struct AggState
AggStatePerTrans curpertrans; /* currently active trans state */ AggStatePerTrans curpertrans; /* currently active trans state */
bool input_done; /* indicates end of input */ bool input_done; /* indicates end of input */
bool agg_done; /* indicates completion of Agg scan */ bool agg_done; /* indicates completion of Agg scan */
bool combineStates; /* input tuples contain transition states */
bool finalizeAggs; /* should we call the finalfn on agg states? */
bool serialStates; /* should agg states be (de)serialized? */
int projected_set; /* The last projected grouping set */ int projected_set; /* The last projected grouping set */
int current_set; /* The current grouping set being evaluated */ int current_set; /* The current grouping set being evaluated */
Bitmapset *grouped_cols; /* grouped cols in current projection */ Bitmapset *grouped_cols; /* grouped cols in current projection */
......
...@@ -694,6 +694,36 @@ typedef enum AggStrategy ...@@ -694,6 +694,36 @@ typedef enum AggStrategy
AGG_HASHED /* grouped agg, use internal hashtable */ AGG_HASHED /* grouped agg, use internal hashtable */
} AggStrategy; } AggStrategy;
/*
* AggSplit -
* splitting (partial aggregation) modes for Agg plan nodes
*
* This is needed in both plannodes.h and relation.h, so put it here...
*/
/* Primitive options supported by nodeAgg.c: */
#define AGGSPLITOP_COMBINE 0x01 /* substitute combinefn for transfn */
#define AGGSPLITOP_SKIPFINAL 0x02 /* skip finalfn, return state as-is */
#define AGGSPLITOP_SERIALIZE 0x04 /* apply serializefn to output */
#define AGGSPLITOP_DESERIALIZE 0x08 /* apply deserializefn to input */
/* Supported operating modes (i.e., useful combinations of these options): */
typedef enum AggSplit
{
/* Basic, non-split aggregation: */
AGGSPLIT_SIMPLE = 0,
/* Initial phase of partial aggregation, with serialization: */
AGGSPLIT_INITIAL_SERIAL = AGGSPLITOP_SKIPFINAL | AGGSPLITOP_SERIALIZE,
/* Final phase of partial aggregation, with deserialization: */
AGGSPLIT_FINAL_DESERIAL = AGGSPLITOP_COMBINE | AGGSPLITOP_DESERIALIZE
} AggSplit;
/* Test whether an AggSplit value selects each primitive option: */
#define DO_AGGSPLIT_COMBINE(as) (((as) & AGGSPLITOP_COMBINE) != 0)
#define DO_AGGSPLIT_SKIPFINAL(as) (((as) & AGGSPLITOP_SKIPFINAL) != 0)
#define DO_AGGSPLIT_SERIALIZE(as) (((as) & AGGSPLITOP_SERIALIZE) != 0)
#define DO_AGGSPLIT_DESERIALIZE(as) (((as) & AGGSPLITOP_DESERIALIZE) != 0)
/* /*
* SetOpCmd and SetOpStrategy - * SetOpCmd and SetOpStrategy -
* overall semantics and execution strategies for SetOp plan nodes * overall semantics and execution strategies for SetOp plan nodes
......
...@@ -711,9 +711,7 @@ typedef struct Agg ...@@ -711,9 +711,7 @@ typedef struct Agg
{ {
Plan plan; Plan plan;
AggStrategy aggstrategy; /* basic strategy, see nodes.h */ AggStrategy aggstrategy; /* basic strategy, see nodes.h */
bool combineStates; /* input tuples contain transition states */ AggSplit aggsplit; /* agg-splitting mode, see nodes.h */
bool finalizeAggs; /* should we call the finalfn on agg states? */
bool serialStates; /* should agg states be (de)serialized? */
int numCols; /* number of grouping columns */ int numCols; /* number of grouping columns */
AttrNumber *grpColIdx; /* their indexes in the target list */ AttrNumber *grpColIdx; /* their indexes in the target list */
Oid *grpOperators; /* equality operators to compare with */ Oid *grpOperators; /* equality operators to compare with */
......
...@@ -266,22 +266,18 @@ typedef struct Param ...@@ -266,22 +266,18 @@ typedef struct Param
* replaced with a single argument representing the partial-aggregate * replaced with a single argument representing the partial-aggregate
* transition values. * transition values.
* *
* XXX need more documentation about partial aggregation here * aggsplit indicates the expected partial-aggregation mode for the Aggref's
* * parent plan node. It's always set to AGGSPLIT_SIMPLE in the parser, but
* 'aggtype' and 'aggoutputtype' are the same except when we're performing * the planner might change it to something else. We use this mainly as
* partal aggregation; in that case, we output transition states. Nothing * a crosscheck that the Aggrefs match the plan; but note that when aggsplit
* interesting happens in the Aggref itself, but we must set the output data * indicates a non-final mode, aggtype reflects the transition data type
* type to whatever type is used for transition values. * not the SQL-level output type of the aggregate.
*
* Note: If you are adding fields here you may also need to add a comparison
* in search_indexed_tlist_for_partial_aggref()
*/ */
typedef struct Aggref typedef struct Aggref
{ {
Expr xpr; Expr xpr;
Oid aggfnoid; /* pg_proc Oid of the aggregate */ Oid aggfnoid; /* pg_proc Oid of the aggregate */
Oid aggtype; /* type Oid of final result of the aggregate */ Oid aggtype; /* type Oid of result of the aggregate */
Oid aggoutputtype; /* type Oid of result of this aggregate */
Oid aggcollid; /* OID of collation of result */ Oid aggcollid; /* OID of collation of result */
Oid inputcollid; /* OID of collation that function should use */ Oid inputcollid; /* OID of collation that function should use */
Oid aggtranstype; /* type Oid of aggregate's transition value */ Oid aggtranstype; /* type Oid of aggregate's transition value */
...@@ -294,10 +290,9 @@ typedef struct Aggref ...@@ -294,10 +290,9 @@ typedef struct Aggref
bool aggstar; /* TRUE if argument list was really '*' */ bool aggstar; /* TRUE if argument list was really '*' */
bool aggvariadic; /* true if variadic arguments have been bool aggvariadic; /* true if variadic arguments have been
* combined into an array last argument */ * combined into an array last argument */
bool aggcombine; /* combining agg; input is a transvalue */
bool aggpartial; /* partial agg; output is a transvalue */
char aggkind; /* aggregate kind (see pg_aggregate.h) */ char aggkind; /* aggregate kind (see pg_aggregate.h) */
Index agglevelsup; /* > 0 if agg belongs to outer query */ Index agglevelsup; /* > 0 if agg belongs to outer query */
AggSplit aggsplit; /* expected agg-splitting mode of parent Agg */
int location; /* token location, or -1 if unknown */ int location; /* token location, or -1 if unknown */
} Aggref; } Aggref;
......
...@@ -1347,12 +1347,10 @@ typedef struct AggPath ...@@ -1347,12 +1347,10 @@ typedef struct AggPath
Path path; Path path;
Path *subpath; /* path representing input source */ Path *subpath; /* path representing input source */
AggStrategy aggstrategy; /* basic strategy, see nodes.h */ AggStrategy aggstrategy; /* basic strategy, see nodes.h */
AggSplit aggsplit; /* agg-splitting mode, see nodes.h */
double numGroups; /* estimated number of groups in input */ double numGroups; /* estimated number of groups in input */
List *groupClause; /* a list of SortGroupClause's */ List *groupClause; /* a list of SortGroupClause's */
List *qual; /* quals (HAVING quals), if any */ List *qual; /* quals (HAVING quals), if any */
bool combineStates; /* input is partially aggregated agg states */
bool finalizeAggs; /* should the executor call the finalfn? */
bool serialStates; /* should agg states be (de)serialized? */
} AggPath; } AggPath;
/* /*
......
...@@ -67,9 +67,8 @@ extern List *make_ands_implicit(Expr *clause); ...@@ -67,9 +67,8 @@ extern List *make_ands_implicit(Expr *clause);
extern PartialAggType aggregates_allow_partial(Node *clause); extern PartialAggType aggregates_allow_partial(Node *clause);
extern bool contain_agg_clause(Node *clause); extern bool contain_agg_clause(Node *clause);
extern void count_agg_clauses(PlannerInfo *root, Node *clause, extern void get_agg_clause_costs(PlannerInfo *root, Node *clause,
AggClauseCosts *costs, bool finalizeAggs, AggSplit aggsplit, AggClauseCosts *costs);
bool combineStates, bool serialStates);
extern bool contain_window_function(Node *clause); extern bool contain_window_function(Node *clause);
extern WindowFuncLists *find_window_functions(Node *clause, Index maxWinRef); extern WindowFuncLists *find_window_functions(Node *clause, Index maxWinRef);
......
...@@ -166,13 +166,11 @@ extern AggPath *create_agg_path(PlannerInfo *root, ...@@ -166,13 +166,11 @@ extern AggPath *create_agg_path(PlannerInfo *root,
Path *subpath, Path *subpath,
PathTarget *target, PathTarget *target,
AggStrategy aggstrategy, AggStrategy aggstrategy,
AggSplit aggsplit,
List *groupClause, List *groupClause,
List *qual, List *qual,
const AggClauseCosts *aggcosts, const AggClauseCosts *aggcosts,
double numGroups, double numGroups);
bool combineStates,
bool finalizeAggs,
bool serialStates);
extern GroupingSetsPath *create_groupingsets_path(PlannerInfo *root, extern GroupingSetsPath *create_groupingsets_path(PlannerInfo *root,
RelOptInfo *rel, RelOptInfo *rel,
Path *subpath, Path *subpath,
......
...@@ -58,8 +58,8 @@ extern bool is_projection_capable_plan(Plan *plan); ...@@ -58,8 +58,8 @@ extern bool is_projection_capable_plan(Plan *plan);
/* External use of these functions is deprecated: */ /* External use of these functions is deprecated: */
extern Sort *make_sort_from_sortclauses(List *sortcls, Plan *lefttree); extern Sort *make_sort_from_sortclauses(List *sortcls, Plan *lefttree);
extern Agg *make_agg(List *tlist, List *qual, AggStrategy aggstrategy, extern Agg *make_agg(List *tlist, List *qual,
bool combineStates, bool finalizeAggs, bool serialStates, AggStrategy aggstrategy, AggSplit aggsplit,
int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators,
List *groupingSets, List *chain, List *groupingSets, List *chain,
double dNumGroups, Plan *lefttree); double dNumGroups, Plan *lefttree);
......
...@@ -46,7 +46,7 @@ extern bool is_dummy_plan(Plan *plan); ...@@ -46,7 +46,7 @@ extern bool is_dummy_plan(Plan *plan);
extern RowMarkType select_rowmark_type(RangeTblEntry *rte, extern RowMarkType select_rowmark_type(RangeTblEntry *rte,
LockClauseStrength strength); LockClauseStrength strength);
extern void mark_partial_aggref(Aggref *agg, bool serialize); extern void mark_partial_aggref(Aggref *agg, AggSplit aggsplit);
extern Path *get_cheapest_fractional_path(RelOptInfo *rel, extern Path *get_cheapest_fractional_path(RelOptInfo *rel,
double tuple_fraction); double tuple_fraction);
......
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