bug_fix_childrel_stat_access_v2.patch
application/octet-stream
Filename: bug_fix_childrel_stat_access_v2.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| src/backend/optimizer/util/relnode.c | 23 | 0 |
| src/backend/utils/adt/selfuncs.c | 63 | 3 |
| src/include/nodes/relation.h | 1 | 0 |
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 39f5729..d3bfe80 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -204,6 +204,29 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
rel->partitioned_child_rels = NIL;
/*
+ * Pass top parent's relid down the inheritance hierarchy. If the parent
+ * has inh_root_parent set then pass it down.
+ */
+ if (parent)
+ {
+ if (parent->inh_root_parent)
+ rel->inh_root_parent = parent->inh_root_parent;
+ else
+ {
+ RangeTblEntry *parent_rte;
+
+ parent_rte = root->simple_rte_array[parent->relid];
+
+ if (parent_rte->rtekind == RTE_RELATION)
+ rel->inh_root_parent = parent->relid;
+ else
+ rel->inh_root_parent = 0;
+ }
+ }
+ else
+ rel->inh_root_parent = 0;
+
+ /*
* Pass top parent's relids down the inheritance hierarchy. If the parent
* has top_parent_relids set, it's a direct or an indirect child of the
* top parent indicated by top_parent_relids. By extension this child is
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index e0ece74..56451f1 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 the child partition fetch the index of
+ * the root parent.
+ */
+ 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);
/*
@@ -4957,6 +4967,39 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
}
/*
+ * transalate_varattno
+ *
+ * translate child attno to parent attno.
+ */
+static int
+transalate_varattno(Oid oldrelid, Oid newrelid, int old_attno)
+{
+ Relation oldrelation = heap_open(oldrelid, NoLock);
+ TupleDesc old_tupdesc = RelationGetDescr(oldrelation);
+ HeapTuple newtup;
+ Form_pg_attribute att;
+ int new_attno = old_attno;
+ char *attname;
+
+ att = TupleDescAttr(old_tupdesc, old_attno - 1);
+ attname = NameStr(att->attname);
+
+ newtup = SearchSysCacheAttName(newrelid, attname);
+ if (!newtup)
+ {
+ heap_close(oldrelation, NoLock);
+ return InvalidAttrNumber;
+ }
+
+ new_attno = ((Form_pg_attribute) GETSTRUCT(newtup))->attnum;
+ ReleaseSysCache(newtup);
+
+ heap_close(oldrelation, NoLock);
+
+ return new_attno;
+}
+
+/*
* examine_simple_variable
* Handle a simple Var for examine_variable
*
@@ -4998,11 +5041,28 @@ 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 the child partition fetch the index of the root parent. */
+ if (rel->inh_root_parent)
+ {
+ rte = planner_rt_fetch(rel->inh_root_parent, root);
+
+ varattno = transalate_varattno(relid, rte->relid, var->varattno);
+ if (AttributeNumberIsValid(varattno))
+ relid = rte->relid;
+ else
+ varattno = var->varattno;
+ }
/* 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
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 88d3723..9688fec 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -694,6 +694,7 @@ typedef struct RelOptInfo
* rel) */
/* used for partitioned relations */
+ Index inh_root_parent; /* RTI index of the inheritance root. */
PartitionScheme part_scheme; /* Partitioning scheme. */
int nparts; /* number of partitions */
struct PartitionBoundInfoData *boundinfo; /* Partition bounds */