mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
Build "other rels" of appendrel baserels in a separate step.
Up to now, otherrel RelOptInfos were built at the same time as baserel RelOptInfos, thanks to recursion in build_simple_rel(). However, nothing in query_planner's preprocessing cares at all about otherrels, only baserels, so we don't really need to build them until just before we enter make_one_rel. This has two benefits: * create_lateral_join_info did a lot of extra work to propagate lateral-reference information from parents to the correct children. But if we delay creation of the children till after that, it's trivial (and much harder to break, too). * Since we have all the restriction quals correctly assigned to parent appendrels by this point, it'll be possible to do plan-time pruning and never make child RelOptInfos at all for partitions that can be pruned away. That's not done here, but will be later on. Amit Langote, reviewed at various times by Dilip Kumar, Jesper Pedersen, Yoshikazu Imai, and David Rowley Discussion: https://postgr.es/m/9d7c5112-cb99-6a47-d3be-cf1ee6862a1d@lab.ntt.co.jp
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user