1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-31 03:21:24 +03:00

Convert planner's AggInfo and AggTransInfo structs to proper Nodes.

This is mostly just to get outfuncs.c support for them, so that
the agginfos and aggtransinfos lists can be dumped when dumping
the contents of PlannerInfo.

While here, improve some related comments; notably, clean up
obsolete comments left over from when preprocess_minmax_aggregates
had to make its own scan of the query tree.

Discussion: https://postgr.es/m/742479.1658160504@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2022-07-19 12:29:37 -04:00
parent e2f6c307c0
commit d6a3aeb9a3
3 changed files with 45 additions and 33 deletions

View File

@ -137,8 +137,8 @@ preprocess_minmax_aggregates(PlannerInfo *root)
return; return;
/* /*
* Scan the tlist and HAVING qual to find all the aggregates and verify * Examine all the aggregates and verify all are MIN/MAX aggregates. Stop
* all are MIN/MAX aggregates. Stop as soon as we find one that isn't. * as soon as we find one that isn't.
*/ */
aggs_list = NIL; aggs_list = NIL;
if (!can_minmax_aggs(root, &aggs_list)) if (!can_minmax_aggs(root, &aggs_list))
@ -227,24 +227,24 @@ preprocess_minmax_aggregates(PlannerInfo *root)
/* /*
* can_minmax_aggs * can_minmax_aggs
* Walk through all the aggregates in the query, and check * Examine all the aggregates in the query, and check if they are
* if they are all MIN/MAX aggregates. If so, build a list of the * all MIN/MAX aggregates. If so, build a list of MinMaxAggInfo
* distinct aggregate calls in the tree. * nodes for them.
* *
* Returns false if a non-MIN/MAX aggregate is found, true otherwise. * Returns false if a non-MIN/MAX aggregate is found, true otherwise.
*
* This does not descend into subqueries, and so should be used only after
* reduction of sublinks to subplans. There mustn't be outer-aggregate
* references either.
*/ */
static bool static bool
can_minmax_aggs(PlannerInfo *root, List **context) can_minmax_aggs(PlannerInfo *root, List **context)
{ {
ListCell *lc; ListCell *lc;
/*
* This function used to have to scan the query for itself, but now we can
* just thumb through the AggInfo list made by preprocess_aggrefs.
*/
foreach(lc, root->agginfos) foreach(lc, root->agginfos)
{ {
AggInfo *agginfo = (AggInfo *) lfirst(lc); AggInfo *agginfo = lfirst_node(AggInfo, lc);
Aggref *aggref = agginfo->representative_aggref; Aggref *aggref = agginfo->representative_aggref;
Oid aggsortop; Oid aggsortop;
TargetEntry *curTarget; TargetEntry *curTarget;

View File

@ -223,13 +223,13 @@ preprocess_aggref(Aggref *aggref, PlannerInfo *root)
aggno = find_compatible_agg(root, aggref, &same_input_transnos); aggno = find_compatible_agg(root, aggref, &same_input_transnos);
if (aggno != -1) if (aggno != -1)
{ {
AggInfo *agginfo = list_nth(root->agginfos, aggno); AggInfo *agginfo = list_nth_node(AggInfo, root->agginfos, aggno);
transno = agginfo->transno; transno = agginfo->transno;
} }
else else
{ {
AggInfo *agginfo = palloc(sizeof(AggInfo)); AggInfo *agginfo = makeNode(AggInfo);
agginfo->finalfn_oid = aggfinalfn; agginfo->finalfn_oid = aggfinalfn;
agginfo->representative_aggref = aggref; agginfo->representative_aggref = aggref;
@ -266,7 +266,7 @@ preprocess_aggref(Aggref *aggref, PlannerInfo *root)
same_input_transnos); same_input_transnos);
if (transno == -1) if (transno == -1)
{ {
AggTransInfo *transinfo = palloc(sizeof(AggTransInfo)); AggTransInfo *transinfo = makeNode(AggTransInfo);
transinfo->args = aggref->args; transinfo->args = aggref->args;
transinfo->aggfilter = aggref->aggfilter; transinfo->aggfilter = aggref->aggfilter;
@ -381,7 +381,7 @@ find_compatible_agg(PlannerInfo *root, Aggref *newagg,
aggno = -1; aggno = -1;
foreach(lc, root->agginfos) foreach(lc, root->agginfos)
{ {
AggInfo *agginfo = (AggInfo *) lfirst(lc); AggInfo *agginfo = lfirst_node(AggInfo, lc);
Aggref *existingRef; Aggref *existingRef;
aggno++; aggno++;
@ -452,7 +452,9 @@ find_compatible_trans(PlannerInfo *root, Aggref *newagg, bool shareable,
foreach(lc, transnos) foreach(lc, transnos)
{ {
int transno = lfirst_int(lc); int transno = lfirst_int(lc);
AggTransInfo *pertrans = (AggTransInfo *) list_nth(root->aggtransinfos, transno); AggTransInfo *pertrans = list_nth_node(AggTransInfo,
root->aggtransinfos,
transno);
/* /*
* if the transfns or transition state types are not the same then the * if the transfns or transition state types are not the same then the
@ -541,7 +543,7 @@ get_agg_clause_costs(PlannerInfo *root, AggSplit aggsplit, AggClauseCosts *costs
foreach(lc, root->aggtransinfos) foreach(lc, root->aggtransinfos)
{ {
AggTransInfo *transinfo = (AggTransInfo *) lfirst(lc); AggTransInfo *transinfo = lfirst_node(AggTransInfo, lc);
/* /*
* Add the appropriate component function execution costs to * Add the appropriate component function execution costs to
@ -645,7 +647,7 @@ get_agg_clause_costs(PlannerInfo *root, AggSplit aggsplit, AggClauseCosts *costs
foreach(lc, root->agginfos) foreach(lc, root->agginfos)
{ {
AggInfo *agginfo = (AggInfo *) lfirst(lc); AggInfo *agginfo = lfirst_node(AggInfo, lc);
Aggref *aggref = agginfo->representative_aggref; Aggref *aggref = agginfo->representative_aggref;
/* /*

View File

@ -442,15 +442,15 @@ struct PlannerInfo
* Information about aggregates. Filled by preprocess_aggrefs(). * Information about aggregates. Filled by preprocess_aggrefs().
*/ */
/* AggInfo structs */ /* AggInfo structs */
List *agginfos pg_node_attr(read_write_ignore); List *agginfos;
/* AggTransInfo structs */ /* AggTransInfo structs */
List *aggtransinfos pg_node_attr(read_write_ignore); List *aggtransinfos;
/* number w/ DISTINCT/ORDER BY/WITHIN GROUP */ /* number of aggs with DISTINCT/ORDER BY/WITHIN GROUP */
int numOrderedAggs pg_node_attr(read_write_ignore); int numOrderedAggs;
/* does any agg not support partial mode? */ /* does any agg not support partial mode? */
bool hasNonPartialAggs pg_node_attr(read_write_ignore); bool hasNonPartialAggs;
/* is any partial agg non-serializable? */ /* is any partial agg non-serializable? */
bool hasNonSerialAggs pg_node_attr(read_write_ignore); bool hasNonSerialAggs;
/* /*
* These fields are used only when hasRecursion is true: * These fields are used only when hasRecursion is true:
@ -3121,6 +3121,10 @@ typedef struct JoinCostWorkspace
*/ */
typedef struct AggInfo typedef struct AggInfo
{ {
pg_node_attr(no_copy_equal, no_read)
NodeTag type;
/* /*
* Link to an Aggref expr this state value is for. * Link to an Aggref expr this state value is for.
* *
@ -3129,6 +3133,7 @@ typedef struct AggInfo
*/ */
Aggref *representative_aggref; Aggref *representative_aggref;
/* Transition state number for this aggregate */
int transno; int transno;
/* /*
@ -3137,9 +3142,8 @@ typedef struct AggInfo
*/ */
bool shareable; bool shareable;
/* Oid of the final function or InvalidOid */ /* Oid of the final function, or InvalidOid if none */
Oid finalfn_oid; Oid finalfn_oid;
} AggInfo; } AggInfo;
/* /*
@ -3151,34 +3155,40 @@ typedef struct AggInfo
*/ */
typedef struct AggTransInfo typedef struct AggTransInfo
{ {
pg_node_attr(no_copy_equal, no_read)
NodeTag type;
/* Inputs for this transition state */
List *args; List *args;
Expr *aggfilter; Expr *aggfilter;
/* Oid of the state transition function */ /* Oid of the state transition function */
Oid transfn_oid; Oid transfn_oid;
/* Oid of the serialization function or InvalidOid */ /* Oid of the serialization function, or InvalidOid if none */
Oid serialfn_oid; Oid serialfn_oid;
/* Oid of the deserialization function or InvalidOid */ /* Oid of the deserialization function, or InvalidOid if none */
Oid deserialfn_oid; Oid deserialfn_oid;
/* Oid of the combine function or InvalidOid */ /* Oid of the combine function, or InvalidOid if none */
Oid combinefn_oid; Oid combinefn_oid;
/* Oid of state value's datatype */ /* Oid of state value's datatype */
Oid aggtranstype; Oid aggtranstype;
/* Additional data about transtype */
int32 aggtranstypmod; int32 aggtranstypmod;
int transtypeLen; int transtypeLen;
bool transtypeByVal; bool transtypeByVal;
/* Space-consumption estimate */
int32 aggtransspace; int32 aggtransspace;
/* /* Initial value from pg_aggregate entry */
* initial value from pg_aggregate entry Datum initValue pg_node_attr(read_write_ignore);
*/
Datum initValue;
bool initValueIsNull; bool initValueIsNull;
} AggTransInfo; } AggTransInfo;
#endif /* PATHNODES_H */ #endif /* PATHNODES_H */