mirror of
https://github.com/postgres/postgres.git
synced 2025-10-31 10:30:33 +03:00
Revert MERGE patch
This reverts commitsd204ef6377,83454e3c2band a few more commits thereafter (complete list at the end) related to MERGE feature. While the feature was fully functional, with sufficient test coverage and necessary documentation, it was felt that some parts of the executor and parse-analyzer can use a different design and it wasn't possible to do that in the available time. So it was decided to revert the patch for PG11 and retry again in the future. Thanks again to all reviewers and bug reporters. List of commits reverted, in reverse chronological order:f1464c5380Improve parse representation for MERGEddb4158579MERGE syntax diagram correction530e69e59bAllow cpluspluscheck to pass by renaming variable01b88b4df5MERGE minor errata3af7b2b0d4MERGE fix variable warning in non-assert buildsa5d86181ecMERGE INSERT allows only one VALUES clause4b2d44031fMERGE post-commit review4923550c20Tab completion for MERGEaa3faa3c7aWITH support in MERGE83454e3c2bNew files for MERGEd204ef6377MERGE SQL Command following SQL:2016 Author: Pavan Deolasee Reviewed-by: Michael Paquier
This commit is contained in:
@@ -289,13 +289,9 @@ static ModifyTable *make_modifytable(PlannerInfo *root,
|
||||
CmdType operation, bool canSetTag,
|
||||
Index nominalRelation, List *partitioned_rels,
|
||||
bool partColsUpdated,
|
||||
List *resultRelations,
|
||||
Index mergeTargetRelation,
|
||||
List *subplans,
|
||||
List *resultRelations, List *subplans,
|
||||
List *withCheckOptionLists, List *returningLists,
|
||||
List *rowMarks, OnConflictExpr *onconflict,
|
||||
List *mergeSourceTargetList,
|
||||
List *mergeActionList, int epqParam);
|
||||
List *rowMarks, OnConflictExpr *onconflict, int epqParam);
|
||||
static GatherMerge *create_gather_merge_plan(PlannerInfo *root,
|
||||
GatherMergePath *best_path);
|
||||
|
||||
@@ -2486,14 +2482,11 @@ 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);
|
||||
@@ -6561,13 +6554,9 @@ make_modifytable(PlannerInfo *root,
|
||||
CmdType operation, bool canSetTag,
|
||||
Index nominalRelation, List *partitioned_rels,
|
||||
bool partColsUpdated,
|
||||
List *resultRelations,
|
||||
Index mergeTargetRelation,
|
||||
List *subplans,
|
||||
List *resultRelations, List *subplans,
|
||||
List *withCheckOptionLists, List *returningLists,
|
||||
List *rowMarks, OnConflictExpr *onconflict,
|
||||
List *mergeSourceTargetList,
|
||||
List *mergeActionList, int epqParam)
|
||||
List *rowMarks, OnConflictExpr *onconflict, int epqParam)
|
||||
{
|
||||
ModifyTable *node = makeNode(ModifyTable);
|
||||
List *fdw_private_list;
|
||||
@@ -6593,7 +6582,6 @@ 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;
|
||||
@@ -6626,8 +6614,6 @@ make_modifytable(PlannerInfo *root,
|
||||
node->withCheckOptionLists = withCheckOptionLists;
|
||||
node->returningLists = returningLists;
|
||||
node->rowMarks = rowMarks;
|
||||
node->mergeSourceTargetList = mergeSourceTargetList;
|
||||
node->mergeActionList = mergeActionList;
|
||||
node->epqParam = epqParam;
|
||||
|
||||
/*
|
||||
|
||||
@@ -794,24 +794,6 @@ 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);
|
||||
@@ -1564,7 +1546,6 @@ inheritance_planner(PlannerInfo *root)
|
||||
subroot->parse->returningList);
|
||||
|
||||
Assert(!parse->onConflict);
|
||||
Assert(parse->mergeActionList == NIL);
|
||||
}
|
||||
|
||||
/* Result path must go into outer query's FINAL upperrel */
|
||||
@@ -1638,15 +1619,12 @@ inheritance_planner(PlannerInfo *root)
|
||||
partitioned_rels,
|
||||
root->partColsUpdated,
|
||||
resultRelations,
|
||||
0,
|
||||
subpaths,
|
||||
subroots,
|
||||
withCheckOptionLists,
|
||||
returningLists,
|
||||
rowMarks,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
SS_assign_special_param(root)));
|
||||
}
|
||||
|
||||
@@ -2177,8 +2155,8 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is an INSERT/UPDATE/DELETE/MERGE, and we're not being
|
||||
* called from inheritance_planner, add the ModifyTable node.
|
||||
* If this is an INSERT/UPDATE/DELETE, and we're not being called from
|
||||
* inheritance_planner, add the ModifyTable node.
|
||||
*/
|
||||
if (parse->commandType != CMD_SELECT && !inheritance_update)
|
||||
{
|
||||
@@ -2218,15 +2196,12 @@ 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));
|
||||
}
|
||||
|
||||
|
||||
@@ -851,60 +851,6 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
|
||||
fix_scan_list(root, splan->exclRelTlist, rtoffset);
|
||||
}
|
||||
|
||||
/*
|
||||
* The MERGE statement 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 statement
|
||||
* 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;
|
||||
|
||||
|
||||
@@ -118,46 +118,6 @@ 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
|
||||
@@ -388,7 +348,6 @@ expand_targetlist(List *tlist, int command_type,
|
||||
true /* byval */ );
|
||||
}
|
||||
break;
|
||||
case CMD_MERGE:
|
||||
case CMD_UPDATE:
|
||||
if (!att_tup->attisdropped)
|
||||
{
|
||||
|
||||
@@ -3302,21 +3302,17 @@ 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,
|
||||
Index mergeTargetRelation,
|
||||
List *subpaths,
|
||||
List *resultRelations, List *subpaths,
|
||||
List *subroots,
|
||||
List *withCheckOptionLists, List *returningLists,
|
||||
List *rowMarks, OnConflictExpr *onconflict,
|
||||
List *mergeSourceTargetList,
|
||||
List *mergeActionList, int epqParam)
|
||||
int epqParam)
|
||||
{
|
||||
ModifyTablePath *pathnode = makeNode(ModifyTablePath);
|
||||
double total_size;
|
||||
@@ -3381,7 +3377,6 @@ 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;
|
||||
@@ -3389,8 +3384,6 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
|
||||
pathnode->rowMarks = rowMarks;
|
||||
pathnode->onconflict = onconflict;
|
||||
pathnode->epqParam = epqParam;
|
||||
pathnode->mergeSourceTargetList = mergeSourceTargetList;
|
||||
pathnode->mergeActionList = mergeActionList;
|
||||
|
||||
return pathnode;
|
||||
}
|
||||
|
||||
@@ -1851,10 +1851,6 @@ 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;
|
||||
|
||||
Reference in New Issue
Block a user