1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-31 10:30:33 +03:00

Modified files for MERGE

This commit is contained in:
Simon Riggs
2018-04-02 21:12:47 +01:00
parent e6597dc353
commit 354f13855e
82 changed files with 2570 additions and 165 deletions

View File

@@ -288,9 +288,13 @@ static ModifyTable *make_modifytable(PlannerInfo *root,
CmdType operation, bool canSetTag,
Index nominalRelation, List *partitioned_rels,
bool partColsUpdated,
List *resultRelations, List *subplans,
List *resultRelations,
Index mergeTargetRelation,
List *subplans,
List *withCheckOptionLists, List *returningLists,
List *rowMarks, OnConflictExpr *onconflict, int epqParam);
List *rowMarks, OnConflictExpr *onconflict,
List *mergeSourceTargetList,
List *mergeActionList, int epqParam);
static GatherMerge *create_gather_merge_plan(PlannerInfo *root,
GatherMergePath *best_path);
@@ -2446,11 +2450,14 @@ create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path)
best_path->partitioned_rels,
best_path->partColsUpdated,
best_path->resultRelations,
best_path->mergeTargetRelation,
subplans,
best_path->withCheckOptionLists,
best_path->returningLists,
best_path->rowMarks,
best_path->onconflict,
best_path->mergeSourceTargetList,
best_path->mergeActionList,
best_path->epqParam);
copy_generic_path_info(&plan->plan, &best_path->path);
@@ -6517,9 +6524,13 @@ make_modifytable(PlannerInfo *root,
CmdType operation, bool canSetTag,
Index nominalRelation, List *partitioned_rels,
bool partColsUpdated,
List *resultRelations, List *subplans,
List *resultRelations,
Index mergeTargetRelation,
List *subplans,
List *withCheckOptionLists, List *returningLists,
List *rowMarks, OnConflictExpr *onconflict, int epqParam)
List *rowMarks, OnConflictExpr *onconflict,
List *mergeSourceTargetList,
List *mergeActionList, int epqParam)
{
ModifyTable *node = makeNode(ModifyTable);
List *fdw_private_list;
@@ -6545,6 +6556,7 @@ make_modifytable(PlannerInfo *root,
node->partitioned_rels = partitioned_rels;
node->partColsUpdated = partColsUpdated;
node->resultRelations = resultRelations;
node->mergeTargetRelation = mergeTargetRelation;
node->resultRelIndex = -1; /* will be set correctly in setrefs.c */
node->rootResultRelIndex = -1; /* will be set correctly in setrefs.c */
node->plans = subplans;
@@ -6577,6 +6589,8 @@ make_modifytable(PlannerInfo *root,
node->withCheckOptionLists = withCheckOptionLists;
node->returningLists = returningLists;
node->rowMarks = rowMarks;
node->mergeSourceTargetList = mergeSourceTargetList;
node->mergeActionList = mergeActionList;
node->epqParam = epqParam;
/*

View File

@@ -794,6 +794,24 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
/* exclRelTlist contains only Vars, so no preprocessing needed */
}
foreach(l, parse->mergeActionList)
{
MergeAction *action = (MergeAction *) lfirst(l);
action->targetList = (List *)
preprocess_expression(root,
(Node *) action->targetList,
EXPRKIND_TARGET);
action->qual =
preprocess_expression(root,
(Node *) action->qual,
EXPRKIND_QUAL);
}
parse->mergeSourceTargetList = (List *)
preprocess_expression(root, (Node *) parse->mergeSourceTargetList,
EXPRKIND_TARGET);
root->append_rel_list = (List *)
preprocess_expression(root, (Node *) root->append_rel_list,
EXPRKIND_APPINFO);
@@ -1535,6 +1553,7 @@ inheritance_planner(PlannerInfo *root)
subroot->parse->returningList);
Assert(!parse->onConflict);
Assert(parse->mergeActionList == NIL);
}
/* Result path must go into outer query's FINAL upperrel */
@@ -1593,12 +1612,15 @@ inheritance_planner(PlannerInfo *root)
partitioned_rels,
partColsUpdated,
resultRelations,
0,
subpaths,
subroots,
withCheckOptionLists,
returningLists,
rowMarks,
NULL,
NULL,
NULL,
SS_assign_special_param(root)));
}
@@ -2129,8 +2151,8 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
}
/*
* If this is an INSERT/UPDATE/DELETE, and we're not being called from
* inheritance_planner, add the ModifyTable node.
* If this is an INSERT/UPDATE/DELETE/MERGE, and we're not being
* called from inheritance_planner, add the ModifyTable node.
*/
if (parse->commandType != CMD_SELECT && !inheritance_update)
{
@@ -2170,12 +2192,15 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
NIL,
false,
list_make1_int(parse->resultRelation),
parse->mergeTarget_relation,
list_make1(path),
list_make1(root),
withCheckOptionLists,
returningLists,
rowMarks,
parse->onConflict,
parse->mergeSourceTargetList,
parse->mergeActionList,
SS_assign_special_param(root));
}

