aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2023-02-20 16:00:42 +0100
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2023-02-20 16:00:42 +0100
commita316a3bc6d3f57e3fe0d287d11eb4f114388b1b6 (patch)
tree8d243e7406590a268c181e5c7d40d34deee5d2f6 /src
parent94cad7a3e6040e23d51b9d4869fc20e3e56ddbf7 (diff)
downloadpostgresql-a316a3bc6d3f57e3fe0d287d11eb4f114388b1b6.tar.gz
postgresql-a316a3bc6d3f57e3fe0d287d11eb4f114388b1b6.zip
Correctly set userid of subquery relations' child rels
The RelOptInfo->userid field (the user ID to check permissions as) of an "otherrel" relation was being copied from its parent relation, which is correct in most cases but wrong when the parent is a subquery. In that case, using the value from the RTEPermissionInfo of the child itself is the appropriate thing to do. Coming up with a test case where user-visible behavior changes proves hard enough, so we don't add one here. Bug introduced by a61b1f74823c, discovered by Amit while reviewing nearby code. Author: Amit Langote <amitlangote09@gmail.com> Discussion: https://postgr.es/m/CA+HiwqE0WY_AhLnGtTsY7eYebG212XWbM-D8gr2A_ToOHyCywQ@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/util/relnode.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index a70a16238a8..d29a25f8aa6 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -233,12 +233,22 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
rel->serverid = InvalidOid;
if (rte->rtekind == RTE_RELATION)
{
+ Assert(parent == NULL ||
+ parent->rtekind == RTE_RELATION ||
+ parent->rtekind == RTE_SUBQUERY);
+
/*
- * Get the userid from the relation's RTEPermissionInfo, though only
- * the tables mentioned in query are assigned RTEPermissionInfos.
- * Child relations (otherrels) simply use the parent's value.
+ * For any RELATION rte, we need a userid with which to check
+ * permission access. Baserels simply use their own
+ * RTEPermissionInfo's checkAsUser.
+ *
+ * For otherrels normally there's no RTEPermissionInfo, so we use the
+ * parent's, which normally has one. The exceptional case is that the
+ * parent is a subquery, in which case the otherrel will have its own.
*/
- if (parent == NULL)
+ if (rel->reloptkind == RELOPT_BASEREL ||
+ (rel->reloptkind == RELOPT_OTHER_MEMBER_REL &&
+ parent->rtekind == RTE_SUBQUERY))
{
RTEPermissionInfo *perminfo;