diff options
Diffstat (limited to 'src/backend/optimizer/util/relnode.c')
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 41 |
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 */ |