diff options
Diffstat (limited to 'src/backend/optimizer/plan/planagg.c')
-rw-r--r-- | src/backend/optimizer/plan/planagg.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index f0e9c05a452..a761cfdb09b 100644 --- a/src/backend/optimizer/plan/planagg.c +++ b/src/backend/optimizer/plan/planagg.c @@ -416,13 +416,23 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo, * WHERE col IS NOT NULL AND existing-quals * ORDER BY col ASC/DESC * LIMIT 1) + * + * We cheat a bit here by building what is effectively a subplan query + * level without taking the trouble to increment varlevelsup of outer + * references. Therefore we don't increment the subroot's query_level nor + * repoint its parent_root to the parent level. We can get away with that + * because the plan will be an initplan and therefore cannot need any + * parameters from the parent level. But see hackery in make_agg_subplan; + * we might someday need to do this the hard way. *---------- */ subroot = (PlannerInfo *) palloc(sizeof(PlannerInfo)); memcpy(subroot, root, sizeof(PlannerInfo)); subroot->parse = parse = (Query *) copyObject(root->parse); - /* make sure subroot planning won't change root->init_plans contents */ - subroot->init_plans = list_copy(root->init_plans); + /* reset subplan-related stuff */ + subroot->plan_params = NIL; + subroot->outer_params = NULL; + subroot->init_plans = NIL; /* There shouldn't be any OJ or LATERAL info to translate, as yet */ Assert(subroot->join_info_list == NIL); Assert(subroot->lateral_info_list == NIL); @@ -578,23 +588,30 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *mminfo) 0, 1); /* + * We have to do some of the same cleanup that subquery_planner() would + * do, namely cope with params and initplans used within this plan tree. + * + * This is a little bit messy because although we initially created the + * subroot by cloning the outer root, it really is a subplan and needs to + * consider initplans belonging to the outer root as providing available + * parameters. So temporarily change its parent_root pointer. + * (Fortunately, SS_identify_outer_params doesn't care whether the depth + * of parent_root nesting matches query_level.) + */ + subroot->parent_root = root; + SS_identify_outer_params(subroot); + subroot->parent_root = root->parent_root; + + SS_attach_initplans(subroot, plan); + + /* * Convert the plan into an InitPlan, and make a Param for its result. */ mminfo->param = - SS_make_initplan_from_plan(subroot, plan, + SS_make_initplan_from_plan(root, subroot, plan, exprType((Node *) mminfo->target), -1, exprCollation((Node *) mminfo->target)); - - /* - * Make sure the initplan gets into the outer PlannerInfo, along with any - * other initplans generated by the sub-planning run. We had to include - * the outer PlannerInfo's pre-existing initplans into the inner one's - * init_plans list earlier, so make sure we don't put back any duplicate - * entries. - */ - root->init_plans = list_concat_unique_ptr(root->init_plans, - subroot->init_plans); } /* |