diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/analyze.c | 68 | ||||
-rw-r--r-- | src/backend/parser/parse_clause.c | 9 | ||||
-rw-r--r-- | src/backend/parser/parse_merge.c | 9 | ||||
-rw-r--r-- | src/backend/parser/parse_relation.c | 178 | ||||
-rw-r--r-- | src/backend/parser/parse_target.c | 18 | ||||
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 6 |
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); |