diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/copy.c | 23 | ||||
-rw-r--r-- | src/backend/commands/copyfrom.c | 11 | ||||
-rw-r--r-- | src/backend/commands/view.c | 33 |
3 files changed, 51 insertions, 16 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index db4c9dbc231..b8bd78d358b 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -109,7 +109,7 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt, { LOCKMODE lockmode = is_from ? RowExclusiveLock : AccessShareLock; ParseNamespaceItem *nsitem; - RangeTblEntry *rte; + RTEPermissionInfo *perminfo; TupleDesc tupDesc; List *attnums; ListCell *cur; @@ -123,8 +123,9 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt, nsitem = addRangeTableEntryForRelation(pstate, rel, lockmode, NULL, false, false); - rte = nsitem->p_rte; - rte->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT); + + perminfo = nsitem->p_perminfo; + perminfo->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT); if (stmt->whereClause) { @@ -150,15 +151,15 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt, attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist); foreach(cur, attnums) { - int attno = lfirst_int(cur) - - FirstLowInvalidHeapAttributeNumber; + int attno; + Bitmapset **bms; - if (is_from) - rte->insertedCols = bms_add_member(rte->insertedCols, attno); - else - rte->selectedCols = bms_add_member(rte->selectedCols, attno); + attno = lfirst_int(cur) - FirstLowInvalidHeapAttributeNumber; + bms = is_from ? &perminfo->insertedCols : &perminfo->selectedCols; + + *bms = bms_add_member(*bms, attno); } - ExecCheckRTPerms(pstate->p_rtable, true); + ExecCheckPermissions(pstate->p_rtable, list_make1(perminfo), true); /* * Permission check for row security policies. @@ -174,7 +175,7 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt, * If RLS is not enabled for this, then just fall through to the * normal non-filtering relation handling. */ - if (check_enable_rls(rte->relid, InvalidOid, false) == RLS_ENABLED) + if (check_enable_rls(relid, InvalidOid, false) == RLS_ENABLED) { SelectStmt *select; ColumnRef *cr; diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c index 504afcb8110..0371f512208 100644 --- a/src/backend/commands/copyfrom.c +++ b/src/backend/commands/copyfrom.c @@ -761,6 +761,12 @@ CopyFrom(CopyFromState cstate) resultRelInfo = target_resultRelInfo = makeNode(ResultRelInfo); ExecInitResultRelation(estate, resultRelInfo, 1); + /* + * Copy the RTEPermissionInfos into estate as well, so that + * ExecGetInsertedCols() et al will work correctly. + */ + estate->es_rteperminfos = cstate->rteperminfos; + /* Verify the named relation is a valid target for INSERT */ CheckValidResultRel(resultRelInfo, CMD_INSERT); @@ -1525,9 +1531,12 @@ BeginCopyFrom(ParseState *pstate, initStringInfo(&cstate->attribute_buf); - /* Assign range table, we'll need it in CopyFrom. */ + /* Assign range table and rteperminfos, we'll need them in CopyFrom. */ if (pstate) + { cstate->range_table = pstate->p_rtable; + cstate->rteperminfos = pstate->p_rteperminfos; + } tupDesc = RelationGetDescr(cstate->rel); num_phys_attrs = tupDesc->natts; diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index b5a0fc02e5c..8e3c1efae40 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -367,7 +367,7 @@ DefineViewRules(Oid viewOid, Query *viewParse, bool replace) * by 2... * * These extra RT entries are not actually used in the query, - * except for run-time locking and permission checking. + * except for run-time locking. *--------------------------------------------------------------- */ static Query * @@ -378,7 +378,9 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse) ParseNamespaceItem *nsitem; RangeTblEntry *rt_entry1, *rt_entry2; + RTEPermissionInfo *rte_perminfo1; ParseState *pstate; + ListCell *lc; /* * 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) makeAlias("old", NIL), false, false); rt_entry1 = nsitem->p_rte; + rte_perminfo1 = nsitem->p_perminfo; nsitem = addRangeTableEntryForRelation(pstate, viewRel, AccessShareLock, makeAlias("new", NIL), false, false); rt_entry2 = nsitem->p_rte; - /* Must override addRangeTableEntry's default access-check flags */ - rt_entry1->requiredPerms = 0; - rt_entry2->requiredPerms = 0; + /* + * Add only the "old" RTEPermissionInfo at the head of view query's list + * and update the other RTEs' perminfoindex accordingly. When rewriting a + * query on the view, ApplyRetrieveRule() will transfer the view + * relation's permission details into this RTEPermissionInfo. That's + * needed because the view's RTE itself will be transposed into a subquery + * RTE that can't carry the permission details; see the code stanza toward + * the end of ApplyRetrieveRule() for how that's done. + */ + viewParse->rteperminfos = lcons(rte_perminfo1, viewParse->rteperminfos); + foreach(lc, viewParse->rtable) + { + RangeTblEntry *rte = lfirst(lc); + + if (rte->perminfoindex > 0) + rte->perminfoindex += 1; + } + + /* + * Also make the "new" RTE's RTEPermissionInfo undiscoverable. This is a + * bit of a hack given that all the non-child RTE_RELATION entries really + * should have a RTEPermissionInfo, but this dummy "new" RTE is going to + * go away anyway in the very near future. + */ + rt_entry2->perminfoindex = 0; new_rt = lcons(rt_entry1, lcons(rt_entry2, viewParse->rtable)); |