1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-03 15:22:11 +03:00

Get rid of the planner's LateralJoinInfo data structure.

I originally modeled this data structure on SpecialJoinInfo, but after
commit acfcd45cac that looks like a pretty poor decision.
All we really need is relid sets identifying laterally-referenced rels;
and most of the time, what we want to know about includes indirect lateral
references, a case the LateralJoinInfo data was unsuited to compute with
any efficiency.  The previous commit redefined RelOptInfo.lateral_relids
as the transitive closure of lateral references, so that it easily supports
checking indirect references.  For the places where we really do want just
direct references, add a new RelOptInfo field direct_lateral_relids, which
is easily set up as a copy of lateral_relids before we perform the
transitive closure calculation.  Then we can just drop lateral_info_list
and LateralJoinInfo and the supporting code.  This makes the planner's
handling of lateral references noticeably more efficient, and shorter too.

Such a change can't be back-patched into stable branches for fear of
breaking extensions that might be looking at the planner's data structures;
but it seems not too late to push it into 9.5, so I've done so.
This commit is contained in:
Tom Lane
2015-12-11 15:52:16 -05:00
parent ed8bec915e
commit 4fcf48450d
17 changed files with 100 additions and 289 deletions

View File

@@ -363,12 +363,10 @@ fix_placeholder_input_needed_levels(PlannerInfo *root)
/*
* add_placeholders_to_base_rels
* Add any required PlaceHolderVars to base rels' targetlists, and
* update lateral_vars lists for lateral references contained in them.
* Add any required PlaceHolderVars to base rels' targetlists.
*
* If any placeholder can be computed at a base rel and is needed above it,
* add it to that rel's targetlist, and add any lateral references it requires
* to the rel's lateral_vars list. This might look like it could be merged
* add it to that rel's targetlist. This might look like it could be merged
* with fix_placeholder_input_needed_levels, but it must be separate because
* join removal happens in between, and can change the ph_eval_at sets. There
* is essentially the same logic in add_placeholders_to_joinrel, but we can't
@@ -385,58 +383,22 @@ add_placeholders_to_base_rels(PlannerInfo *root)
Relids eval_at = phinfo->ph_eval_at;
int varno;
if (bms_get_singleton_member(eval_at, &varno))
if (bms_get_singleton_member(eval_at, &varno) &&
bms_nonempty_difference(phinfo->ph_needed, eval_at))
{
RelOptInfo *rel = find_base_rel(root, varno);
/* add it to reltargetlist if needed above the rel scan level */
if (bms_nonempty_difference(phinfo->ph_needed, eval_at))
rel->reltargetlist = lappend(rel->reltargetlist,
copyObject(phinfo->ph_var));
/* if there are lateral refs in it, add them to lateral_vars */
if (phinfo->ph_lateral != NULL)
{
List *vars = pull_var_clause((Node *) phinfo->ph_var->phexpr,
PVC_RECURSE_AGGREGATES,
PVC_INCLUDE_PLACEHOLDERS);
ListCell *lc2;
foreach(lc2, vars)
{
Node *node = (Node *) lfirst(lc2);
if (IsA(node, Var))
{
Var *var = (Var *) node;
if (var->varno != varno)
rel->lateral_vars = lappend(rel->lateral_vars,
var);
}
else if (IsA(node, PlaceHolderVar))
{
PlaceHolderVar *other_phv = (PlaceHolderVar *) node;
PlaceHolderInfo *other_phi;
other_phi = find_placeholder_info(root, other_phv,
false);
if (!bms_is_subset(other_phi->ph_eval_at, eval_at))
rel->lateral_vars = lappend(rel->lateral_vars,
other_phv);
}
else
Assert(false);
}
list_free(vars);
}
rel->reltargetlist = lappend(rel->reltargetlist,
copyObject(phinfo->ph_var));
}
}
}
/*
* add_placeholders_to_joinrel
* Add any required PlaceHolderVars to a join rel's targetlist.
* Add any required PlaceHolderVars to a join rel's targetlist;
* and if they contain lateral references, add those references to the
* joinrel's direct_lateral_relids.
*
* A join rel should emit a PlaceHolderVar if (a) the PHV is needed above
* this join level and (b) the PHV can be computed at or below this level.
@@ -463,6 +425,10 @@ add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel)
joinrel->reltargetlist = lappend(joinrel->reltargetlist,
phinfo->ph_var);
joinrel->width += phinfo->ph_width;
/* Adjust joinrel's direct_lateral_relids as needed */
joinrel->direct_lateral_relids =
bms_add_members(joinrel->direct_lateral_relids,
phinfo->ph_lateral);
}
}
}