mirror of
https://github.com/postgres/postgres.git
synced 2025-09-09 13:09:39 +03:00
Add RETURNING support to MERGE.
This allows a RETURNING clause to be appended to a MERGE query, to return values based on each row inserted, updated, or deleted. As with plain INSERT, UPDATE, and DELETE commands, the returned values are based on the new contents of the target table for INSERT and UPDATE actions, and on its old contents for DELETE actions. Values from the source relation may also be returned. As with INSERT/UPDATE/DELETE, the output of MERGE ... RETURNING may be used as the source relation for other operations such as WITH queries and COPY commands. Additionally, a special function merge_action() is provided, which returns 'INSERT', 'UPDATE', or 'DELETE', depending on the action executed for each row. The merge_action() function can be used anywhere in the RETURNING list, including in arbitrary expressions and subqueries, but it is an error to use it anywhere outside of a MERGE query's RETURNING list. Dean Rasheed, reviewed by Isaac Morland, Vik Fearing, Alvaro Herrera, Gurjeet Singh, Jian He, Jeff Davis, Merlin Moncure, Peter Eisentraut, and Wolfgang Walther. Discussion: http://postgr.es/m/CAEZATCWePEGQR5LBn-vD6SfeLZafzEm2Qy_L_Oky2=qw2w3Pzg@mail.gmail.com
This commit is contained in:
@@ -1855,7 +1855,8 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
|
||||
/*
|
||||
* Replace correlation vars (uplevel vars) with Params.
|
||||
*
|
||||
* Uplevel PlaceHolderVars and aggregates are replaced, too.
|
||||
* Uplevel PlaceHolderVars, aggregates, GROUPING() expressions, and
|
||||
* MergeSupportFuncs are replaced, too.
|
||||
*
|
||||
* Note: it is critical that this runs immediately after SS_process_sublinks.
|
||||
* Since we do not recurse into the arguments of uplevel PHVs and aggregates,
|
||||
@@ -1909,6 +1910,12 @@ replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
|
||||
if (((GroupingFunc *) node)->agglevelsup > 0)
|
||||
return (Node *) replace_outer_grouping(root, (GroupingFunc *) node);
|
||||
}
|
||||
if (IsA(node, MergeSupportFunc))
|
||||
{
|
||||
if (root->parse->commandType != CMD_MERGE)
|
||||
return (Node *) replace_outer_merge_support(root,
|
||||
(MergeSupportFunc *) node);
|
||||
}
|
||||
return expression_tree_mutator(node,
|
||||
replace_correlation_vars_mutator,
|
||||
(void *) root);
|
||||
|
@@ -307,6 +307,57 @@ replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a Param node to replace the given MergeSupportFunc expression
|
||||
* which is expected to be in the RETURNING list of an upper-level MERGE
|
||||
* query. Record the need for the MergeSupportFunc in the proper upper-level
|
||||
* root->plan_params.
|
||||
*/
|
||||
Param *
|
||||
replace_outer_merge_support(PlannerInfo *root, MergeSupportFunc *msf)
|
||||
{
|
||||
Param *retval;
|
||||
PlannerParamItem *pitem;
|
||||
Oid ptype = exprType((Node *) msf);
|
||||
|
||||
Assert(root->parse->commandType != CMD_MERGE);
|
||||
|
||||
/*
|
||||
* The parser should have ensured that the MergeSupportFunc is in the
|
||||
* RETURNING list of an upper-level MERGE query, so find that query.
|
||||
*/
|
||||
do
|
||||
{
|
||||
root = root->parent_root;
|
||||
if (root == NULL)
|
||||
elog(ERROR, "MergeSupportFunc found outside MERGE");
|
||||
} while (root->parse->commandType != CMD_MERGE);
|
||||
|
||||
/*
|
||||
* It does not seem worthwhile to try to de-duplicate references to outer
|
||||
* MergeSupportFunc expressions. Just make a new slot every time.
|
||||
*/
|
||||
msf = copyObject(msf);
|
||||
|
||||
pitem = makeNode(PlannerParamItem);
|
||||
pitem->item = (Node *) msf;
|
||||
pitem->paramId = list_length(root->glob->paramExecTypes);
|
||||
root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes,
|
||||
ptype);
|
||||
|
||||
root->plan_params = lappend(root->plan_params, pitem);
|
||||
|
||||
retval = makeNode(Param);
|
||||
retval->paramkind = PARAM_EXEC;
|
||||
retval->paramid = pitem->paramId;
|
||||
retval->paramtype = ptype;
|
||||
retval->paramtypmod = -1;
|
||||
retval->paramcollid = InvalidOid;
|
||||
retval->location = msf->location;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a Param node to replace the given Var,
|
||||
* which is expected to come from some upper NestLoop plan node.
|
||||
|
Reference in New Issue
Block a user