aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/analyze.c68
-rw-r--r--src/backend/parser/parse_clause.c9
-rw-r--r--src/backend/parser/parse_merge.c9
-rw-r--r--src/backend/parser/parse_relation.c178
-rw-r--r--src/backend/parser/parse_target.c18
-rw-r--r--src/backend/parser/parse_utilcmd.c6
6 files changed, 167 insertions, 121 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 6688c2a865b..2e593aed2bc 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -518,6 +518,7 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
/* done building the range table and jointree */
qry->rtable = pstate->p_rtable;
+ qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
qry->hasSubLinks = pstate->p_hasSubLinks;
@@ -546,11 +547,12 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
List *exprList = NIL;
bool isGeneralSelect;
List *sub_rtable;
+ List *sub_rteperminfos;
List *sub_namespace;
List *icolumns;
List *attrnos;
ParseNamespaceItem *nsitem;
- RangeTblEntry *rte;
+ RTEPermissionInfo *perminfo;
ListCell *icols;
ListCell *attnos;
ListCell *lc;
@@ -594,17 +596,19 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
/*
* If a non-nil rangetable/namespace was passed in, and we are doing
- * INSERT/SELECT, arrange to pass the rangetable/namespace down to the
- * SELECT. This can only happen if we are inside a CREATE RULE, and in
- * that case we want the rule's OLD and NEW rtable entries to appear as
- * part of the SELECT's rtable, not as outer references for it. (Kluge!)
- * The SELECT's joinlist is not affected however. We must do this before
- * adding the target table to the INSERT's rtable.
+ * INSERT/SELECT, arrange to pass the rangetable/rteperminfos/namespace
+ * down to the SELECT. This can only happen if we are inside a CREATE
+ * RULE, and in that case we want the rule's OLD and NEW rtable entries to
+ * appear as part of the SELECT's rtable, not as outer references for it.
+ * (Kluge!) The SELECT's joinlist is not affected however. We must do
+ * this before adding the target table to the INSERT's rtable.
*/
if (isGeneralSelect)
{
sub_rtable = pstate->p_rtable;
pstate->p_rtable = NIL;
+ sub_rteperminfos = pstate->p_rteperminfos;
+ pstate->p_rteperminfos = NIL;
sub_namespace = pstate->p_namespace;
pstate->p_namespace = NIL;
}
@@ -669,6 +673,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
* the target column's type, which we handle below.
*/
sub_pstate->p_rtable = sub_rtable;
+ sub_pstate->p_rteperminfos = sub_rteperminfos;
sub_pstate->p_joinexprs = NIL; /* sub_rtable has no joins */
sub_pstate->p_namespace = sub_namespace;
sub_pstate->p_resolve_unknowns = false;
@@ -894,7 +899,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
* Generate query's target list using the computed list of expressions.
* Also, mark all the target columns as needing insert permissions.
*/
- rte = pstate->p_target_nsitem->p_rte;
+ perminfo = pstate->p_target_nsitem->p_perminfo;
qry->targetList = NIL;
Assert(list_length(exprList) <= list_length(icolumns));
forthree(lc, exprList, icols, icolumns, attnos, attrnos)
@@ -910,8 +915,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
false);
qry->targetList = lappend(qry->targetList, tle);
- rte->insertedCols = bms_add_member(rte->insertedCols,
- attr_num - FirstLowInvalidHeapAttributeNumber);
+ perminfo->insertedCols = bms_add_member(perminfo->insertedCols,
+ attr_num - FirstLowInvalidHeapAttributeNumber);
}
/*
@@ -938,6 +943,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
/* done building the range table and jointree */
qry->rtable = pstate->p_rtable;
+ qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
@@ -1096,8 +1102,6 @@ transformOnConflictClause(ParseState *pstate,
* (We'll check the actual target relation, instead.)
*/
exclRte->relkind = RELKIND_COMPOSITE_TYPE;
- exclRte->requiredPerms = 0;
- /* other permissions fields in exclRte are already empty */
/* Create EXCLUDED rel's targetlist for use by EXPLAIN */
exclRelTlist = BuildOnConflictExcludedTargetlist(targetrel,
@@ -1391,6 +1395,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
resolveTargetListUnknowns(pstate, qry->targetList);
qry->rtable = pstate->p_rtable;
+ qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
qry->hasSubLinks = pstate->p_hasSubLinks;
@@ -1619,6 +1624,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
linitial(stmt->lockingClause))->strength))));
qry->rtable = pstate->p_rtable;
+ qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
qry->hasSubLinks = pstate->p_hasSubLinks;
@@ -1865,6 +1871,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
qry->limitOption = stmt->limitOption;
qry->rtable = pstate->p_rtable;
+ qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
qry->hasSubLinks = pstate->p_hasSubLinks;
@@ -2339,6 +2346,7 @@ transformReturnStmt(ParseState *pstate, ReturnStmt *stmt)
if (pstate->p_resolve_unknowns)
resolveTargetListUnknowns(pstate, qry->targetList);
qry->rtable = pstate->p_rtable;
+ qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
qry->hasSubLinks = pstate->p_hasSubLinks;
qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
@@ -2405,6 +2413,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
qry->targetList = transformUpdateTargetList(pstate, stmt->targetList);
qry->rtable = pstate->p_rtable;
+ qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
@@ -2423,7 +2432,7 @@ List *
transformUpdateTargetList(ParseState *pstate, List *origTlist)
{
List *tlist = NIL;
- RangeTblEntry *target_rte;
+ RTEPermissionInfo *target_perminfo;
ListCell *orig_tl;
ListCell *tl;
@@ -2435,7 +2444,7 @@ transformUpdateTargetList(ParseState *pstate, List *origTlist)
pstate->p_next_resno = RelationGetNumberOfAttributes(pstate->p_target_relation) + 1;
/* Prepare non-junk columns for assignment to target table */
- target_rte = pstate->p_target_nsitem->p_rte;
+ target_perminfo = pstate->p_target_nsitem->p_perminfo;
orig_tl = list_head(origTlist);
foreach(tl, tlist)
@@ -2476,8 +2485,8 @@ transformUpdateTargetList(ParseState *pstate, List *origTlist)
origTarget->location);
/* Mark the target column as requiring update permissions */
- target_rte->updatedCols = bms_add_member(target_rte->updatedCols,
- attrno - FirstLowInvalidHeapAttributeNumber);
+ target_perminfo->updatedCols = bms_add_member(target_perminfo->updatedCols,
+ attrno - FirstLowInvalidHeapAttributeNumber);
orig_tl = lnext(origTlist, orig_tl);
}
@@ -2764,6 +2773,7 @@ transformPLAssignStmt(ParseState *pstate, PLAssignStmt *stmt)
&qry->targetList);
qry->rtable = pstate->p_rtable;
+ qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
qry->hasSubLinks = pstate->p_hasSubLinks;
@@ -3242,9 +3252,16 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
switch (rte->rtekind)
{
case RTE_RELATION:
- applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
- pushedDown);
- rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
+ {
+ RTEPermissionInfo *perminfo;
+
+ applyLockingClause(qry, i,
+ lc->strength,
+ lc->waitPolicy,
+ pushedDown);
+ perminfo = getRTEPermissionInfo(qry->rteperminfos, rte);
+ perminfo->requiredPerms |= ACL_SELECT_FOR_UPDATE;
+ }
break;
case RTE_SUBQUERY:
applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
@@ -3324,9 +3341,16 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
switch (rte->rtekind)
{
case RTE_RELATION:
- applyLockingClause(qry, i, lc->strength,
- lc->waitPolicy, pushedDown);
- rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
+ {
+ RTEPermissionInfo *perminfo;
+
+ applyLockingClause(qry, i,
+ lc->strength,
+ lc->waitPolicy,
+ pushedDown);
+ perminfo = getRTEPermissionInfo(qry->rteperminfos, rte);
+ perminfo->requiredPerms |= ACL_SELECT_FOR_UPDATE;
+ }
break;
case RTE_SUBQUERY:
applyLockingClause(qry, i, lc->strength,
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index e01c0734d17..856839f379d 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -225,7 +225,7 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
* analysis, we will add the ACL_SELECT bit back again; see
* markVarForSelectPriv and its callers.
*/
- nsitem->p_rte->requiredPerms = requiredPerms;
+ nsitem->p_perminfo->requiredPerms = requiredPerms;
/*
* If UPDATE/DELETE, add table to joinlist and namespace.
@@ -3226,16 +3226,17 @@ transformOnConflictArbiter(ParseState *pstate,
if (infer->conname)
{
Oid relid = RelationGetRelid(pstate->p_target_relation);
- RangeTblEntry *rte = pstate->p_target_nsitem->p_rte;
+ RTEPermissionInfo *perminfo = pstate->p_target_nsitem->p_perminfo;
Bitmapset *conattnos;
conattnos = get_relation_constraint_attnos(relid, infer->conname,
false, constraint);
/* Make sure the rel as a whole is marked for SELECT access */
- rte->requiredPerms |= ACL_SELECT;
+ perminfo->requiredPerms |= ACL_SELECT;
/* Mark the constrained columns as requiring SELECT access */
- rte->selectedCols = bms_add_members(rte->selectedCols, conattnos);
+ perminfo->selectedCols = bms_add_members(perminfo->selectedCols,
+ conattnos);
}
}
diff --git a/src/backend/parser/parse_merge.c b/src/backend/parser/parse_merge.c
index 62c2ff69f0c..3844f2b45f3 100644
--- a/src/backend/parser/parse_merge.c
+++ b/src/backend/parser/parse_merge.c
@@ -215,6 +215,7 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
*/
qry->targetList = NIL;
qry->rtable = pstate->p_rtable;
+ qry->rteperminfos = pstate->p_rteperminfos;
/*
* Transform the join condition. This includes references to the target
@@ -287,7 +288,7 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
{
List *exprList = NIL;
ListCell *lc;
- RangeTblEntry *rte;
+ RTEPermissionInfo *perminfo;
ListCell *icols;
ListCell *attnos;
List *icolumns;
@@ -346,7 +347,7 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
* of expressions. Also, mark all the target columns as
* needing insert permissions.
*/
- rte = pstate->p_target_nsitem->p_rte;
+ perminfo = pstate->p_target_nsitem->p_perminfo;
forthree(lc, exprList, icols, icolumns, attnos, attrnos)
{
Expr *expr = (Expr *) lfirst(lc);
@@ -360,8 +361,8 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
false);
action->targetList = lappend(action->targetList, tle);
- rte->insertedCols =
- bms_add_member(rte->insertedCols,
+ perminfo->insertedCols =
+ bms_add_member(perminfo->insertedCols,
attr_num - FirstLowInvalidHeapAttributeNumber);
}
}
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;
+}
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 8e0d6fd01f1..56d64c88516 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -1132,7 +1132,7 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
*
* Note: this code is a lot like transformColumnRef; it's tempting to
* call that instead and then replace the resulting whole-row Var with
- * a list of Vars. However, that would leave us with the RTE's
+ * a list of Vars. However, that would leave us with the relation's
* selectedCols bitmap showing the whole row as needing select
* permission, as well as the individual columns. That would be
* incorrect (since columns added later shouldn't need select
@@ -1367,6 +1367,7 @@ ExpandSingleTable(ParseState *pstate, ParseNamespaceItem *nsitem,
else
{
RangeTblEntry *rte = nsitem->p_rte;
+ RTEPermissionInfo *perminfo = nsitem->p_perminfo;
List *vars;
ListCell *l;
@@ -1381,7 +1382,10 @@ ExpandSingleTable(ParseState *pstate, ParseNamespaceItem *nsitem,
* target 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;
+ }
/* Require read access to each column */
foreach(l, vars)
@@ -1414,11 +1418,11 @@ ExpandRowReference(ParseState *pstate, Node *expr,
/*
* If the rowtype expression is a whole-row Var, we can expand the fields
* as simple Vars. Note: if the RTE is a relation, this case leaves us
- * with the RTE's selectedCols bitmap showing the whole row as needing
- * select permission, as well as the individual columns. However, we can
- * only get here for weird notations like (table.*).*, so it's not worth
- * trying to clean up --- arguably, the permissions marking is correct
- * anyway for such cases.
+ * with its RTEPermissionInfo's selectedCols bitmap showing the whole row
+ * as needing select permission, as well as the individual columns.
+ * However, we can only get here for weird notations like (table.*).*, so
+ * it's not worth trying to clean up --- arguably, the permissions marking
+ * is correct anyway for such cases.
*/
if (IsA(expr, Var) &&
((Var *) expr)->varattno == InvalidAttrNumber)
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 36791d88179..342a1791338 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -3023,9 +3023,6 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
AccessShareLock,
makeAlias("new", NIL),
false, false);
- /* Must override addRangeTableEntry's default access-check flags */
- oldnsitem->p_rte->requiredPerms = 0;
- newnsitem->p_rte->requiredPerms = 0;
/*
* They must be in the namespace too for lookup purposes, but only add the
@@ -3081,6 +3078,7 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
nothing_qry->commandType = CMD_NOTHING;
nothing_qry->rtable = pstate->p_rtable;
+ nothing_qry->rteperminfos = pstate->p_rteperminfos;
nothing_qry->jointree = makeFromExpr(NIL, NULL); /* no join wanted */
*actions = list_make1(nothing_qry);
@@ -3123,8 +3121,6 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
AccessShareLock,
makeAlias("new", NIL),
false, false);
- oldnsitem->p_rte->requiredPerms = 0;
- newnsitem->p_rte->requiredPerms = 0;
addNSItemToQuery(sub_pstate, oldnsitem, false, true, false);
addNSItemToQuery(sub_pstate, newnsitem, false, true, false);