aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteHandler.c
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2015-05-08 00:20:46 +0200
committerAndres Freund <andres@anarazel.de>2015-05-08 00:20:46 +0200
commit2c8f4836db058d0715bc30a30655d646287ba509 (patch)
tree31576f5fc453bd2dbc5642c1281640b5eb959307 /src/backend/rewrite/rewriteHandler.c
parentdb5f98ab4fa44bc563ec62d7b1aada4fc276d9b2 (diff)
downloadpostgresql-2c8f4836db058d0715bc30a30655d646287ba509.tar.gz
postgresql-2c8f4836db058d0715bc30a30655d646287ba509.zip
Represent columns requiring insert and update privileges indentently.
Previously, relation range table entries used a single Bitmapset field representing which columns required either UPDATE or INSERT privileges, despite the fact that INSERT and UPDATE privileges are separately cataloged, and may be independently held. As statements so far required either insert or update privileges but never both, that was sufficient. The required permission could be inferred from the top level statement run. The upcoming INSERT ... ON CONFLICT UPDATE feature needs to independently check for both privileges in one statement though, so that is not sufficient anymore. Bumps catversion as stored rules change. Author: Peter Geoghegan Reviewed-By: Andres Freund
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r--src/backend/rewrite/rewriteHandler.c52
1 files changed, 30 insertions, 22 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 60c60caf396..0fc47cb786c 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -1403,7 +1403,8 @@ ApplyRetrieveRule(Query *parsetree,
rte->requiredPerms = 0;
rte->checkAsUser = InvalidOid;
rte->selectedCols = NULL;
- rte->modifiedCols = NULL;
+ rte->insertedCols = NULL;
+ rte->updatedCols = NULL;
/*
* For the most part, Vars referencing the view should remain as
@@ -1466,12 +1467,14 @@ ApplyRetrieveRule(Query *parsetree,
subrte->requiredPerms = rte->requiredPerms;
subrte->checkAsUser = rte->checkAsUser;
subrte->selectedCols = rte->selectedCols;
- subrte->modifiedCols = rte->modifiedCols;
+ subrte->insertedCols = rte->insertedCols;
+ subrte->updatedCols = rte->updatedCols;
rte->requiredPerms = 0; /* no permission check on subquery itself */
rte->checkAsUser = InvalidOid;
rte->selectedCols = NULL;
- rte->modifiedCols = NULL;
+ rte->insertedCols = NULL;
+ rte->updatedCols = NULL;
/*
* If FOR [KEY] UPDATE/SHARE of view, mark all the contained tables as
@@ -2621,9 +2624,9 @@ rewriteTargetView(Query *parsetree, Relation view)
/*
* For 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 modifiedCols set, since rewriteTargetListIU may have added
- * additional targetlist entries for view defaults, and these must also be
- * updatable.
+ * 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.
*/
if (parsetree->commandType != CMD_DELETE)
{
@@ -2760,28 +2763,33 @@ rewriteTargetView(Query *parsetree, Relation view)
*
* Initially, new_rte contains selectedCols permission check bits for all
* base-rel columns referenced by the view, but since the view is a SELECT
- * query its modifiedCols is empty. We set modifiedCols to include all
- * the columns the outer query is trying to modify, adjusting the column
- * numbers as needed. But we leave selectedCols as-is, so the view owner
- * must have read permission for all columns used in the view definition,
- * even if some of them are not read by the outer query. We could try to
- * limit selectedCols to only columns used in the transformed query, but
- * that does not correspond to what happens in ordinary SELECT usage of a
- * view: all referenced columns must have read permission, even if
- * optimization finds that some of them can be discarded during query
- * transformation. The flattening we're doing here is an optional
- * optimization, too. (If you are unpersuaded and want to change this,
- * note that applying adjust_view_column_set to view_rte->selectedCols is
- * clearly *not* the right answer, since that neglects base-rel columns
- * used in the view's WHERE quals.)
+ * query its insertedCols/updatedCols is empty. We set insertedCols and
+ * updatedCols to include all the columns the outer query is trying to
+ * modify, adjusting the column numbers as needed. But we leave
+ * selectedCols as-is, so the view owner must have read permission for all
+ * columns used in the view definition, even if some of them are not read
+ * by the outer query. We could try to limit selectedCols to only columns
+ * used in the transformed query, but that does not correspond to what
+ * happens in ordinary SELECT usage of a view: all referenced columns must
+ * have read permission, even if optimization finds that some of them can
+ * be discarded during query transformation. The flattening we're doing
+ * here is an optional optimization, too. (If you are unpersuaded and want
+ * to change this, note that applying adjust_view_column_set to
+ * view_rte->selectedCols is clearly *not* the right answer, since that
+ * neglects base-rel columns used in the view's WHERE quals.)
*
* This step needs the modified view targetlist, so we have to do things
* in this order.
*/
- Assert(bms_is_empty(new_rte->modifiedCols));
- new_rte->modifiedCols = adjust_view_column_set(view_rte->modifiedCols,
+ Assert(bms_is_empty(new_rte->insertedCols) &&
+ bms_is_empty(new_rte->updatedCols));
+
+ new_rte->insertedCols = adjust_view_column_set(view_rte->insertedCols,
view_targetlist);
+ new_rte->updatedCols = adjust_view_column_set(view_rte->updatedCols,
+ view_targetlist);
+
/*
* Move any security barrier quals from the view RTE onto the new target
* RTE. Any such quals should now apply to the new target RTE and will