diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 0ab4014..9f9a4d1 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -56,8 +56,8 @@ typedef struct { PlannerInfo *root; - int nappinfos; - AppendRelInfo **appinfos; + int nappinfos; /* # of entries in appinfos array. */ + AppendRelInfo **appinfos; /* AppendRelInfo dectating the adjustment. */ } adjust_appendrel_attrs_context; static RelOptInfo *recurse_set_operations(Node *setOp, PlannerInfo *root, @@ -2037,6 +2037,9 @@ translate_col_privs(const Bitmapset *parent_privs, * update rtindexes appearing outside Vars, such as resultRelation and * jointree relids. * + * appinfos is an array of nappinfos AppendRelInfos indicating non-overlapping + * parent-child pairs. + * * Note: this is only applied after conversion of sublinks to subplans, * so we don't need to cope with recursion into sub-queries. * @@ -2050,6 +2053,12 @@ adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, Node *result; adjust_appendrel_attrs_context context; +#ifdef USE_ASSERT_CHECKING + Relids parents = NULL; + Relids children = NULL; + int cnt; +#endif /* USE_ASSERT_CHECKING */ + context.root = root; context.nappinfos = nappinfos; context.appinfos = appinfos; @@ -2057,6 +2066,38 @@ adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, /* If there's nothing to adjust, don't call this function. */ Assert(nappinfos >= 1 && appinfos != NULL); +#ifdef USE_ASSERT_CHECKING + /* + * The appinfos are expected to contains non-overlapping AppendRelInfos so + * that the changes made for one AppendRelInfo doesn't get affected by + * another AppendRelInfo in that array. These tests are applicable only in + * case of multiple AppendRelInfos. + */ + if (nappinfos > 1) + { + for (cnt = 0; cnt < nappinfos; cnt++) + { + AppendRelInfo *appinfo = appinfos[cnt]; + + parents = bms_add_member(parents, appinfo->parent_relid); + children = bms_add_member(children, appinfo->child_relid); + } + + /* No two AppendRelInfos should have same parent or child. */ + Assert(bms_num_members(parents) == nappinfos); + Assert(bms_num_members(children) == nappinfos); + + /* No child should act as parent as well and vice versa. */ + for (cnt = 0; cnt < nappinfos; cnt++) + { + AppendRelInfo *appinfo = appinfos[cnt]; + + Assert(!bms_is_member(appinfo->child_relid, parents)); + Assert(!bms_is_member(appinfo->parent_relid, children)); + } + } +#endif /* USE_ASSERT_CHECKING */ + /* * Must be prepared to start with a Query or a bare expression tree. */ @@ -2613,6 +2654,9 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo, * * The AppendRelInfos are returned in an array, which can be pfree'd by the * caller. *nappinfos is set to the number of entries in the array. + * + * The returned array and *nappinfos is usually passed down to + * adjust_appendrel_attrs(). See prologue of that function for more details. */ AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos) diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 3b28d19..0d17999 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -2096,6 +2096,13 @@ typedef struct SpecialJoinInfo * will not have many different append parents, it doesn't seem worthwhile * to complicate things. * + * We expand multi-level partitioning hierarchy into corresponding inheritance + * hierarchy level by level. An intermediate partitioned partition acts as + * both, a parent (of its partitions) and a child (to the partitioned table + * whose partition it is). Per expand_single_inheritance_child() the + * AppendRelInfo of an intermediate parent appears before that of any of its + * children. + * * Note: after completion of the planner prep phase, any given RTE is an * append parent having entries in append_rel_list if and only if its * "inh" flag is set. We clear "inh" for plain tables that turn out not