aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/relnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/relnode.c')
-rw-r--r--src/backend/optimizer/util/relnode.c41
1 files changed, 21 insertions, 20 deletions
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 79842bbdaca..bb47819a2a8 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -376,7 +376,8 @@ build_join_rel(PlannerInfo *root,
joinrel->attr_needed = NULL;
joinrel->attr_widths = NULL;
joinrel->lateral_vars = NIL;
- joinrel->lateral_relids = min_join_parameterization(root, joinrel->relids);
+ joinrel->lateral_relids = min_join_parameterization(root, joinrel->relids,
+ outer_rel, inner_rel);
joinrel->lateral_referencers = NULL;
joinrel->indexlist = NIL;
joinrel->pages = 0;
@@ -469,32 +470,32 @@ build_join_rel(PlannerInfo *root,
* min_join_parameterization
*
* Determine the minimum possible parameterization of a joinrel, that is, the
- * set of other rels it contains LATERAL references to.
+ * set of other rels it contains LATERAL references to. We save this value in
+ * the join's RelOptInfo. This function is split out of build_join_rel()
+ * because join_is_legal() needs the value to check a prospective join.
*/
Relids
-min_join_parameterization(PlannerInfo *root, Relids joinrelids)
+min_join_parameterization(PlannerInfo *root,
+ Relids joinrelids,
+ RelOptInfo *outer_rel,
+ RelOptInfo *inner_rel)
{
Relids result;
- ListCell *lc;
-
- /* Easy if there are no lateral references */
- if (root->lateral_info_list == NIL)
- return NULL;
/*
- * Scan lateral_info_list to find all the lateral references occurring in
- * or below this join.
+ * Basically we just need the union of the inputs' lateral_relids, less
+ * whatever is already in the join.
+ *
+ * It's not immediately obvious that this is a valid way to compute the
+ * result, because it might seem that we're ignoring possible lateral refs
+ * of PlaceHolderVars that are due to be computed at the join but not in
+ * either input. However, because create_lateral_join_info() already
+ * charged all such PHV refs to each member baserel of the join, they'll
+ * be accounted for already in the inputs' lateral_relids. Likewise, we
+ * do not need to worry about doing transitive closure here, because that
+ * was already accounted for in the original baserel lateral_relids.
*/
- result = NULL;
- foreach(lc, root->lateral_info_list)
- {
- LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(lc);
-
- if (bms_is_subset(ljinfo->lateral_rhs, joinrelids))
- result = bms_add_members(result, ljinfo->lateral_lhs);
- }
-
- /* Remove any rels that are already included in the join */
+ result = bms_union(outer_rel->lateral_relids, inner_rel->lateral_relids);
result = bms_del_members(result, joinrelids);
/* Maintain invariant that result is exactly NULL if empty */