Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4989ce7

Browse files
committed
MERGE ... DO NOTHING: require SELECT privileges
Verify that a user running MERGE with a DO NOTHING clause has privileges to read the table, even if no columns are referenced. Such privileges were already required if the ON clause or any of the WHEN conditions referenced any column at all, so there's no functional change in practice. This change fixes an assertion failure in the case where no column is referenced by the command and the WHEN clauses are all DO NOTHING. Backpatch to 15, where MERGE was introduced. Reported-by: Alena Rybakina <a.rybakina@postgrespro.ru> Reported-by: Alexander Lakhin <exclusion@gmail.com> Discussion: https://postgr.es/m/4d65a385-7efa-4436-a825-0869f89d9d92@postgrespro.ru
1 parent ed345c2 commit 4989ce7

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

src/backend/parser/parse_merge.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,11 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
133133
int when_type = (mergeWhenClause->matched ? 0 : 1);
134134

135135
/*
136-
* Collect action types so we can check target permissions
136+
* Collect permissions to check, according to action types. We require
137+
* SELECT privileges for DO NOTHING because it'd be irregular to have
138+
* a target relation with zero privileges checked, in case DO NOTHING
139+
* is the only action. There's no damage from that: any meaningful
140+
* MERGE command requires at least some access to the table anyway.
137141
*/
138142
switch (mergeWhenClause->commandType)
139143
{
@@ -147,6 +151,7 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
147151
targetPerms |= ACL_DELETE;
148152
break;
149153
case CMD_NOTHING:
154+
targetPerms |= ACL_SELECT;
150155
break;
151156
default:
152157
elog(ERROR, "unknown action in MERGE WHEN clause");

src/test/regress/expected/merge.out

+10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
--
44
CREATE USER regress_merge_privs;
55
CREATE USER regress_merge_no_privs;
6+
CREATE USER regress_merge_none;
67
DROP TABLE IF EXISTS target;
78
NOTICE: table "target" does not exist, skipping
89
DROP TABLE IF EXISTS source;
@@ -159,6 +160,14 @@ ERROR: cannot execute MERGE on relation "mv"
159160
DETAIL: This operation is not supported for materialized views.
160161
DROP MATERIALIZED VIEW mv;
161162
-- permissions
163+
SET SESSION AUTHORIZATION regress_merge_none;
164+
MERGE INTO target
165+
USING (SELECT 1)
166+
ON true
167+
WHEN MATCHED THEN
168+
DO NOTHING;
169+
ERROR: permission denied for table target
170+
SET SESSION AUTHORIZATION regress_merge_privs;
162171
MERGE INTO target
163172
USING source2
164173
ON target.tid = source2.sid
@@ -2248,3 +2257,4 @@ DROP TABLE source, source2;
22482257
DROP FUNCTION merge_trigfunc();
22492258
DROP USER regress_merge_privs;
22502259
DROP USER regress_merge_no_privs;
2260+
DROP USER regress_merge_none;

src/test/regress/sql/merge.sql

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
CREATE USER regress_merge_privs;
66
CREATE USER regress_merge_no_privs;
7+
CREATE USER regress_merge_none;
8+
79
DROP TABLE IF EXISTS target;
810
DROP TABLE IF EXISTS source;
911
CREATE TABLE target (tid integer, balance integer)
@@ -118,6 +120,14 @@ DROP MATERIALIZED VIEW mv;
118120

119121
-- permissions
120122

123+
SET SESSION AUTHORIZATION regress_merge_none;
124+
MERGE INTO target
125+
USING (SELECT 1)
126+
ON true
127+
WHEN MATCHED THEN
128+
DO NOTHING;
129+
130+
SET SESSION AUTHORIZATION regress_merge_privs;
121131
MERGE INTO target
122132
USING source2
123133
ON target.tid = source2.sid
@@ -1471,3 +1481,4 @@ DROP TABLE source, source2;
14711481
DROP FUNCTION merge_trigfunc();
14721482
DROP USER regress_merge_privs;
14731483
DROP USER regress_merge_no_privs;
1484+
DROP USER regress_merge_none;

0 commit comments

Comments
 (0)