aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/initsplan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/initsplan.c')
-rw-r--r--src/backend/optimizer/plan/initsplan.c94
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;
- }
}