View File

@@ -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;

View File

@@ -118,6 +118,46 @@ preprocess_targetlist(PlannerInfo *root)
tlist = expand_targetlist(tlist, command_type,
result_relation, target_relation);
if (command_type == CMD_MERGE)
{
ListCell *l;
/*
* For MERGE, add any junk column(s) needed to allow the executor to
* identify the rows to be updated or deleted, with different
* handling for partitioned tables.
*/
rewriteTargetListMerge(parse, target_relation);
/*
* For MERGE command, handle targetlist of each MergeAction separately.
* Give the same treatment to MergeAction->targetList as we would have
* given to a regular INSERT/UPDATE/DELETE.
*/
foreach(l, parse->mergeActionList)
{
MergeAction *action = (MergeAction *) lfirst(l);
switch (action->commandType)
{
case CMD_INSERT:
case CMD_UPDATE:
action->targetList = expand_targetlist(action->targetList,
action->commandType,
result_relation,
target_relation);
break;
case CMD_DELETE:
break;
case CMD_NOTHING:
break;
default:
elog(ERROR, "unknown action in MERGE WHEN clause");
}
}
}
/*
* Add necessary junk columns for rowmarked rels. These values are needed
* for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
@@ -348,6 +388,7 @@ expand_targetlist(List *tlist, int command_type,
true /* byval */ );
}
break;
case CMD_MERGE:
case CMD_UPDATE:
if (!att_tup->attisdropped)
{

View File

@@ -3284,17 +3284,21 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel,
* 'rowMarks' is a list of PlanRowMarks (non-locking only)
* 'onconflict' is the ON CONFLICT clause, or NULL
* 'epqParam' is the ID of Param for EvalPlanQual re-eval
* 'mergeActionList' is a list of MERGE actions
*/
ModifyTablePath *
create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
CmdType operation, bool canSetTag,
Index nominalRelation, List *partitioned_rels,
bool partColsUpdated,
List *resultRelations, List *subpaths,
List *resultRelations,
Index mergeTargetRelation,
List *subpaths,
List *subroots,
List *withCheckOptionLists, List *returningLists,
List *rowMarks, OnConflictExpr *onconflict,
int epqParam)
List *mergeSourceTargetList,
List *mergeActionList, int epqParam)
{
ModifyTablePath *pathnode = makeNode(ModifyTablePath);
double total_size;
@@ -3359,6 +3363,7 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
pathnode->partitioned_rels = list_copy(partitioned_rels);
pathnode->partColsUpdated = partColsUpdated;
pathnode->resultRelations = resultRelations;
pathnode->mergeTargetRelation = mergeTargetRelation;
pathnode->subpaths = subpaths;
pathnode->subroots = subroots;
pathnode->withCheckOptionLists = withCheckOptionLists;
@@ -3366,6 +3371,8 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
pathnode->rowMarks = rowMarks;
pathnode->onconflict = onconflict;
pathnode->epqParam = epqParam;
pathnode->mergeSourceTargetList = mergeSourceTargetList;
pathnode->mergeActionList = mergeActionList;
return pathnode;
}

View File

@@ -1835,6 +1835,10 @@ has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
trigDesc->trig_delete_before_row))
result = true;
break;
/* There is no separate event for MERGE, only INSERT/UPDATE/DELETE */
case CMD_MERGE:
result = false;
break;
default:
elog(ERROR, "unrecognized CmdType: %d", (int) event);
break;