On 2022-Dec-12, Amit Langote wrote:

> On Sun, Dec 11, 2022 at 6:25 PM Amit Langote <amitlangot...@gmail.com> wrote:
> > I've attached 0001 to remove those extraneous code blocks and add a
> > comment mentioning that userid need not be recomputed.
> >
> > While staring at the build_simple_rel() bit mentioned above, I
> > realized that this code fails to set userid correctly in the
> > inheritance parent rels that are child relations of subquery parent
> > relations, such as UNION ALL subqueries.  In that case, instead of
> > copying the userid (= 0) of the parent rel, the child should look up
> > its own RTEPermissionInfo, which should be there, and use the
> > checkAsUser value from there.  I've attached 0002 to fix this hole.  I
> > am not sure whether there's a way to add a test case for this in the
> > core suite.
> 
> Ah, I realized we could just expand the test added by 553d2ec27 with a
> wrapper view (to test checkAsUser functionality) and a UNION ALL query
> over the view (to test this change).

Hmm, but if I run this test without the code change in 0002, the test
also passes (to wit: the plan still has two hash joins), so I understand
that either you're testing something that's not changed by the patch,
or the test case itself isn't really what you wanted.

As for 0001, it seems simpler to me to put the 'userid' variable in the
same scope as 'onerel', and then compute it just once and don't bother
with it at all afterwards, as in the attached.

-- 
Álvaro Herrera               48°01'N 7°57'E  —  https://www.EnterpriseDB.com/
Al principio era UNIX, y UNIX habló y dijo: "Hello world\n".
No dijo "Hello New Jersey\n", ni "Hello USA\n".
gpg: Firmado el lun 16 ene 2023 17:23:19 CET
gpg:                usando RSA clave E2C96E4A9BCA7E92A8E3DA551C20ACB9D5C564AE
gpg: Firma correcta de "Álvaro Herrera <alvhe...@alvh.no-ip.org>" [absoluta]
gpg:                 alias "Álvaro Herrera (PostgreSQL Global Development Group) <alvhe...@postgresql.org>" [absoluta]
gpg:                 alias "Álvaro Herrera (2ndQuadrant) <alvhe...@2ndquadrant.com>" [absoluta]
commit cdc09715305d98457c8240b579528b7835c39d58
Author:     Alvaro Herrera <alvhe...@alvh.no-ip.org> [Álvaro Herrera <alvhe...@alvh.no-ip.org>]
AuthorDate: Sun Dec 11 18:12:05 2022 +0900
CommitDate: Mon Jan 16 17:23:19 2023 +0100

    Remove some dead code in selfuncs.c
    
    RelOptInfo.userid is the same for all relations in a given
    inheritance tree, so the code in examine_variable() and
    example_simple_variable() that wants to repeat the ACL checks on
    the root parent rel instead of a given leaf child relations need not
    recompute userid too.
    
    Author: Amit Langote
    Reported-by: Justin Pryzby
    Discussion: https://postgr.es/m/20221210201753.ga27...@telsasoft.com

diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 75bc20c7c9..0a5632699d 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -500,7 +500,6 @@ find_join_rel(PlannerInfo *root, Relids relids)
  *
  * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
  * called for the join relation.
- *
  */
 static void
 set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel,
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 57de51f0db..4e4888dde4 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -5080,6 +5080,18 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 		 */
 		ListCell   *ilist;
 		ListCell   *slist;
+		Oid			userid;
+
+		/*
+		 * Determine the user ID to use for privilege checks: either
+		 * onerel->userid if it's set (e.g., in case we're accessing the table
+		 * via a view), or the current user otherwise.
+		 *
+		 * If we drill down to child relations, we keep using the same userid:
+		 * it's going to be the same anyway, due to how we set up the relation
+		 * tree (q.v. build_simple_rel).
+		 */
+		userid = OidIsValid(onerel->userid) ? onerel->userid : GetUserId();
 
 		foreach(ilist, onerel->indexlist)
 		{
@@ -5150,18 +5162,10 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 							{
 								/* Get index's table for permission check */
 								RangeTblEntry *rte;
-								Oid			userid;
 
 								rte = planner_rt_fetch(index->rel->relid, root);
 								Assert(rte->rtekind == RTE_RELATION);
 
-								/*
-								 * Use onerel->userid if it's set, in case
-								 * we're accessing the table via a view.
-								 */
-								userid = OidIsValid(onerel->userid) ?
-									onerel->userid : GetUserId();
-
 								/*
 								 * For simplicity, we insist on the whole
 								 * table being selectable, rather than trying
@@ -5212,9 +5216,6 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 										rte = planner_rt_fetch(varno, root);
 										Assert(rte->rtekind == RTE_RELATION);
 
-										userid = OidIsValid(onerel->userid) ?
-											onerel->userid : GetUserId();
-
 										vardata->acl_ok =
 											rte->securityQuals == NIL &&
 											(pg_class_aclcheck(rte->relid,
@@ -5281,8 +5282,6 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 				/* found a match, see if we can extract pg_statistic row */
 				if (equal(node, expr))
 				{
-					Oid			userid;
-
 					/*
 					 * XXX Not sure if we should cache the tuple somewhere.
 					 * Now we just create a new copy every time.
@@ -5292,13 +5291,6 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 
 					vardata->freefunc = ReleaseDummy;
 
-					/*
-					 * Use onerel->userid if it's set, in case we're accessing
-					 * the table via a view.
-					 */
-					userid = OidIsValid(onerel->userid) ?
-						onerel->userid : GetUserId();
-
 					/*
 					 * For simplicity, we insist on the whole table being
 					 * selectable, rather than trying to identify which
@@ -5345,9 +5337,6 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 							rte = planner_rt_fetch(varno, root);
 							Assert(rte->rtekind == RTE_RELATION);
 
-							userid = OidIsValid(onerel->userid) ?
-								onerel->userid : GetUserId();
-
 							vardata->acl_ok =
 								rte->securityQuals == NIL &&
 								(pg_class_aclcheck(rte->relid,
@@ -5486,9 +5475,10 @@ examine_simple_variable(PlannerInfo *root, Var *var,
 				rte = planner_rt_fetch(varno, root);
 				Assert(rte->rtekind == RTE_RELATION);
 
-				userid = OidIsValid(onerel->userid) ?
-					onerel->userid : GetUserId();
-
+				/*
+				 * Fine to use the same userid as it's the same in all
+				 * relations of a given inheritance tree.
+				 */
 				vardata->acl_ok =
 					rte->securityQuals == NIL &&
 					((pg_class_aclcheck(rte->relid, userid,

Reply via email to