Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita61b1f7

Browse files
committed
Rework query relation permission checking
Currently, information about the permissions to be checked on relationsmentioned in a query is stored in their range table entries. So theexecutor must scan the entire range table looking for relations thatneed to have permissions checked. This can make the permission checkingpart of the executor initialization needlessly expensive when manyinheritance children are present in the range range. While thepermissions need not be checked on the individual child relations, theexecutor still must visit every range table entry to filter them out.This commit moves the permission checking information out of the rangetable entries into a new plan node called RTEPermissionInfo. Everytop-level (inheritance "root") RTE_RELATION entry in the range tablegets one and a list of those is maintained alongside the range table.This new list is initialized by the parser when initializing the rangetable. The rewriter can add more entries to it as rules/views areexpanded. Finally, the planner combines the lists of the individualsubqueries into one flat list that is passed to the executor forchecking.To make it quick to find the RTEPermissionInfo entry belonging to agiven relation, RangeTblEntry gets a new Index field 'perminfoindex'that stores the corresponding RTEPermissionInfo's index in the query'slist of the latter.ExecutorCheckPerms_hook has gained another List * argument; thesignature is now:typedef bool (*ExecutorCheckPerms_hook_type) (List *rangeTable, List *rtePermInfos, bool ereport_on_violation);The first argument is no longer used by any in-core uses of the hook,but we leave it in place because there may be other implementations thatdo. Implementations should likely scan the rtePermInfos list todetermine which operations to allow or deny.Author: Amit Langote <amitlangote09@gmail.com>Discussion:https://postgr.es/m/CA+HiwqGjJDmUhDSfv-U2qhKJjt9ST7Xh9JXC_irsAQ1TAUsJYg@mail.gmail.com
1 parentb5bbaf0 commita61b1f7

File tree

47 files changed

+953
-533
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+953
-533
lines changed

