On 2018/11/01 20:34, Dilip Kumar wrote:
> On Mon, Oct 29, 2018 at 2:53 PM Amit Langote wrote:
>> Anyway, why don't we just use the child table's AppendRelInfo to get the
>> parent's version of varattno instead of creating a new function?  It can
>> be done as shown in the attached revised version of the portion of the
>> patch changing selfuncs.c.  Please take a look.
> 
> +1

Okay, here are two patches:

0001 adds a new RelOptInfo member inh_root_parent that's set for
inheritance child otherrels and contains the RT index of the inheritance
parent table mentioned in the query from which they originated.

0002 is your patch that modifies examine_variable, etc. to use the
permissions granted on parent before reading stats on otherrel inheritance
child tables. I've added your name as the author in the 2nd patch.

Thanks,
Amit
From 04c2c1c2876995322309dc791866c617e2c4a539 Mon Sep 17 00:00:00 2001
From: amit <amitlangot...@gmail.com>
Date: Fri, 26 Oct 2018 16:45:59 +0900
Subject: [PATCH 1/2] Store inheritance root parent index in otherrel's
 RelOptInfo

Although it's set by build_simple_rel, it's not being used by any
code yet.
---
 src/backend/nodes/outfuncs.c         |  1 +
 src/backend/optimizer/util/relnode.c | 14 ++++++++++++++
 src/include/nodes/relation.h         |  4 ++++
 3 files changed, 19 insertions(+)

diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 69731ccdea..53a657c0ae 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -2371,6 +2371,7 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node)
        WRITE_BOOL_FIELD(consider_partitionwise_join);
        WRITE_BITMAPSET_FIELD(top_parent_relids);
        WRITE_NODE_FIELD(partitioned_child_rels);
+       WRITE_UINT_FIELD(inh_root_parent);
 }
 
 static void
diff --git a/src/backend/optimizer/util/relnode.c 
b/src/backend/optimizer/util/relnode.c
index 39f5729b91..29ba19349f 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -215,9 +215,23 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo 
*parent)
                        rel->top_parent_relids = parent->top_parent_relids;
                else
                        rel->top_parent_relids = bms_copy(parent->relids);
+
+               /*
+                * For inheritance child relations, we also set inh_root_parent.
+                * Note that 'parent' might itself be a child (a sub-partitioned
+                * partition), in which case we simply use its value of
+                * inh_root_parent.
+                */
+               if (parent->rtekind == RTE_RELATION)
+                       rel->inh_root_parent = parent->inh_root_parent > 0 ?
+                                                                               
parent->inh_root_parent :
+                                                                               
parent->relid;
        }
        else
+       {
                rel->top_parent_relids = NULL;
+               rel->inh_root_parent = 0;
+       }
 
        /* Check type of rtable entry */
        switch (rte->rtekind)
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 88d37236f7..bbc1408d05 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -703,6 +703,10 @@ typedef struct RelOptInfo
        List      **partexprs;          /* Non-nullable partition key 
expressions. */
        List      **nullable_partexprs; /* Nullable partition key expressions. 
*/
        List       *partitioned_child_rels; /* List of RT indexes. */
+
+       Index           inh_root_parent;        /* For otherrels, this is the 
RT index of
+                                                                        * 
inheritance table mentioned in the query
+                                                                        * from 
which this relation originated */
 } RelOptInfo;
 
 /*
-- 
2.11.0

From e7ce03017391f7472a9d30b039447d66f1d956c6 Mon Sep 17 00:00:00 2001
From: amit <amitlangot...@gmail.com>
Date: Fri, 2 Nov 2018 16:48:25 +0900
Subject: [PATCH 2/2] Use permissions granted on parent to read stats on
 otherrel children

Author: Dilip Kumar
Reviewed by: Amit Langote
---
 src/backend/utils/adt/selfuncs.c | 58 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 55 insertions(+), 3 deletions(-)

diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index e0ece74bb9..698a4eca63 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -4924,8 +4924,18 @@ examine_variable(PlannerInfo *root, Node *node, int 
varRelid,
                                                        {
                                                                /* Get index's 
table for permission check */
                                                                RangeTblEntry 
*rte;
+                                                               RelOptInfo      
*rel = index->rel;
+
+                                                               /*
+                                                                * For a child 
table, check permissions using
+                                                                * parent's RTE.
+                                                                */
+                                                               if 
(rel->inh_root_parent)
+                                                                       rte = 
planner_rt_fetch(rel->inh_root_parent,
+                                                                               
                                   root);
+                                                               else
+                                                                       rte = 
planner_rt_fetch(rel->relid, root);
 
-                                                               rte = 
planner_rt_fetch(index->rel->relid, root);
                                                                
Assert(rte->rtekind == RTE_RELATION);
 
                                                                /*
@@ -4998,11 +5008,53 @@ examine_simple_variable(PlannerInfo *root, Var *var,
 
                if (HeapTupleIsValid(vardata->statsTuple))
                {
+                       RelOptInfo *rel;
+                       Oid     relid = rte->relid;
+                       int     varattno = var->varattno;
+
+                       rel = root->simple_rel_array[var->varno];
+
+                       /*
+                        * For an inheritance child table, check permissions 
using the
+                        * root parent's RTE and columns.
+                        */
+                       if (rel->inh_root_parent)
+                       {
+                               relid = planner_rt_fetch(rel->inh_root_parent, 
root)->relid;
+
+                               /*
+                                * Must find out the column's attribute number 
per the root
+                                * parent's schema.
+                                */
+                               if (varattno > 0)
+                               {
+                                       AppendRelInfo *appinfo = 
root->append_rel_array[rel->relid];
+                                       ListCell   *l;
+                                       bool            found = false;
+
+                                       Assert(appinfo != NULL);
+                                       varattno = 1;
+                                       foreach(l, appinfo->translated_vars)
+                                       {
+                                               if (equal(var, lfirst(l)))
+                                               {
+                                                       found = true;
+                                                       break;
+                                               }
+                                               varattno++;
+                                       }
+                                       /*
+                                        * The query can only select columns 
present in the parent
+                                        * table, so we must've found one in 
translated_vars.
+                                        */
+                                       Assert(found);
+                               }
+                       }
                        /* check if user has permission to read this column */
                        vardata->acl_ok =
-                               (pg_class_aclcheck(rte->relid, GetUserId(),
+                               (pg_class_aclcheck(relid, GetUserId(),
                                                                   ACL_SELECT) 
== ACLCHECK_OK) ||
-                               (pg_attribute_aclcheck(rte->relid, 
var->varattno, GetUserId(),
+                               (pg_attribute_aclcheck(relid, varattno, 
GetUserId(),
                                                                           
ACL_SELECT) == ACLCHECK_OK);
                }
                else
-- 
2.11.0

Reply via email to