aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_merge.c
diff options
context:
space:
mode:
authorDean Rasheed <dean.a.rasheed@gmail.com>2024-02-29 15:56:59 +0000
committerDean Rasheed <dean.a.rasheed@gmail.com>2024-02-29 15:56:59 +0000
commit5f2e179bd31e5f5803005101eb12a8d7bf8db8f3 (patch)
tree838a9f273c1d3d825db322161c0b8cdf3fbb0ce1 /src/backend/parser/parse_merge.c
parent8b29a119fdaa381d6f75105f539b1e658c0f8cdb (diff)
downloadpostgresql-5f2e179bd31e5f5803005101eb12a8d7bf8db8f3.tar.gz
postgresql-5f2e179bd31e5f5803005101eb12a8d7bf8db8f3.zip
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
Diffstat (limited to 'src/backend/parser/parse_merge.c')
-rw-r--r--src/backend/parser/parse_merge.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/src/backend/parser/parse_merge.c b/src/backend/parser/parse_merge.c
index 73f7a48b3c6..4356d61f8ed 100644
--- a/src/backend/parser/parse_merge.c
+++ b/src/backend/parser/parse_merge.c
@@ -172,28 +172,27 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
* Set up the MERGE target table. The target table is added to the
* namespace below and to joinlist in transform_MERGE_to_join, so don't do
* it here.
+ *
+ * Initially mergeTargetRelation is the same as resultRelation, so data is
+ * read from the table being updated. However, that might be changed by
+ * the rewriter, if the target is a trigger-updatable view, to allow
+ * target data to be read from the expanded view query while updating the
+ * original view relation.
*/
qry->resultRelation = setTargetTable(pstate, stmt->relation,
stmt->relation->inh,
false, targetPerms);
+ qry->mergeTargetRelation = qry->resultRelation;
- /*
- * MERGE is unsupported in various cases
- */
+ /* The target relation must be a table or a view */
if (pstate->p_target_relation->rd_rel->relkind != RELKIND_RELATION &&
- pstate->p_target_relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+ pstate->p_target_relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
+ pstate->p_target_relation->rd_rel->relkind != RELKIND_VIEW)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot execute MERGE on relation \"%s\"",
RelationGetRelationName(pstate->p_target_relation)),
errdetail_relkind_not_supported(pstate->p_target_relation->rd_rel->relkind)));
- if (pstate->p_target_relation->rd_rules != NULL &&
- pstate->p_target_relation->rd_rules->numLocks > 0)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("cannot execute MERGE on relation \"%s\"",
- RelationGetRelationName(pstate->p_target_relation)),
- errdetail("MERGE is not supported for relations with rules.")));
/* Now transform the source relation to produce the source RTE. */
transformFromClause(pstate,