mirror of
https://github.com/postgres/postgres.git
synced 2025-09-09 13:09:39 +03:00
Support MERGE into updatable views.
This allows the target relation of MERGE to be an auto-updatable or trigger-updatable view, and includes support for WITH CHECK OPTION, security barrier views, and security invoker views. A trigger-updatable view must have INSTEAD OF triggers for every type of action (INSERT, UPDATE, and DELETE) mentioned in the MERGE command. An auto-updatable view must not have any INSTEAD OF triggers. Mixing auto-update and trigger-update actions (i.e., having a partial set of INSTEAD OF triggers) is not supported. Rule-updatable views are also not supported, since there is no rewriter support for non-SELECT rules with MERGE operations. Dean Rasheed, reviewed by Jian He and Alvaro Herrera. Discussion: https://postgr.es/m/CAEZATCVcB1g0nmxuEc-A+gGB0HnfcGQNGYH7gS=7rq0u0zOBXA@mail.gmail.com
This commit is contained in:
@@ -198,12 +198,17 @@ transform_MERGE_to_join(Query *parse)
|
||||
|
||||
/*
|
||||
* Create a JOIN between the target and the source relation.
|
||||
*
|
||||
* Here the target is identified by parse->mergeTargetRelation. For a
|
||||
* regular table, this will equal parse->resultRelation, but for a
|
||||
* trigger-updatable view, it will be the expanded view subquery that we
|
||||
* need to pull data from.
|
||||
*/
|
||||
joinexpr = makeNode(JoinExpr);
|
||||
joinexpr->jointype = jointype;
|
||||
joinexpr->isNatural = false;
|
||||
joinexpr->larg = (Node *) makeNode(RangeTblRef);
|
||||
((RangeTblRef *) joinexpr->larg)->rtindex = parse->resultRelation;
|
||||
((RangeTblRef *) joinexpr->larg)->rtindex = parse->mergeTargetRelation;
|
||||
joinexpr->rarg = linitial(parse->jointree->fromlist); /* original join */
|
||||
joinexpr->usingClause = NIL;
|
||||
joinexpr->join_using_alias = NULL;
|
||||
@@ -215,6 +220,19 @@ transform_MERGE_to_join(Query *parse)
|
||||
/* Make the new join be the sole entry in the query's jointree */
|
||||
parse->jointree->fromlist = list_make1(joinexpr);
|
||||
parse->jointree->quals = NULL;
|
||||
|
||||
/*
|
||||
* If necessary, mark parse->targetlist entries that refer to the target
|
||||
* as nullable by the join. Normally the targetlist will be empty for a
|
||||
* MERGE, but if the target is a trigger-updatable view, it will contain a
|
||||
* whole-row Var referring to the expanded view query.
|
||||
*/
|
||||
if (parse->targetList != NIL &&
|
||||
(jointype == JOIN_RIGHT || jointype == JOIN_FULL))
|
||||
parse->targetList = (List *)
|
||||
add_nulling_relids((Node *) parse->targetList,
|
||||
bms_make_singleton(parse->mergeTargetRelation),
|
||||
bms_make_singleton(joinrti));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -891,8 +891,7 @@ add_row_identity_columns(PlannerInfo *root, Index rtindex,
|
||||
|
||||
Assert(commandType == CMD_UPDATE || commandType == CMD_DELETE || commandType == CMD_MERGE);
|
||||
|
||||
if (commandType == CMD_MERGE ||
|
||||
relkind == RELKIND_RELATION ||
|
||||
if (relkind == RELKIND_RELATION ||
|
||||
relkind == RELKIND_MATVIEW ||
|
||||
relkind == RELKIND_PARTITIONED_TABLE)
|
||||
{
|
||||
|
Reference in New Issue
Block a user