‎contrib/postgres_fdw/postgres_fdw.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include"optimizer/appendinfo.h"
3232
#include"optimizer/clauses.h"
3333
#include"optimizer/cost.h"
34+
#include"optimizer/inherit.h"
3435
#include"optimizer/optimizer.h"
3536
#include"optimizer/pathnode.h"
3637
#include"optimizer/paths.h"
@@ -657,8 +658,8 @@ postgresGetForeignRelSize(PlannerInfo *root,
657658
/*
658659
* If the table or the server is configured to use remote estimates,
659660
* identify which user to do remote access as during planning. This
660-
* should match whatExecCheckRTEPerms() does. If we fail due to lack of
661-
* permissions, the query would have failed at runtime anyway.
661+
* should match whatExecCheckPermissions() does. If we fail due to lack
662+
*ofpermissions, the query would have failed at runtime anyway.
662663
*/
663664
if (fpinfo->use_remote_estimate)
664665
{
@@ -1809,7 +1810,8 @@ postgresPlanForeignModify(PlannerInfo *root,
18091810
elseif (operation==CMD_UPDATE)
18101811
{
18111812
intcol;
1812-
Bitmapset*allUpdatedCols=bms_union(rte->updatedCols,rte->extraUpdatedCols);
1813+
RelOptInfo*rel=find_base_rel(root,resultRelation);
1814+
Bitmapset*allUpdatedCols=get_rel_all_updated_cols(root,rel);
18131815

18141816
col=-1;
18151817
while ((col=bms_next_member(allUpdatedCols,col)) >=0)
@@ -2650,7 +2652,7 @@ postgresBeginDirectModify(ForeignScanState *node, int eflags)
26502652

26512653
/*
26522654
* Identify which user to do the remote access as. This should match what
2653-
*ExecCheckRTEPerms() does.
2655+
*ExecCheckPermissions() does.
26542656
*/
26552657
userid=OidIsValid(fsplan->checkAsUser) ?fsplan->checkAsUser :GetUserId();
26562658

@@ -3975,11 +3977,8 @@ create_foreign_modify(EState *estate,
39753977
fmstate= (PgFdwModifyState*)palloc0(sizeof(PgFdwModifyState));
39763978
fmstate->rel=rel;
39773979

3978-
/*
3979-
* Identify which user to do the remote access as. This should match what
3980-
* ExecCheckRTEPerms() does.
3981-
*/
3982-
userid=OidIsValid(rte->checkAsUser) ?rte->checkAsUser :GetUserId();
3980+
/* Identify which user to do the remote access as. */
3981+
userid=ExecGetResultRelCheckAsUser(resultRelInfo,estate);
39833982

39843983
/* Get info about foreign table. */
39853984
table=GetForeignTable(RelationGetRelid(rel));

‎contrib/sepgsql/dml.c

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include"commands/tablecmds.h"
2424
#include"executor/executor.h"
2525
#include"nodes/bitmapset.h"
26+
#include"parser/parsetree.h"
2627
#include"sepgsql.h"
2728
#include"utils/lsyscache.h"
2829
#include"utils/syscache.h"
@@ -277,38 +278,33 @@ check_relation_privileges(Oid relOid,
277278
* Entrypoint of the DML permission checks
278279
*/
279280
bool
280-
sepgsql_dml_privileges(List*rangeTabls,boolabort_on_violation)
281+
sepgsql_dml_privileges(List*rangeTbls,List*rteperminfos,
282+
boolabort_on_violation)
281283
{
282284
ListCell*lr;
283285

284-
foreach(lr,rangeTabls)
286+
foreach(lr,rteperminfos)
285287
{
286-
RangeTblEntry*rte=lfirst(lr);
288+
RTEPermissionInfo*perminfo=lfirst_node(RTEPermissionInfo,lr);
287289
uint32required=0;
288290
List*tableIds;
289291
ListCell*li;
290292

291-
/*
292-
* Only regular relations shall be checked
293-
*/
294-
if (rte->rtekind!=RTE_RELATION)
295-
continue;
296-
297293
/*
298294
* Find out required permissions
299295
*/
300-
if (rte->requiredPerms&ACL_SELECT)
296+
if (perminfo->requiredPerms&ACL_SELECT)
301297
required |=SEPG_DB_TABLE__SELECT;
302-
if (rte->requiredPerms&ACL_INSERT)
298+
if (perminfo->requiredPerms&ACL_INSERT)
303299
required |=SEPG_DB_TABLE__INSERT;
304-
if (rte->requiredPerms&ACL_UPDATE)
300+
if (perminfo->requiredPerms&ACL_UPDATE)
305301
{
306-
if (!bms_is_empty(rte->updatedCols))
302+
if (!bms_is_empty(perminfo->updatedCols))
307303
required |=SEPG_DB_TABLE__UPDATE;
308304
else
309305
required |=SEPG_DB_TABLE__LOCK;
310306
}
311-
if (rte->requiredPerms&ACL_DELETE)
307+
if (perminfo->requiredPerms&ACL_DELETE)
312308
required |=SEPG_DB_TABLE__DELETE;
313309

314310
/*
@@ -323,10 +319,10 @@ sepgsql_dml_privileges(List *rangeTabls, bool abort_on_violation)
323319
* expand rte->relid into list of OIDs of inheritance hierarchy, then
324320
* checker routine will be invoked for each relations.
325321
*/
326-
if (!rte->inh)
327-
tableIds=list_make1_oid(rte->relid);
322+
if (!perminfo->inh)
323+
tableIds=list_make1_oid(perminfo->relid);
328324
else
329-
tableIds=find_all_inheritors(rte->relid,NoLock,NULL);
325+
tableIds=find_all_inheritors(perminfo->relid,NoLock,NULL);
330326

331327
foreach(li,tableIds)
332328
{
@@ -339,12 +335,12 @@ sepgsql_dml_privileges(List *rangeTabls, bool abort_on_violation)
339335
* child table has different attribute numbers, so we need to fix
340336
* up them.
341337
*/
342-
selectedCols=fixup_inherited_columns(rte->relid,tableOid,
343-
rte->selectedCols);
344-
insertedCols=fixup_inherited_columns(rte->relid,tableOid,
345-
rte->insertedCols);
346-
updatedCols=fixup_inherited_columns(rte->relid,tableOid,
347-
rte->updatedCols);
338+
selectedCols=fixup_inherited_columns(perminfo->relid,tableOid,
339+
perminfo->selectedCols);
340+
insertedCols=fixup_inherited_columns(perminfo->relid,tableOid,
341+
perminfo->insertedCols);
342+
updatedCols=fixup_inherited_columns(perminfo->relid,tableOid,
343+
perminfo->updatedCols);
348344

349345
/*
350346
* check permissions on individual tables

‎contrib/sepgsql/hooks.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,17 +287,17 @@ sepgsql_object_access(ObjectAccessType access,
287287
* Entrypoint of DML permissions
288288
*/
289289
staticbool
290-
sepgsql_exec_check_perms(List*rangeTabls,boolabort)
290+
sepgsql_exec_check_perms(List*rangeTbls,List*rteperminfos,boolabort)
291291
{
292292
/*
293293
* If security provider is stacking and one of them replied 'false' at
294294
* least, we don't need to check any more.
295295
*/
296296
if (next_exec_check_perms_hook&&
297-
!(*next_exec_check_perms_hook) (rangeTabls,abort))
297+
!(*next_exec_check_perms_hook) (rangeTbls,rteperminfos,abort))
298298
return false;
299299

300-
if (!sepgsql_dml_privileges(rangeTabls,abort))
300+
if (!sepgsql_dml_privileges(rangeTbls,rteperminfos,abort))
301301
return false;
302302

303303
return true;

‎contrib/sepgsql/sepgsql.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ extern void sepgsql_object_relabel(const ObjectAddress *object,
274274
/*
275275
* dml.c
276276
*/
277-
externboolsepgsql_dml_privileges(List*rangeTabls,boolabort_on_violation);
277+
externboolsepgsql_dml_privileges(List*rangeTabls,List*rteperminfos,
278+
boolabort_on_violation);
278279

279280
/*
280281
* database.c

‎src/backend/commands/copy.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
109109
{
110110
LOCKMODElockmode=is_from ?RowExclusiveLock :AccessShareLock;
111111
ParseNamespaceItem*nsitem;
112-
RangeTblEntry*rte;
112+
RTEPermissionInfo*perminfo;
113113
TupleDesctupDesc;
114114
List*attnums;
115115
ListCell*cur;
@@ -123,8 +123,9 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
123123

124124
nsitem=addRangeTableEntryForRelation(pstate,rel,lockmode,
125125
NULL, false, false);
126-
rte=nsitem->p_rte;
127-
rte->requiredPerms= (is_from ?ACL_INSERT :ACL_SELECT);
126+
127+
perminfo=nsitem->p_perminfo;
128+
perminfo->requiredPerms= (is_from ?ACL_INSERT :ACL_SELECT);
128129

129130
if (stmt->whereClause)
130131
{
@@ -150,15 +151,15 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
150151
attnums=CopyGetAttnums(tupDesc,rel,stmt->attlist);
151152
foreach(cur,attnums)
152153
{
153-
intattno=lfirst_int(cur)-
154-
FirstLowInvalidHeapAttributeNumber;
154+
intattno;
155+
Bitmapset**bms;
155156

156-
if (is_from)
157-
rte->insertedCols=bms_add_member(rte->insertedCols,attno);
158-
else
159-
rte->selectedCols=bms_add_member(rte->selectedCols,attno);
157+
attno=lfirst_int(cur)-FirstLowInvalidHeapAttributeNumber;
158+
bms=is_from ?&perminfo->insertedCols :&perminfo->selectedCols;
159+
160+
*bms=bms_add_member(*bms,attno);
160161
}
161-
ExecCheckRTPerms(pstate->p_rtable, true);
162+
ExecCheckPermissions(pstate->p_rtable,list_make1(perminfo), true);
162163

163164
/*
164165
* Permission check for row security policies.
@@ -174,7 +175,7 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
174175
* If RLS is not enabled for this, then just fall through to the
175176
* normal non-filtering relation handling.
176177
*/
177-
if (check_enable_rls(rte->relid,InvalidOid, false)==RLS_ENABLED)
178+
if (check_enable_rls(relid,InvalidOid, false)==RLS_ENABLED)
178179
{
179180
SelectStmt*select;
180181
ColumnRef*cr;

‎src/backend/commands/copyfrom.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,12 @@ CopyFrom(CopyFromState cstate)
761761
resultRelInfo=target_resultRelInfo=makeNode(ResultRelInfo);
762762
ExecInitResultRelation(estate,resultRelInfo,1);
763763

764+
/*
765+
* Copy the RTEPermissionInfos into estate as well, so that
766+
* ExecGetInsertedCols() et al will work correctly.
767+
*/
768+
estate->es_rteperminfos=cstate->rteperminfos;
769+
764770
/* Verify the named relation is a valid target for INSERT */
765771
CheckValidResultRel(resultRelInfo,CMD_INSERT);
766772

@@ -1525,9 +1531,12 @@ BeginCopyFrom(ParseState *pstate,
15251531

15261532
initStringInfo(&cstate->attribute_buf);
15271533

1528-
/* Assign range table, we'll needit in CopyFrom. */
1534+
/* Assign range table and rteperminfos, we'll needthem in CopyFrom. */
15291535
if (pstate)
1536+
{
15301537
cstate->range_table=pstate->p_rtable;
1538+
cstate->rteperminfos=pstate->p_rteperminfos;
1539+
}
15311540

15321541
tupDesc=RelationGetDescr(cstate->rel);
15331542
num_phys_attrs=tupDesc->natts;

‎src/backend/commands/view.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ DefineViewRules(Oid viewOid, Query *viewParse, bool replace)
367367
* by 2...
368368
*
369369
* These extra RT entries are not actually used in the query,
370-
* except for run-time locking and permission checking.
370+
* except for run-time locking.
371371
*---------------------------------------------------------------
372372
*/
373373
staticQuery*
@@ -378,7 +378,9 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
378378
ParseNamespaceItem*nsitem;
379379
RangeTblEntry*rt_entry1,
380380
*rt_entry2;
381+
RTEPermissionInfo*rte_perminfo1;
381382
ParseState*pstate;
383+
ListCell*lc;
382384

383385
/*
384386
* Make a copy of the given parsetree. It's not so much that we don't
@@ -405,15 +407,38 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
405407
makeAlias("old",NIL),
406408
false, false);
407409
rt_entry1=nsitem->p_rte;
410+
rte_perminfo1=nsitem->p_perminfo;
408411
nsitem=addRangeTableEntryForRelation(pstate,viewRel,
409412
AccessShareLock,
410413
makeAlias("new",NIL),
411414
false, false);
412415
rt_entry2=nsitem->p_rte;
413416

414-
/* Must override addRangeTableEntry's default access-check flags */
415-
rt_entry1->requiredPerms=0;
416-
rt_entry2->requiredPerms=0;
417+
/*
418+
* Add only the "old" RTEPermissionInfo at the head of view query's list
419+
* and update the other RTEs' perminfoindex accordingly. When rewriting a
420+
* query on the view, ApplyRetrieveRule() will transfer the view
421+
* relation's permission details into this RTEPermissionInfo. That's
422+
* needed because the view's RTE itself will be transposed into a subquery
423+
* RTE that can't carry the permission details; see the code stanza toward
424+
* the end of ApplyRetrieveRule() for how that's done.
425+
*/
426+
viewParse->rteperminfos=lcons(rte_perminfo1,viewParse->rteperminfos);
427+
foreach(lc,viewParse->rtable)
428+
{
429+
RangeTblEntry*rte=lfirst(lc);
430+
431+
if (rte->perminfoindex>0)
432+
rte->perminfoindex+=1;
433+
}
434+
435+
/*
436+
* Also make the "new" RTE's RTEPermissionInfo undiscoverable. This is a
437+
* bit of a hack given that all the non-child RTE_RELATION entries really
438+
* should have a RTEPermissionInfo, but this dummy "new" RTE is going to
439+
* go away anyway in the very near future.
440+
*/
441+
rt_entry2->perminfoindex=0;
417442

418443
new_rt=lcons(rt_entry1,lcons(rt_entry2,viewParse->rtable));
419444

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp