diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index 2c900e6b12..799bdc91d0 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 b781080dba..cf9e0a74db 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 9d4bb47027..62cccf9d87 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++) - { - 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)) - node = adjust_appendrel_attrs_multilevel(root, node, parent_relids, - top_parent_relids); + if (childrel->parent != parentrel) + { + if (childrel->parent) + node = adjust_appendrel_attrs_multilevel(root, node, + childrel->parent, + parentrel); + else + elog(ERROR, "childrel is not a child of parentrel"); + } + + /* 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 dd64b46086..e10561d843 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 965eb5b3b4..edcdd0a360 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 fc19232c7b..bf9fe5b7aa 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 bdc7b50db9..294cfe9c47 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 fc808dcd27..5e80a741a4 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,