aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/path/equivclass.c16
-rw-r--r--src/backend/optimizer/plan/planner.c16
-rw-r--r--src/backend/optimizer/util/appendinfo.c92
-rw-r--r--src/backend/optimizer/util/pathnode.c8
-rw-r--r--src/backend/optimizer/util/relnode.c23
-rw-r--r--src/backend/partitioning/partprune.c4
-rw-r--r--src/include/nodes/pathnodes.h10
-rw-r--r--src/include/optimizer/appendinfo.h8
8 files changed, 83 insertions, 94 deletions
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index 2c900e6b120..799bdc91d09 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -1760,8 +1760,8 @@ generate_join_implied_equalities_broken(PlannerInfo *root,
if (IS_OTHER_REL(inner_rel) && result != NIL)
result = (List *) adjust_appendrel_attrs_multilevel(root,
(Node *) result,
- inner_rel->relids,
- inner_rel->top_parent_relids);
+ inner_rel,
+ inner_rel->top_parent);
return result;
}
@@ -2626,8 +2626,8 @@ add_child_rel_equivalences(PlannerInfo *root,
child_expr = (Expr *)
adjust_appendrel_attrs_multilevel(root,
(Node *) cur_em->em_expr,
- child_relids,
- top_parent_relids);
+ child_rel,
+ child_rel->top_parent);
}
/*
@@ -2768,8 +2768,8 @@ add_child_join_rel_equivalences(PlannerInfo *root,
child_expr = (Expr *)
adjust_appendrel_attrs_multilevel(root,
(Node *) cur_em->em_expr,
- child_relids,
- top_parent_relids);
+ child_joinrel,
+ child_joinrel->top_parent);
}
/*
@@ -2791,8 +2791,8 @@ add_child_join_rel_equivalences(PlannerInfo *root,
new_nullable_relids =
adjust_child_relids_multilevel(root,
new_nullable_relids,
- child_relids,
- top_parent_relids);
+ child_joinrel,
+ child_joinrel->top_parent);
(void) add_eq_member(cur_ec, child_expr,
new_relids, new_nullable_relids,
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index b781080dbac..cf9e0a74dbf 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1793,8 +1793,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
withCheckOptions = (List *)
adjust_appendrel_attrs_multilevel(root,
(Node *) withCheckOptions,
- this_result_rel->relids,
- top_result_rel->relids);
+ this_result_rel,
+ top_result_rel);
withCheckOptionLists = lappend(withCheckOptionLists,
withCheckOptions);
}
@@ -1806,8 +1806,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
returningList = (List *)
adjust_appendrel_attrs_multilevel(root,
(Node *) returningList,
- this_result_rel->relids,
- top_result_rel->relids);
+ this_result_rel,
+ top_result_rel);
returningLists = lappend(returningLists,
returningList);
}
@@ -1828,13 +1828,13 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
leaf_action->qual =
adjust_appendrel_attrs_multilevel(root,
(Node *) action->qual,
- this_result_rel->relids,
- top_result_rel->relids);
+ this_result_rel,
+ top_result_rel);
leaf_action->targetList = (List *)
adjust_appendrel_attrs_multilevel(root,
(Node *) action->targetList,
- this_result_rel->relids,
- top_result_rel->relids);
+ this_result_rel,
+ top_result_rel);
if (leaf_action->commandType == CMD_UPDATE)
leaf_action->updateColnos =
adjust_inherited_attnums_multilevel(root,
diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c
index 9d4bb470270..62cccf9d87c 100644
--- a/src/backend/optimizer/util/appendinfo.c
+++ b/src/backend/optimizer/util/appendinfo.c
@@ -479,39 +479,34 @@ adjust_appendrel_attrs_mutator(Node *node,
/*
* adjust_appendrel_attrs_multilevel
- * Apply Var translations from a toplevel appendrel parent down to a child.
+ * Apply Var translations from an appendrel parent down to a child.
*
- * In some cases we need to translate expressions referencing a parent relation
- * to reference an appendrel child that's multiple levels removed from it.
+ * Replace Vars in the "node" expression that reference "parentrel" with
+ * the appropriate Vars for "childrel". childrel can be more than one
+ * inheritance level removed from parentrel.
*/
Node *
adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
- Relids child_relids,
- Relids top_parent_relids)
+ RelOptInfo *childrel,
+ RelOptInfo *parentrel)
{
AppendRelInfo **appinfos;
- Bitmapset *parent_relids = NULL;
int nappinfos;
- int cnt;
-
- Assert(bms_num_members(child_relids) == bms_num_members(top_parent_relids));
-
- appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
- /* Construct relids set for the immediate parent of given child. */
- for (cnt = 0; cnt < nappinfos; cnt++)
+ /* Recurse if immediate parent is not the top parent. */
+ if (childrel->parent != parentrel)
{
- AppendRelInfo *appinfo = appinfos[cnt];
-
- parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
+ if (childrel->parent)
+ node = adjust_appendrel_attrs_multilevel(root, node,
+ childrel->parent,
+ parentrel);
+ else
+ elog(ERROR, "childrel is not a child of parentrel");
}
- /* Recurse if immediate parent is not the top parent. */
- if (!bms_equal(parent_relids, top_parent_relids))
- node = adjust_appendrel_attrs_multilevel(root, node, parent_relids,
- top_parent_relids);
+ /* Now translate for this child. */
+ appinfos = find_appinfos_by_relids(root, childrel->relids, &nappinfos);
- /* Now translate for this child */
node = adjust_appendrel_attrs(root, node, nappinfos, appinfos);
pfree(appinfos);
@@ -554,56 +549,43 @@ adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
}
/*
- * Replace any relid present in top_parent_relids with its child in
- * child_relids. Members of child_relids can be multiple levels below top
- * parent in the partition hierarchy.
+ * Substitute child's relids for parent's relids in a Relid set.
+ * The childrel can be multiple inheritance levels below the parent.
*/
Relids
adjust_child_relids_multilevel(PlannerInfo *root, Relids relids,
- Relids child_relids, Relids top_parent_relids)
+ RelOptInfo *childrel,
+ RelOptInfo *parentrel)
{
AppendRelInfo **appinfos;
int nappinfos;
- Relids parent_relids = NULL;
- Relids result;
- Relids tmp_result = NULL;
- int cnt;
/*
- * If the given relids set doesn't contain any of the top parent relids,
- * it will remain unchanged.
+ * If the given relids set doesn't contain any of the parent relids, it
+ * will remain unchanged.
*/
- if (!bms_overlap(relids, top_parent_relids))
+ if (!bms_overlap(relids, parentrel->relids))
return relids;
- appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
-
- /* Construct relids set for the immediate parent of the given child. */
- for (cnt = 0; cnt < nappinfos; cnt++)
- {
- AppendRelInfo *appinfo = appinfos[cnt];
-
- parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
- }
-
/* Recurse if immediate parent is not the top parent. */
- if (!bms_equal(parent_relids, top_parent_relids))
+ if (childrel->parent != parentrel)
{
- tmp_result = adjust_child_relids_multilevel(root, relids,
- parent_relids,
- top_parent_relids);
- relids = tmp_result;
+ if (childrel->parent)
+ relids = adjust_child_relids_multilevel(root, relids,
+ childrel->parent,
+ parentrel);
+ else
+ elog(ERROR, "childrel is not a child of parentrel");
}
- result = adjust_child_relids(relids, nappinfos, appinfos);
+ /* Now translate for this child. */
+ appinfos = find_appinfos_by_relids(root, childrel->relids, &nappinfos);
+
+ relids = adjust_child_relids(relids, nappinfos, appinfos);
- /* Free memory consumed by any intermediate result. */
- if (tmp_result)
- bms_free(tmp_result);
- bms_free(parent_relids);
pfree(appinfos);
- return result;
+ return relids;
}
/*
@@ -694,8 +676,8 @@ get_translated_update_targetlist(PlannerInfo *root, Index relid,
*processed_tlist = (List *)
adjust_appendrel_attrs_multilevel(root,
(Node *) root->processed_tlist,
- bms_make_singleton(relid),
- bms_make_singleton(root->parse->resultRelation));
+ find_base_rel(root, relid),
+ find_base_rel(root, root->parse->resultRelation));
if (update_colnos)
*update_colnos =
adjust_inherited_attnums_multilevel(root, root->update_colnos,
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index dd64b460865..e10561d843a 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -4026,8 +4026,8 @@ reparameterize_path_by_child(PlannerInfo *root, Path *path,
#define ADJUST_CHILD_ATTRS(node) \
((node) = \
(List *) adjust_appendrel_attrs_multilevel(root, (Node *) (node), \
- child_rel->relids, \
- child_rel->top_parent_relids))
+ child_rel, \
+ child_rel->top_parent))
#define REPARAMETERIZE_CHILD_PATH(path) \
do { \
@@ -4244,8 +4244,8 @@ do { \
old_ppi = new_path->param_info;
required_outer =
adjust_child_relids_multilevel(root, old_ppi->ppi_req_outer,
- child_rel->relids,
- child_rel->top_parent_relids);
+ child_rel,
+ child_rel->top_parent);
/* If we already have a PPI for this parameterization, just return it */
new_ppi = find_param_path_info(new_path->parent, required_outer);
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 965eb5b3b45..edcdd0a3603 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -265,14 +265,10 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
*/
if (parent)
{
- /*
- * Each direct or indirect child wants to know the relids of its
- * topmost parent.
- */
- if (parent->top_parent_relids)
- rel->top_parent_relids = parent->top_parent_relids;
- else
- rel->top_parent_relids = bms_copy(parent->relids);
+ /* We keep back-links to immediate parent and topmost parent. */
+ rel->parent = parent;
+ rel->top_parent = parent->top_parent ? parent->top_parent : parent;
+ rel->top_parent_relids = rel->top_parent->relids;
/*
* Also propagate lateral-reference information from appendrel parent
@@ -294,6 +290,8 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
}
else
{
+ rel->parent = NULL;
+ rel->top_parent = NULL;
rel->top_parent_relids = NULL;
rel->direct_lateral_relids = NULL;
rel->lateral_relids = NULL;
@@ -663,6 +661,8 @@ build_join_rel(PlannerInfo *root,
joinrel->joininfo = NIL;
joinrel->has_eclass_joins = false;
joinrel->consider_partitionwise_join = false; /* might get changed later */
+ joinrel->parent = NULL;
+ joinrel->top_parent = NULL;
joinrel->top_parent_relids = NULL;
joinrel->part_scheme = NULL;
joinrel->nparts = -1;
@@ -843,7 +843,9 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
joinrel->joininfo = NIL;
joinrel->has_eclass_joins = false;
joinrel->consider_partitionwise_join = false; /* might get changed later */
- joinrel->top_parent_relids = NULL;
+ joinrel->parent = parent_joinrel;
+ joinrel->top_parent = parent_joinrel->top_parent ? parent_joinrel->top_parent : parent_joinrel;
+ joinrel->top_parent_relids = joinrel->top_parent->relids;
joinrel->part_scheme = NULL;
joinrel->nparts = -1;
joinrel->boundinfo = NULL;
@@ -855,9 +857,6 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
joinrel->partexprs = NULL;
joinrel->nullable_partexprs = NULL;
- joinrel->top_parent_relids = bms_union(outer_rel->top_parent_relids,
- inner_rel->top_parent_relids);
-
/* Compute information relevant to foreign relations. */
set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index fc19232c7b9..bf9fe5b7aaf 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -529,8 +529,8 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
partprunequal = (List *)
adjust_appendrel_attrs_multilevel(root,
(Node *) prunequal,
- subpart->relids,
- targetpart->relids);
+ subpart,
+ targetpart);
}
/*
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index bdc7b50db97..294cfe9c47c 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -938,7 +938,15 @@ typedef struct RelOptInfo
*/
/* consider partitionwise join paths? (if partitioned rel) */
bool consider_partitionwise_join;
- /* Relids of topmost parents (if "other" rel) */
+
+ /*
+ * inheritance links, if this is an otherrel (otherwise NULL):
+ */
+ /* Immediate parent relation (dumping it would be too verbose) */
+ struct RelOptInfo *parent pg_node_attr(read_write_ignore);
+ /* Topmost parent relation (dumping it would be too verbose) */
+ struct RelOptInfo *top_parent pg_node_attr(read_write_ignore);
+ /* Relids of topmost parent (redundant, but handy) */
Relids top_parent_relids;
/*
diff --git a/src/include/optimizer/appendinfo.h b/src/include/optimizer/appendinfo.h
index fc808dcd276..5e80a741a42 100644
--- a/src/include/optimizer/appendinfo.h
+++ b/src/include/optimizer/appendinfo.h
@@ -23,13 +23,13 @@ extern AppendRelInfo *make_append_rel_info(Relation parentrel,
extern Node *adjust_appendrel_attrs(PlannerInfo *root, Node *node,
int nappinfos, AppendRelInfo **appinfos);
extern Node *adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
- Relids child_relids,
- Relids top_parent_relids);
+ RelOptInfo *childrel,
+ RelOptInfo *parentrel);
extern Relids adjust_child_relids(Relids relids, int nappinfos,
AppendRelInfo **appinfos);
extern Relids adjust_child_relids_multilevel(PlannerInfo *root, Relids relids,
- Relids child_relids,
- Relids top_parent_relids);
+ RelOptInfo *childrel,
+ RelOptInfo *parentrel);
extern List *adjust_inherited_attnums(List *attnums, AppendRelInfo *context);
extern List *adjust_inherited_attnums_multilevel(PlannerInfo *root,
List *attnums,