diff options
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 87 |
1 files changed, 28 insertions, 59 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 78ef068fb7b..a56936e0e90 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -298,11 +298,12 @@ static SetOp *make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree, static LockRows *make_lockrows(Plan *lefttree, List *rowMarks, int epqParam); static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan); static ProjectSet *make_project_set(List *tlist, Plan *subplan); -static ModifyTable *make_modifytable(PlannerInfo *root, +static ModifyTable *make_modifytable(PlannerInfo *root, Plan *subplan, CmdType operation, bool canSetTag, Index nominalRelation, Index rootRelation, bool partColsUpdated, - List *resultRelations, List *subplans, List *subroots, + List *resultRelations, + List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, int epqParam); static GatherMerge *create_gather_merge_plan(PlannerInfo *root, @@ -2292,12 +2293,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path) /* * During setrefs.c, we'll need the grouping_map to fix up the cols lists * in GroupingFunc nodes. Save it for setrefs.c to use. - * - * This doesn't work if we're in an inheritance subtree (see notes in - * create_modifytable_plan). Fortunately we can't be because there would - * never be grouping in an UPDATE/DELETE; but let's Assert that. */ - Assert(root->inhTargetKind == INHKIND_NONE); Assert(root->grouping_map == NULL); root->grouping_map = grouping_map; @@ -2459,12 +2455,7 @@ create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path) * with InitPlan output params. (We can't just do that locally in the * MinMaxAgg node, because path nodes above here may have Agg references * as well.) Save the mmaggregates list to tell setrefs.c to do that. - * - * This doesn't work if we're in an inheritance subtree (see notes in - * create_modifytable_plan). Fortunately we can't be because there would - * never be aggregates in an UPDATE/DELETE; but let's Assert that. */ - Assert(root->inhTargetKind == INHKIND_NONE); Assert(root->minmax_aggs == NIL); root->minmax_aggs = best_path->mmaggregates; @@ -2681,46 +2672,24 @@ static ModifyTable * create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path) { ModifyTable *plan; - List *subplans = NIL; - ListCell *subpaths, - *subroots; - - /* Build the plan for each input path */ - forboth(subpaths, best_path->subpaths, - subroots, best_path->subroots) - { - Path *subpath = (Path *) lfirst(subpaths); - PlannerInfo *subroot = (PlannerInfo *) lfirst(subroots); - Plan *subplan; - - /* - * In an inherited UPDATE/DELETE, reference the per-child modified - * subroot while creating Plans from Paths for the child rel. This is - * a kluge, but otherwise it's too hard to ensure that Plan creation - * functions (particularly in FDWs) don't depend on the contents of - * "root" matching what they saw at Path creation time. The main - * downside is that creation functions for Plans that might appear - * below a ModifyTable cannot expect to modify the contents of "root" - * and have it "stick" for subsequent processing such as setrefs.c. - * That's not great, but it seems better than the alternative. - */ - subplan = create_plan_recurse(subroot, subpath, CP_EXACT_TLIST); + Path *subpath = best_path->subpath; + Plan *subplan; - /* Transfer resname/resjunk labeling, too, to keep executor happy */ - apply_tlist_labeling(subplan->targetlist, subroot->processed_tlist); + /* Subplan must produce exactly the specified tlist */ + subplan = create_plan_recurse(root, subpath, CP_EXACT_TLIST); - subplans = lappend(subplans, subplan); - } + /* Transfer resname/resjunk labeling, too, to keep executor happy */ + apply_tlist_labeling(subplan->targetlist, root->processed_tlist); plan = make_modifytable(root, + subplan, best_path->operation, best_path->canSetTag, best_path->nominalRelation, best_path->rootRelation, best_path->partColsUpdated, best_path->resultRelations, - subplans, - best_path->subroots, + best_path->updateColnosLists, best_path->withCheckOptionLists, best_path->returningLists, best_path->rowMarks, @@ -6916,11 +6885,12 @@ make_project_set(List *tlist, * Build a ModifyTable plan node */ static ModifyTable * -make_modifytable(PlannerInfo *root, +make_modifytable(PlannerInfo *root, Plan *subplan, CmdType operation, bool canSetTag, Index nominalRelation, Index rootRelation, bool partColsUpdated, - List *resultRelations, List *subplans, List *subroots, + List *resultRelations, + List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, int epqParam) { @@ -6928,17 +6898,17 @@ make_modifytable(PlannerInfo *root, List *fdw_private_list; Bitmapset *direct_modify_plans; ListCell *lc; - ListCell *lc2; int i; - Assert(list_length(resultRelations) == list_length(subplans)); - Assert(list_length(resultRelations) == list_length(subroots)); + Assert(operation == CMD_UPDATE ? + list_length(resultRelations) == list_length(updateColnosLists) : + updateColnosLists == NIL); Assert(withCheckOptionLists == NIL || list_length(resultRelations) == list_length(withCheckOptionLists)); Assert(returningLists == NIL || list_length(resultRelations) == list_length(returningLists)); - node->plan.lefttree = NULL; + node->plan.lefttree = subplan; node->plan.righttree = NULL; node->plan.qual = NIL; /* setrefs.c will fill in the targetlist, if needed */ @@ -6950,7 +6920,6 @@ make_modifytable(PlannerInfo *root, node->rootRelation = rootRelation; node->partColsUpdated = partColsUpdated; node->resultRelations = resultRelations; - node->plans = subplans; if (!onconflict) { node->onConflictAction = ONCONFLICT_NONE; @@ -6977,6 +6946,7 @@ make_modifytable(PlannerInfo *root, node->exclRelRTI = onconflict->exclRelIndex; node->exclRelTlist = onconflict->exclRelTlist; } + node->updateColnosLists = updateColnosLists; node->withCheckOptionLists = withCheckOptionLists; node->returningLists = returningLists; node->rowMarks = rowMarks; @@ -6989,10 +6959,9 @@ make_modifytable(PlannerInfo *root, fdw_private_list = NIL; direct_modify_plans = NULL; i = 0; - forboth(lc, resultRelations, lc2, subroots) + foreach(lc, resultRelations) { Index rti = lfirst_int(lc); - PlannerInfo *subroot = lfirst_node(PlannerInfo, lc2); FdwRoutine *fdwroutine; List *fdw_private; bool direct_modify; @@ -7004,16 +6973,16 @@ make_modifytable(PlannerInfo *root, * so it's not a baserel; and there are also corner cases for * updatable views where the target rel isn't a baserel.) */ - if (rti < subroot->simple_rel_array_size && - subroot->simple_rel_array[rti] != NULL) + if (rti < root->simple_rel_array_size && + root->simple_rel_array[rti] != NULL) { - RelOptInfo *resultRel = subroot->simple_rel_array[rti]; + RelOptInfo *resultRel = root->simple_rel_array[rti]; fdwroutine = resultRel->fdwroutine; } else { - RangeTblEntry *rte = planner_rt_fetch(rti, subroot); + RangeTblEntry *rte = planner_rt_fetch(rti, root); Assert(rte->rtekind == RTE_RELATION); if (rte->relkind == RELKIND_FOREIGN_TABLE) @@ -7036,16 +7005,16 @@ make_modifytable(PlannerInfo *root, fdwroutine->IterateDirectModify != NULL && fdwroutine->EndDirectModify != NULL && withCheckOptionLists == NIL && - !has_row_triggers(subroot, rti, operation) && - !has_stored_generated_columns(subroot, rti)) - direct_modify = fdwroutine->PlanDirectModify(subroot, node, rti, i); + !has_row_triggers(root, rti, operation) && + !has_stored_generated_columns(root, rti)) + direct_modify = fdwroutine->PlanDirectModify(root, node, rti, i); if (direct_modify) direct_modify_plans = bms_add_member(direct_modify_plans, i); if (!direct_modify && fdwroutine != NULL && fdwroutine->PlanForeignModify != NULL) - fdw_private = fdwroutine->PlanForeignModify(subroot, node, rti, i); + fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i); else fdw_private = NIL; fdw_private_list = lappend(fdw_private_list, fdw_private); |