aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteHandler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r--src/backend/rewrite/rewriteHandler.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 8a29fbbc465..e1d805d113e 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -2986,7 +2986,7 @@ relation_is_updatable(Oid reloid,
*
* This is used with simply-updatable views to map column-permissions sets for
* the view columns onto the matching columns in the underlying base relation.
- * The targetlist is expected to be a list of plain Vars of the underlying
+ * Relevant entries in the targetlist must be plain Vars of the underlying
* relation (as per the checks above in view_query_is_auto_updatable).
*/
static Bitmapset *
@@ -3186,6 +3186,10 @@ rewriteTargetView(Query *parsetree, Relation view)
*/
viewquery = copyObject(get_view_query(view));
+ /* Locate RTE and perminfo describing the view in the outer query */
+ view_rte = rt_fetch(parsetree->resultRelation, parsetree->rtable);
+ view_perminfo = getRTEPermissionInfo(parsetree->rteperminfos, view_rte);
+
/*
* Are we doing INSERT/UPDATE, or MERGE containing INSERT/UPDATE? If so,
* various additional checks on the view columns need to be applied, and
@@ -3225,17 +3229,26 @@ rewriteTargetView(Query *parsetree, Relation view)
/*
* For INSERT/UPDATE (or MERGE containing INSERT/UPDATE) the modified
- * columns must all be updatable. Note that we get the modified columns
- * from the query's targetlist, not from the result RTE's insertedCols
- * and/or updatedCols set, since rewriteTargetListIU may have added
- * additional targetlist entries for view defaults, and these must also be
- * updatable.
+ * columns must all be updatable.
*/
if (insert_or_update)
{
- Bitmapset *modified_cols = NULL;
+ Bitmapset *modified_cols;
char *non_updatable_col;
+ /*
+ * Compute the set of modified columns as those listed in the result
+ * RTE's insertedCols and/or updatedCols sets plus those that are
+ * targets of the query's targetlist(s). We must consider the query's
+ * targetlist because rewriteTargetListIU may have added additional
+ * targetlist entries for view defaults, and these must also be
+ * updatable. But rewriteTargetListIU can also remove entries if they
+ * are DEFAULT markers and the column's default is NULL, so
+ * considering only the targetlist would also be wrong.
+ */
+ modified_cols = bms_union(view_perminfo->insertedCols,
+ view_perminfo->updatedCols);
+
foreach(lc, parsetree->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(lc);
@@ -3337,9 +3350,6 @@ rewriteTargetView(Query *parsetree, Relation view)
}
}
- /* Locate RTE describing the view in the outer query */
- view_rte = rt_fetch(parsetree->resultRelation, parsetree->rtable);
-
/*
* If we get here, view_query_is_auto_updatable() has verified that the
* view contains a single base relation.
@@ -3434,10 +3444,7 @@ rewriteTargetView(Query *parsetree, Relation view)
* Note: the original view's RTEPermissionInfo remains in the query's
* rteperminfos so that the executor still performs appropriate
* permissions checks for the query caller's use of the view.
- */
- view_perminfo = getRTEPermissionInfo(parsetree->rteperminfos, view_rte);
-
- /*
+ *
* Disregard the perminfo in viewquery->rteperminfos that the base_rte
* would currently be pointing at, because we'd like it to point now to a
* new one that will be filled below. Must set perminfoindex to 0 to not