diff options
Diffstat (limited to 'src/backend/optimizer/plan/initsplan.c')
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 94 |
1 files changed, 40 insertions, 54 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 2afc3f1dfe0..62dfac67dcb 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -90,17 +90,16 @@ static void check_hashjoinable(RestrictInfo *restrictinfo); * add_base_rels_to_query * * Scan the query's jointree and create baserel RelOptInfos for all - * the base relations (ie, table, subquery, and function RTEs) + * the base relations (e.g., table, subquery, and function RTEs) * appearing in the jointree. * * The initial invocation must pass root->parse->jointree as the value of * jtnode. Internally, the function recurses through the jointree. * * At the end of this process, there should be one baserel RelOptInfo for - * every non-join RTE that is used in the query. Therefore, this routine - * is the only place that should call build_simple_rel with reloptkind - * RELOPT_BASEREL. (Note: build_simple_rel recurses internally to build - * "other rel" RelOptInfos for the members of any appendrels we find here.) + * every non-join RTE that is used in the query. Some of the baserels + * may be appendrel parents, which will require additional "otherrel" + * RelOptInfos for their member rels, but those are added later. */ void add_base_rels_to_query(PlannerInfo *root, Node *jtnode) @@ -133,6 +132,42 @@ add_base_rels_to_query(PlannerInfo *root, Node *jtnode) (int) nodeTag(jtnode)); } +/* + * add_other_rels_to_query + * create "otherrel" RelOptInfos for the children of appendrel baserels + * + * At the end of this process, there should be RelOptInfos for all relations + * that will be scanned by the query. + */ +void +add_other_rels_to_query(PlannerInfo *root) +{ + int rti; + + for (rti = 1; rti < root->simple_rel_array_size; rti++) + { + RelOptInfo *rel = root->simple_rel_array[rti]; + RangeTblEntry *rte = root->simple_rte_array[rti]; + + /* there may be empty slots corresponding to non-baserel RTEs */ + if (rel == NULL) + continue; + + /* Ignore any "otherrels" that were already added. */ + if (rel->reloptkind != RELOPT_BASEREL) + continue; + + /* If it's marked as inheritable, look for children. */ + if (rte->inh) + { + /* Only relation and subquery RTEs can have children. */ + Assert(rte->rtekind == RTE_RELATION || + rte->rtekind == RTE_SUBQUERY); + add_appendrel_other_rels(root, rel, rti); + } + } +} + /***************************************************************************** * @@ -419,7 +454,6 @@ void create_lateral_join_info(PlannerInfo *root) { bool found_laterals = false; - Relids prev_parents PG_USED_FOR_ASSERTS_ONLY = NULL; Index rti; ListCell *lc; @@ -618,54 +652,6 @@ create_lateral_join_info(PlannerInfo *root) bms_add_member(brel2->lateral_referencers, rti); } } - - /* - * Lastly, propagate lateral_relids and lateral_referencers 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 - * some don't reference all the lateral rels. This is because any append - * path for the parent will have to have the same parameterization for - * every child anyway, and there's no value in forcing extra - * reparameterize_path() calls. Similarly, a lateral reference to the - * parent prevents use of otherwise-movable join rels for each child. - * - * It's possible for child rels to have their own children, in which case - * the topmost parent's lateral info must be propagated all the way down. - * This code handles that case correctly so long as append_rel_list has - * entries for child relationships before grandchild relationships, which - * is an okay assumption right now, but we'll need to be careful to - * preserve it. The assertions below check for incorrect ordering. - */ - foreach(lc, root->append_rel_list) - { - AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc); - RelOptInfo *parentrel = root->simple_rel_array[appinfo->parent_relid]; - RelOptInfo *childrel = root->simple_rel_array[appinfo->child_relid]; - - /* - * If we're processing a subquery of a query with inherited target rel - * (cf. inheritance_planner), append_rel_list may contain entries for - * tables that are not part of the current subquery and hence have no - * RelOptInfo. Ignore them. We can ignore dead rels, too. - */ - if (parentrel == NULL || !IS_SIMPLE_REL(parentrel)) - continue; - - /* Verify that children are processed before grandchildren */ -#ifdef USE_ASSERT_CHECKING - prev_parents = bms_add_member(prev_parents, appinfo->parent_relid); - Assert(!bms_is_member(appinfo->child_relid, prev_parents)); -#endif - - /* OK, propagate info down */ - Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL); - Assert(childrel->direct_lateral_relids == NULL); - childrel->direct_lateral_relids = parentrel->direct_lateral_relids; - Assert(childrel->lateral_relids == NULL); - childrel->lateral_relids = parentrel->lateral_relids; - Assert(childrel->lateral_referencers == NULL); - childrel->lateral_referencers = parentrel->lateral_referencers; - } } |