diff options
Diffstat (limited to 'src/backend/optimizer/plan/setrefs.c')
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 69dd327f0c9..cd540a0df5b 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -851,6 +851,60 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) fix_scan_list(root, splan->exclRelTlist, rtoffset); } + /* + * The MERGE produces the target rows by performing a right + * join between the target relation and the source relation + * (which could be a plain relation or a subquery). The INSERT + * and UPDATE actions of the MERGE requires access to the + * columns from the source relation. We arrange things so that + * the source relation attributes are available as INNER_VAR + * and the target relation attributes are available from the + * scan tuple. + */ + if (splan->mergeActionList != NIL) + { + /* + * mergeSourceTargetList is already setup correctly to + * include all Vars coming from the source relation. So we + * fix the targetList of individual action nodes by + * ensuring that the source relation Vars are referenced + * as INNER_VAR. Note that for this to work correctly, + * during execution, the ecxt_innertuple must be set to + * the tuple obtained from the source relation. + * + * We leave the Vars from the result relation (i.e. the + * target relation) unchanged i.e. those Vars would be + * picked from the scan slot. So during execution, we must + * ensure that ecxt_scantuple is setup correctly to refer + * to the tuple from the target relation. + */ + + indexed_tlist *itlist; + + itlist = build_tlist_index(splan->mergeSourceTargetList); + + splan->mergeTargetRelation += rtoffset; + + foreach(l, splan->mergeActionList) + { + MergeAction *action = (MergeAction *) lfirst(l); + + /* Fix targetList of each action. */ + action->targetList = fix_join_expr(root, + action->targetList, + NULL, itlist, + linitial_int(splan->resultRelations), + rtoffset); + + /* Fix quals too. */ + action->qual = (Node *) fix_join_expr(root, + (List *) action->qual, + NULL, itlist, + linitial_int(splan->resultRelations), + rtoffset); + } + } + splan->nominalRelation += rtoffset; splan->exclRelRTI += rtoffset; |