aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_relation.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_relation.c')
-rw-r--r--src/backend/parser/parse_relation.c178
1 files changed, 99 insertions, 79 deletions
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 4665f0b2b7c..b4878a92eab 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1037,11 +1037,15 @@ markRTEForSelectPriv(ParseState *pstate, int rtindex, AttrNumber col)
if (rte->rtekind == RTE_RELATION)
{
+ RTEPermissionInfo *perminfo;
+
/* Make sure the rel as a whole is marked for SELECT access */
- rte->requiredPerms |= ACL_SELECT;
+ perminfo = getRTEPermissionInfo(pstate->p_rteperminfos, rte);
+ perminfo->requiredPerms |= ACL_SELECT;
/* Must offset the attnum to fit in a bitmapset */
- rte->selectedCols = bms_add_member(rte->selectedCols,
- col - FirstLowInvalidHeapAttributeNumber);
+ perminfo->selectedCols =
+ bms_add_member(perminfo->selectedCols,
+ col - FirstLowInvalidHeapAttributeNumber);
}
else if (rte->rtekind == RTE_JOIN)
{
@@ -1251,10 +1255,13 @@ chooseScalarFunctionAlias(Node *funcexpr, char *funcname,
*
* rte: the new RangeTblEntry for the rel
* rtindex: its index in the rangetable list
+ * perminfo: permission list entry for the rel
* tupdesc: the physical column information
*/
static ParseNamespaceItem *
-buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex, TupleDesc tupdesc)
+buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex,
+ RTEPermissionInfo *perminfo,
+ TupleDesc tupdesc)
{
ParseNamespaceItem *nsitem;
ParseNamespaceColumn *nscolumns;
@@ -1290,6 +1297,7 @@ buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex, TupleDesc tupdesc)
nsitem->p_names = rte->eref;
nsitem->p_rte = rte;
nsitem->p_rtindex = rtindex;
+ nsitem->p_perminfo = perminfo;
nsitem->p_nscolumns = nscolumns;
/* set default visibility flags; might get changed later */
nsitem->p_rel_visible = true;
@@ -1433,6 +1441,7 @@ addRangeTableEntry(ParseState *pstate,
bool inFromCl)
{
RangeTblEntry *rte = makeNode(RangeTblEntry);
+ RTEPermissionInfo *perminfo;
char *refname = alias ? alias->aliasname : relation->relname;
LOCKMODE lockmode;
Relation rel;
@@ -1469,7 +1478,7 @@ addRangeTableEntry(ParseState *pstate,
buildRelationAliases(rel->rd_att, alias, rte->eref);
/*
- * Set flags and access permissions.
+ * Set flags and initialize access permissions.
*
* The initial default on access checks is always check-for-READ-access,
* which is the right thing for all except target tables.
@@ -1478,12 +1487,8 @@ addRangeTableEntry(ParseState *pstate,
rte->inh = inh;
rte->inFromCl = inFromCl;
- rte->requiredPerms = ACL_SELECT;
- rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
- rte->selectedCols = NULL;
- rte->insertedCols = NULL;
- rte->updatedCols = NULL;
- rte->extraUpdatedCols = NULL;
+ perminfo = addRTEPermissionInfo(&pstate->p_rteperminfos, rte);
+ perminfo->requiredPerms = ACL_SELECT;
/*
* Add completed RTE to pstate's range table list, so that we know its
@@ -1497,7 +1502,7 @@ addRangeTableEntry(ParseState *pstate,
* list --- caller must do that if appropriate.
*/
nsitem = buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable),
- rel->rd_att);
+ perminfo, rel->rd_att);
/*
* Drop the rel refcount, but keep the access lock till end of transaction
@@ -1534,6 +1539,7 @@ addRangeTableEntryForRelation(ParseState *pstate,
bool inFromCl)
{
RangeTblEntry *rte = makeNode(RangeTblEntry);
+ RTEPermissionInfo *perminfo;
char *refname = alias ? alias->aliasname : RelationGetRelationName(rel);
Assert(pstate != NULL);
@@ -1557,7 +1563,7 @@ addRangeTableEntryForRelation(ParseState *pstate,
buildRelationAliases(rel->rd_att, alias, rte->eref);
/*
- * Set flags and access permissions.
+ * Set flags and initialize access permissions.
*
* The initial default on access checks is always check-for-READ-access,
* which is the right thing for all except target tables.
@@ -1566,12 +1572,8 @@ addRangeTableEntryForRelation(ParseState *pstate,
rte->inh = inh;
rte->inFromCl = inFromCl;
- rte->requiredPerms = ACL_SELECT;
- rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
- rte->selectedCols = NULL;
- rte->insertedCols = NULL;
- rte->updatedCols = NULL;
- rte->extraUpdatedCols = NULL;
+ perminfo = addRTEPermissionInfo(&pstate->p_rteperminfos, rte);
+ perminfo->requiredPerms = ACL_SELECT;
/*
* Add completed RTE to pstate's range table list, so that we know its
@@ -1585,7 +1587,7 @@ addRangeTableEntryForRelation(ParseState *pstate,
* list --- caller must do that if appropriate.
*/
return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable),
- rel->rd_att);
+ perminfo, rel->rd_att);
}
/*
@@ -1659,21 +1661,15 @@ addRangeTableEntryForSubquery(ParseState *pstate,
rte->eref = eref;
/*
- * Set flags and access permissions.
+ * Set flags.
*
- * Subqueries are never checked for access rights.
+ * Subqueries are never checked for access rights, so no need to perform
+ * addRTEPermissionInfo().
*/
rte->lateral = lateral;
rte->inh = false; /* never true for subqueries */
rte->inFromCl = inFromCl;
- rte->requiredPerms = 0;
- rte->checkAsUser = InvalidOid;
- rte->selectedCols = NULL;
- rte->insertedCols = NULL;
- rte->updatedCols = NULL;
- rte->extraUpdatedCols = NULL;
-
/*
* Add completed RTE to pstate's range table list, so that we know its
* index. But we don't add it to the join list --- caller must do that if
@@ -1990,20 +1986,13 @@ addRangeTableEntryForFunction(ParseState *pstate,
/*
* Set flags and access permissions.
*
- * Functions are never checked for access rights (at least, not by the RTE
- * permissions mechanism).
+ * Functions are never checked for access rights (at least, not by
+ * ExecCheckPermissions()), so no need to perform addRTEPermissionInfo().
*/
rte->lateral = lateral;
rte->inh = false; /* never true for functions */
rte->inFromCl = inFromCl;
- rte->requiredPerms = 0;
- rte->checkAsUser = InvalidOid;
- rte->selectedCols = NULL;
- rte->insertedCols = NULL;
- rte->updatedCols = NULL;
- rte->extraUpdatedCols = NULL;
-
/*
* Add completed RTE to pstate's range table list, so that we know its
* index. But we don't add it to the join list --- caller must do that if
@@ -2015,7 +2004,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
* Build a ParseNamespaceItem, but don't add it to the pstate's namespace
* list --- caller must do that if appropriate.
*/
- return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable),
+ return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable), NULL,
tupdesc);
}
@@ -2082,20 +2071,13 @@ addRangeTableEntryForTableFunc(ParseState *pstate,
/*
* Set flags and access permissions.
*
- * Tablefuncs are never checked for access rights (at least, not by the
- * RTE permissions mechanism).
+ * Tablefuncs are never checked for access rights (at least, not by
+ * ExecCheckPermissions()), so no need to perform addRTEPermissionInfo().
*/
rte->lateral = lateral;
rte->inh = false; /* never true for tablefunc RTEs */
rte->inFromCl = inFromCl;
- rte->requiredPerms = 0;
- rte->checkAsUser = InvalidOid;
- rte->selectedCols = NULL;
- rte->insertedCols = NULL;
- rte->updatedCols = NULL;
- rte->extraUpdatedCols = NULL;
-
/*
* Add completed RTE to pstate's range table list, so that we know its
* index. But we don't add it to the join list --- caller must do that if
@@ -2170,19 +2152,13 @@ addRangeTableEntryForValues(ParseState *pstate,
/*
* Set flags and access permissions.
*
- * Subqueries are never checked for access rights.
+ * Subqueries are never checked for access rights, so no need to perform
+ * addRTEPermissionInfo().
*/
rte->lateral = lateral;
rte->inh = false; /* never true for values RTEs */
rte->inFromCl = inFromCl;
- rte->requiredPerms = 0;
- rte->checkAsUser = InvalidOid;
- rte->selectedCols = NULL;
- rte->insertedCols = NULL;
- rte->updatedCols = NULL;
- rte->extraUpdatedCols = NULL;
-
/*
* Add completed RTE to pstate's range table list, so that we know its
* index. But we don't add it to the join list --- caller must do that if
@@ -2267,19 +2243,13 @@ addRangeTableEntryForJoin(ParseState *pstate,
/*
* Set flags and access permissions.
*
- * Joins are never checked for access rights.
+ * Joins are never checked for access rights, so no need to perform
+ * addRTEPermissionInfo().
*/
rte->lateral = false;
rte->inh = false; /* never true for joins */
rte->inFromCl = inFromCl;
- rte->requiredPerms = 0;
- rte->checkAsUser = InvalidOid;
- rte->selectedCols = NULL;
- rte->insertedCols = NULL;
- rte->updatedCols = NULL;
- rte->extraUpdatedCols = NULL;
-
/*
* Add completed RTE to pstate's range table list, so that we know its
* index. But we don't add it to the join list --- caller must do that if
@@ -2294,6 +2264,7 @@ addRangeTableEntryForJoin(ParseState *pstate,
nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
nsitem->p_names = rte->eref;
nsitem->p_rte = rte;
+ nsitem->p_perminfo = NULL;
nsitem->p_rtindex = list_length(pstate->p_rtable);
nsitem->p_nscolumns = nscolumns;
/* set default visibility flags; might get changed later */
@@ -2417,19 +2388,13 @@ addRangeTableEntryForCTE(ParseState *pstate,
/*
* Set flags and access permissions.
*
- * Subqueries are never checked for access rights.
+ * Subqueries are never checked for access rights, so no need to perform
+ * addRTEPermissionInfo().
*/
rte->lateral = false;
rte->inh = false; /* never true for subqueries */
rte->inFromCl = inFromCl;
- rte->requiredPerms = 0;
- rte->checkAsUser = InvalidOid;
- rte->selectedCols = NULL;
- rte->insertedCols = NULL;
- rte->updatedCols = NULL;
- rte->extraUpdatedCols = NULL;
-
/*
* Add completed RTE to pstate's range table list, so that we know its
* index. But we don't add it to the join list --- caller must do that if
@@ -2543,16 +2508,13 @@ addRangeTableEntryForENR(ParseState *pstate,
/*
* Set flags and access permissions.
*
- * ENRs are never checked for access rights.
+ * ENRs are never checked for access rights, so no need to perform
+ * addRTEPermissionInfo().
*/
rte->lateral = false;
rte->inh = false; /* never true for ENRs */
rte->inFromCl = inFromCl;
- rte->requiredPerms = 0;
- rte->checkAsUser = InvalidOid;
- rte->selectedCols = NULL;
-
/*
* Add completed RTE to pstate's range table list, so that we know its
* index. But we don't add it to the join list --- caller must do that if
@@ -2564,7 +2526,7 @@ addRangeTableEntryForENR(ParseState *pstate,
* Build a ParseNamespaceItem, but don't add it to the pstate's namespace
* list --- caller must do that if appropriate.
*/
- return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable),
+ return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable), NULL,
tupdesc);
}
@@ -3189,6 +3151,7 @@ expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem,
int sublevels_up, bool require_col_privs, int location)
{
RangeTblEntry *rte = nsitem->p_rte;
+ RTEPermissionInfo *perminfo = nsitem->p_perminfo;
List *names,
*vars;
ListCell *name,
@@ -3206,7 +3169,10 @@ expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem,
* relation of UPDATE/DELETE, which cannot be under a join.)
*/
if (rte->rtekind == RTE_RELATION)
- rte->requiredPerms |= ACL_SELECT;
+ {
+ Assert(perminfo != NULL);
+ perminfo->requiredPerms |= ACL_SELECT;
+ }
forboth(name, names, var, vars)
{
@@ -3855,3 +3821,57 @@ isQueryUsingTempRelation_walker(Node *node, void *context)
isQueryUsingTempRelation_walker,
context);
}
+
+/*
+ * addRTEPermissionInfo
+ * Creates RTEPermissionInfo for a given RTE and adds it into the
+ * provided list.
+ *
+ * Returns the RTEPermissionInfo and sets rte->perminfoindex.
+ */
+RTEPermissionInfo *
+addRTEPermissionInfo(List **rteperminfos, RangeTblEntry *rte)
+{
+ RTEPermissionInfo *perminfo;
+
+ Assert(rte->rtekind == RTE_RELATION);
+ Assert(rte->perminfoindex == 0);
+
+ /* Nope, so make one and add to the list. */
+ perminfo = makeNode(RTEPermissionInfo);
+ perminfo->relid = rte->relid;
+ perminfo->inh = rte->inh;
+ /* Other information is set by fetching the node as and where needed. */
+
+ *rteperminfos = lappend(*rteperminfos, perminfo);
+
+ /* Note its index (1-based!) */
+ rte->perminfoindex = list_length(*rteperminfos);
+
+ return perminfo;
+}
+
+/*
+ * getRTEPermissionInfo
+ * Find RTEPermissionInfo for a given relation in the provided list.
+ *
+ * This is a simple list_nth() operation, though it's good to have the
+ * function for the various sanity checks.
+ */
+RTEPermissionInfo *
+getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
+{
+ RTEPermissionInfo *perminfo;
+
+ if (rte->perminfoindex == 0 ||
+ rte->perminfoindex > list_length(rteperminfos))
+ elog(ERROR, "invalid perminfoindex %d in RTE with relid %u",
+ rte->perminfoindex, rte->relid);
+ perminfo = list_nth_node(RTEPermissionInfo, rteperminfos,
+ rte->perminfoindex - 1);
+ if (perminfo->relid != rte->relid)
+ elog(ERROR, "permission info at index %u (with relid=%u) does not match provided RTE (with relid=%u)",
+ rte->perminfoindex, perminfo->relid, rte->relid);
+
+ return perminfo;
+}