diff options
author | Dean Rasheed <dean.a.rasheed@gmail.com> | 2024-02-29 15:56:59 +0000 |
---|---|---|
committer | Dean Rasheed <dean.a.rasheed@gmail.com> | 2024-02-29 15:56:59 +0000 |
commit | 5f2e179bd31e5f5803005101eb12a8d7bf8db8f3 (patch) | |
tree | 838a9f273c1d3d825db322161c0b8cdf3fbb0ce1 /src/backend/rewrite/rewriteManip.c | |
parent | 8b29a119fdaa381d6f75105f539b1e658c0f8cdb (diff) | |
download | postgresql-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/rewrite/rewriteManip.c')
-rw-r--r-- | src/backend/rewrite/rewriteManip.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 76c97a5b28e..191f2dc0b1d 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -496,9 +496,10 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up) /* * If we are starting at a Query, and sublevels_up is zero, then we * must also fix rangetable indexes in the Query itself --- namely - * resultRelation, exclRelIndex and rowMarks entries. sublevels_up - * cannot be zero when recursing into a subquery, so there's no need - * to have the same logic inside OffsetVarNodes_walker. + * resultRelation, mergeTargetRelation, exclRelIndex and rowMarks + * entries. sublevels_up cannot be zero when recursing into a + * subquery, so there's no need to have the same logic inside + * OffsetVarNodes_walker. */ if (sublevels_up == 0) { @@ -507,6 +508,9 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up) if (qry->resultRelation) qry->resultRelation += offset; + if (qry->mergeTargetRelation) + qry->mergeTargetRelation += offset; + if (qry->onConflict && qry->onConflict->exclRelIndex) qry->onConflict->exclRelIndex += offset; @@ -687,9 +691,10 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) /* * If we are starting at a Query, and sublevels_up is zero, then we * must also fix rangetable indexes in the Query itself --- namely - * resultRelation and rowMarks entries. sublevels_up cannot be zero - * when recursing into a subquery, so there's no need to have the same - * logic inside ChangeVarNodes_walker. + * resultRelation, mergeTargetRelation, exclRelIndex and rowMarks + * entries. sublevels_up cannot be zero when recursing into a + * subquery, so there's no need to have the same logic inside + * ChangeVarNodes_walker. */ if (sublevels_up == 0) { @@ -698,6 +703,9 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) if (qry->resultRelation == rt_index) qry->resultRelation = new_index; + if (qry->mergeTargetRelation == rt_index) + qry->mergeTargetRelation = new_index; + /* this is unlikely to ever be used, but ... */ if (qry->onConflict && qry->onConflict->exclRelIndex == rt_index) qry->onConflict->exclRelIndex = new_index; |