aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rowsecurity.c
diff options
context:
space:
mode:
authorDean Rasheed <dean.a.rasheed@gmail.com>2024-03-17 13:58:59 +0000
committerDean Rasheed <dean.a.rasheed@gmail.com>2024-03-17 13:58:59 +0000
commitc649fa24a42ba89bf5460c7110e4fc8eeca65959 (patch)
treede7d51489c6c6fff56fddad66c0ced2aa427d6a5 /src/backend/rewrite/rowsecurity.c
parent6a004f1be87d34cfe51acf2fe2552d2b08a79273 (diff)
downloadpostgresql-c649fa24a42ba89bf5460c7110e4fc8eeca65959.tar.gz
postgresql-c649fa24a42ba89bf5460c7110e4fc8eeca65959.zip
Add RETURNING support to MERGE.
This allows a RETURNING clause to be appended to a MERGE query, to return values based on each row inserted, updated, or deleted. As with plain INSERT, UPDATE, and DELETE commands, the returned values are based on the new contents of the target table for INSERT and UPDATE actions, and on its old contents for DELETE actions. Values from the source relation may also be returned. As with INSERT/UPDATE/DELETE, the output of MERGE ... RETURNING may be used as the source relation for other operations such as WITH queries and COPY commands. Additionally, a special function merge_action() is provided, which returns 'INSERT', 'UPDATE', or 'DELETE', depending on the action executed for each row. The merge_action() function can be used anywhere in the RETURNING list, including in arbitrary expressions and subqueries, but it is an error to use it anywhere outside of a MERGE query's RETURNING list. Dean Rasheed, reviewed by Isaac Morland, Vik Fearing, Alvaro Herrera, Gurjeet Singh, Jian He, Jeff Davis, Merlin Moncure, Peter Eisentraut, and Wolfgang Walther. Discussion: http://postgr.es/m/CAEZATCWePEGQR5LBn-vD6SfeLZafzEm2Qy_L_Oky2=qw2w3Pzg@mail.gmail.com
Diffstat (limited to 'src/backend/rewrite/rowsecurity.c')
-rw-r--r--src/backend/rewrite/rowsecurity.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/src/backend/rewrite/rowsecurity.c b/src/backend/rewrite/rowsecurity.c
index 450af27c7f5..59fd305dd7b 100644
--- a/src/backend/rewrite/rowsecurity.c
+++ b/src/backend/rewrite/rowsecurity.c
@@ -384,10 +384,10 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
* on the final action we take.
*
* We already fetched the SELECT policies above, to check existing rows,
- * but we must also check that new rows created by UPDATE actions are
- * visible, if SELECT rights are required for this relation. We don't do
- * this for INSERT actions, since an INSERT command would only do this
- * check if it had a RETURNING list, and MERGE does not support RETURNING.
+ * but we must also check that new rows created by INSERT/UPDATE actions
+ * are visible, if SELECT rights are required. For INSERT actions, we only
+ * do this if RETURNING is specified, to be consistent with a plain INSERT
+ * command, which can only require SELECT rights when RETURNING is used.
*
* We don't push the UPDATE/DELETE USING quals to the RTE because we don't
* really want to apply them while scanning the relation since we don't
@@ -409,6 +409,8 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
List *merge_delete_restrictive_policies;
List *merge_insert_permissive_policies;
List *merge_insert_restrictive_policies;
+ List *merge_select_permissive_policies = NIL;
+ List *merge_select_restrictive_policies = NIL;
/*
* Fetch the UPDATE policies and set them up to execute on the
@@ -446,9 +448,6 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
*/
if (perminfo->requiredPerms & ACL_SELECT)
{
- List *merge_select_permissive_policies;
- List *merge_select_restrictive_policies;
-
get_policies_for_relation(rel, CMD_SELECT, user_id,
&merge_select_permissive_policies,
&merge_select_restrictive_policies);
@@ -497,6 +496,21 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
withCheckOptions,
hasSubLinks,
false);
+
+ /*
+ * Add ALL/SELECT policies as WCO_RLS_INSERT_CHECK WCOs, to ensure
+ * that the inserted row is visible when executing an INSERT action,
+ * if RETURNING is specified and SELECT rights are required for this
+ * relation.
+ */
+ if (perminfo->requiredPerms & ACL_SELECT && root->returningList)
+ add_with_check_options(rel, rt_index,
+ WCO_RLS_INSERT_CHECK,
+ merge_select_permissive_policies,
+ merge_select_restrictive_policies,
+ withCheckOptions,
+ hasSubLinks,
+ true);
}
table_close(rel, NoLock);