diff options
Diffstat (limited to 'src/backend/optimizer/plan/setrefs.c')
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index c63758cb2b7..16e5537f7f9 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -2181,22 +2181,14 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context) if (IsA(node, Aggref)) { Aggref *aggref = (Aggref *) node; + Param *aggparam; /* See if the Aggref should be replaced by a Param */ - if (context->root->minmax_aggs != NIL && - list_length(aggref->args) == 1) + aggparam = find_minmax_agg_replacement_param(context->root, aggref); + if (aggparam != NULL) { - TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args); - ListCell *lc; - - foreach(lc, context->root->minmax_aggs) - { - MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc); - - if (mminfo->aggfnoid == aggref->aggfnoid && - equal(mminfo->target, curTarget->expr)) - return (Node *) copyObject(mminfo->param); - } + /* Make a copy of the Param for paranoia's sake */ + return (Node *) copyObject(aggparam); } /* If no match, just fall through to process it normally */ } @@ -3225,22 +3217,14 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context) if (IsA(node, Aggref)) { Aggref *aggref = (Aggref *) node; + Param *aggparam; /* See if the Aggref should be replaced by a Param */ - if (context->root->minmax_aggs != NIL && - list_length(aggref->args) == 1) + aggparam = find_minmax_agg_replacement_param(context->root, aggref); + if (aggparam != NULL) { - TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args); - ListCell *lc; - - foreach(lc, context->root->minmax_aggs) - { - MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc); - - if (mminfo->aggfnoid == aggref->aggfnoid && - equal(mminfo->target, curTarget->expr)) - return (Node *) copyObject(mminfo->param); - } + /* Make a copy of the Param for paranoia's sake */ + return (Node *) copyObject(aggparam); } /* If no match, just fall through to process it normally */ } @@ -3395,6 +3379,38 @@ set_windowagg_runcondition_references(PlannerInfo *root, return newlist; } +/* + * find_minmax_agg_replacement_param + * If the given Aggref is one that we are optimizing into a subquery + * (cf. planagg.c), then return the Param that should replace it. + * Else return NULL. + * + * This is exported so that SS_finalize_plan can use it before setrefs.c runs. + * Note that it will not find anything until we have built a Plan from a + * MinMaxAggPath, as root->minmax_aggs will never be filled otherwise. + */ +Param * +find_minmax_agg_replacement_param(PlannerInfo *root, Aggref *aggref) +{ + if (root->minmax_aggs != NIL && + list_length(aggref->args) == 1) + { + TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args); + ListCell *lc; + + foreach(lc, root->minmax_aggs) + { + MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc); + + if (mminfo->aggfnoid == aggref->aggfnoid && + equal(mminfo->target, curTarget->expr)) + return mminfo->param; + } + } + return NULL; +} + + /***************************************************************************** * QUERY DEPENDENCY MANAGEMENT *****************************************************************************/ |