From 18f8a79aeb8d153b5b19a387e8e796d0b82b1be5 Mon Sep 17 00:00:00 2001 From: amit Date: Wed, 17 Jul 2019 18:00:15 +0900 Subject: [PATCH v2] Use root parent's permissions when read child table stats Author: Dilip Kumar Reviewed by: Amit Langote --- src/backend/nodes/outfuncs.c | 1 + src/backend/optimizer/util/relnode.c | 11 +++++++ src/backend/utils/adt/selfuncs.c | 57 ++++++++++++++++++++++++++++++++++-- src/include/nodes/pathnodes.h | 5 ++++ 4 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 8e31fae47f..7a8461e24f 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -2276,6 +2276,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 6054bd2b53..059042a9f6 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -259,6 +259,16 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent) rel->top_parent_relids = bms_copy(parent->relids); /* + * For inheritance child relations, also set inh_root_parent. If + * 'parent' is itself a child relation, 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; + + /* * Also propagate lateral-reference information from appendrel parent * rels to their child rels. We intentionally give each child rel the * same minimum parameterization, even though it's quite possible that @@ -279,6 +289,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent) else { rel->top_parent_relids = NULL; + rel->inh_root_parent = 0; rel->direct_lateral_relids = NULL; rel->lateral_relids = NULL; rel->lateral_referencers = NULL; diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 66449b85b1..2651bf7cf2 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -4593,8 +4593,17 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid, /* Get index's table for permission check */ RangeTblEntry *rte; Oid userid; + RelOptInfo *rel = index->rel; - rte = planner_rt_fetch(index->rel->relid, root); + /* + * For an inheritance child table, check + * permissions using the root parent's RTE. + */ + if (rel->inh_root_parent > 0) + rte = planner_rt_fetch(rel->inh_root_parent, + root); + else + rte = planner_rt_fetch(rel->relid, root); Assert(rte->rtekind == RTE_RELATION); /* @@ -4678,6 +4687,48 @@ examine_simple_variable(PlannerInfo *root, Var *var, if (HeapTupleIsValid(vardata->statsTuple)) { Oid userid; + 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 column. + */ + if (rel->inh_root_parent > 0) + { + rte = planner_rt_fetch(rel->inh_root_parent, root); + + /* + * Reverse-map the column's attribute number to that in the + * root parent using the child table's Var translation list. + */ + 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 have found one. + */ + Assert(found); + } + } /* * Check if user has permission to read this column. We require @@ -4689,9 +4740,9 @@ examine_simple_variable(PlannerInfo *root, Var *var, vardata->acl_ok = rte->securityQuals == NIL && - ((pg_class_aclcheck(rte->relid, userid, + ((pg_class_aclcheck(relid, userid, ACL_SELECT) == ACLCHECK_OK) || - (pg_attribute_aclcheck(rte->relid, var->varattno, userid, + (pg_attribute_aclcheck(relid, varattno, userid, ACL_SELECT) == ACLCHECK_OK)); } else diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 441e64eca9..84c5f99766 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -720,6 +720,11 @@ 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 root table mentioned in the + * query from which this relation + * originated. */ } RelOptInfo; /* -- 2.11.0