aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/path/joinpath.c113
-rw-r--r--src/backend/optimizer/util/relnode.c2
-rw-r--r--src/include/nodes/relation.h4
3 files changed, 28 insertions, 91 deletions
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index 1dc2e775987..c0372780f0b 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -29,19 +29,19 @@ static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
RelOptInfo *outerrel, RelOptInfo *innerrel,
List *restrictlist, List *mergeclause_list,
JoinType jointype, SpecialJoinInfo *sjinfo,
- Relids param_source_rels, Relids extra_lateral_rels);
+ Relids param_source_rels);
static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel,
RelOptInfo *outerrel, RelOptInfo *innerrel,
List *restrictlist, List *mergeclause_list,
JoinType jointype, SpecialJoinInfo *sjinfo,
SemiAntiJoinFactors *semifactors,
- Relids param_source_rels, Relids extra_lateral_rels);
+ Relids param_source_rels);
static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
RelOptInfo *outerrel, RelOptInfo *innerrel,
List *restrictlist,
JoinType jointype, SpecialJoinInfo *sjinfo,
SemiAntiJoinFactors *semifactors,
- Relids param_source_rels, Relids extra_lateral_rels);
+ Relids param_source_rels);
static List *select_mergejoin_clauses(PlannerInfo *root,
RelOptInfo *joinrel,
RelOptInfo *outerrel,
@@ -87,7 +87,6 @@ add_paths_to_joinrel(PlannerInfo *root,
bool mergejoin_allowed = true;
SemiAntiJoinFactors semifactors;
Relids param_source_rels = NULL;
- Relids extra_lateral_rels = NULL;
ListCell *lc;
/*
@@ -153,59 +152,14 @@ add_paths_to_joinrel(PlannerInfo *root,
}
/*
- * However, when a LATERAL subquery is involved, we have to be a bit
- * laxer, because there will simply not be any paths for the joinrel that
- * aren't parameterized by whatever the subquery is parameterized by,
- * unless its parameterization is resolved within the joinrel. Hence, add
- * to param_source_rels anything that is laterally referenced in either
- * input and is not in the join already.
+ * However, when a LATERAL subquery is involved, there will simply not be
+ * any paths for the joinrel that aren't parameterized by whatever the
+ * subquery is parameterized by, unless its parameterization is resolved
+ * within the joinrel. So we might as well allow additional dependencies
+ * on whatever residual lateral dependencies the joinrel will have.
*/
- foreach(lc, root->lateral_info_list)
- {
- LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(lc);
-
- if (bms_is_subset(ljinfo->lateral_rhs, joinrel->relids))
- param_source_rels = bms_join(param_source_rels,
- bms_difference(ljinfo->lateral_lhs,
- joinrel->relids));
- }
-
- /*
- * Another issue created by LATERAL references is that PlaceHolderVars
- * that need to be computed at this join level might contain lateral
- * references to rels not in the join, meaning that the paths for the join
- * would need to be marked as parameterized by those rels, independently
- * of all other considerations. Set extra_lateral_rels to the set of such
- * rels. This will not affect our decisions as to which paths to
- * generate; we merely add these rels to their required_outer sets.
- */
- foreach(lc, root->placeholder_list)
- {
- PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
-
- /* PHVs without lateral refs can be skipped over quickly */
- if (phinfo->ph_lateral == NULL)
- continue;
- /* Is it due to be evaluated at this join, and not in either input? */
- if (bms_is_subset(phinfo->ph_eval_at, joinrel->relids) &&
- !bms_is_subset(phinfo->ph_eval_at, outerrel->relids) &&
- !bms_is_subset(phinfo->ph_eval_at, innerrel->relids))
- {
- /* Yes, remember its lateral rels */
- extra_lateral_rels = bms_add_members(extra_lateral_rels,
- phinfo->ph_lateral);
- }
- }
-
- /*
- * Make sure extra_lateral_rels doesn't list anything within the join, and
- * that it's NULL if empty. (This allows us to use bms_add_members to add
- * it to required_outer below, while preserving the property that
- * required_outer is exactly NULL if empty.)
- */
- extra_lateral_rels = bms_del_members(extra_lateral_rels, joinrel->relids);
- if (bms_is_empty(extra_lateral_rels))
- extra_lateral_rels = NULL;
+ param_source_rels = bms_add_members(param_source_rels,
+ joinrel->lateral_relids);
/*
* 1. Consider mergejoin paths where both relations must be explicitly
@@ -215,7 +169,7 @@ add_paths_to_joinrel(PlannerInfo *root,
sort_inner_and_outer(root, joinrel, outerrel, innerrel,
restrictlist, mergeclause_list, jointype,
sjinfo,
- param_source_rels, extra_lateral_rels);
+ param_source_rels);
/*
* 2. Consider paths where the outer relation need not be explicitly
@@ -228,7 +182,7 @@ add_paths_to_joinrel(PlannerInfo *root,
match_unsorted_outer(root, joinrel, outerrel, innerrel,
restrictlist, mergeclause_list, jointype,
sjinfo, &semifactors,
- param_source_rels, extra_lateral_rels);
+ param_source_rels);
#ifdef NOT_USED
@@ -247,7 +201,7 @@ add_paths_to_joinrel(PlannerInfo *root,
match_unsorted_inner(root, joinrel, outerrel, innerrel,
restrictlist, mergeclause_list, jointype,
sjinfo, &semifactors,
- param_source_rels, extra_lateral_rels);
+ param_source_rels);
#endif
/*
@@ -259,7 +213,7 @@ add_paths_to_joinrel(PlannerInfo *root,
hash_inner_and_outer(root, joinrel, outerrel, innerrel,
restrictlist, jointype,
sjinfo, &semifactors,
- param_source_rels, extra_lateral_rels);
+ param_source_rels);
}
/*
@@ -353,7 +307,6 @@ try_nestloop_path(PlannerInfo *root,
SpecialJoinInfo *sjinfo,
SemiAntiJoinFactors *semifactors,
Relids param_source_rels,
- Relids extra_lateral_rels,
Path *outer_path,
Path *inner_path,
List *restrict_clauses,
@@ -382,9 +335,13 @@ try_nestloop_path(PlannerInfo *root,
/*
* Independently of that, add parameterization needed for any
- * PlaceHolderVars that need to be computed at the join.
+ * PlaceHolderVars that need to be computed at the join. We can handle
+ * that just by adding joinrel->lateral_relids; that might include some
+ * rels that are already in required_outer, but no harm done. (Note that
+ * lateral_relids is exactly NULL if empty, so this will not break the
+ * property that required_outer is too.)
*/
- required_outer = bms_add_members(required_outer, extra_lateral_rels);
+ required_outer = bms_add_members(required_outer, joinrel->lateral_relids);
/*
* Do a precheck to quickly eliminate obviously-inferior paths. We
@@ -434,7 +391,6 @@ try_mergejoin_path(PlannerInfo *root,
JoinType jointype,
SpecialJoinInfo *sjinfo,
Relids param_source_rels,
- Relids extra_lateral_rels,
Path *outer_path,
Path *inner_path,
List *restrict_clauses,
@@ -464,7 +420,7 @@ try_mergejoin_path(PlannerInfo *root,
* Independently of that, add parameterization needed for any
* PlaceHolderVars that need to be computed at the join.
*/
- required_outer = bms_add_members(required_outer, extra_lateral_rels);
+ required_outer = bms_add_members(required_outer, joinrel->lateral_relids);
/*
* If the given paths are already well enough ordered, we can skip doing
@@ -523,7 +479,6 @@ try_hashjoin_path(PlannerInfo *root,
SpecialJoinInfo *sjinfo,
SemiAntiJoinFactors *semifactors,
Relids param_source_rels,
- Relids extra_lateral_rels,
Path *outer_path,
Path *inner_path,
List *restrict_clauses,
@@ -550,7 +505,7 @@ try_hashjoin_path(PlannerInfo *root,
* Independently of that, add parameterization needed for any
* PlaceHolderVars that need to be computed at the join.
*/
- required_outer = bms_add_members(required_outer, extra_lateral_rels);
+ required_outer = bms_add_members(required_outer, joinrel->lateral_relids);
/*
* See comments in try_nestloop_path(). Also note that hashjoin paths
@@ -630,7 +585,6 @@ clause_sides_match_join(RestrictInfo *rinfo, RelOptInfo *outerrel,
* 'jointype' is the type of join to do
* 'sjinfo' is extra info about the join for selectivity estimation
* 'param_source_rels' are OK targets for parameterization of result paths
- * 'extra_lateral_rels' are additional parameterization for result paths
*/
static void
sort_inner_and_outer(PlannerInfo *root,
@@ -641,8 +595,7 @@ sort_inner_and_outer(PlannerInfo *root,
List *mergeclause_list,
JoinType jointype,
SpecialJoinInfo *sjinfo,
- Relids param_source_rels,
- Relids extra_lateral_rels)
+ Relids param_source_rels)
{
Path *outer_path;
Path *inner_path;
@@ -772,7 +725,6 @@ sort_inner_and_outer(PlannerInfo *root,
jointype,
sjinfo,
param_source_rels,
- extra_lateral_rels,
outer_path,
inner_path,
restrictlist,
@@ -818,7 +770,6 @@ sort_inner_and_outer(PlannerInfo *root,
* 'sjinfo' is extra info about the join for selectivity estimation
* 'semifactors' contains valid data if jointype is SEMI or ANTI
* 'param_source_rels' are OK targets for parameterization of result paths
- * 'extra_lateral_rels' are additional parameterization for result paths
*/
static void
match_unsorted_outer(PlannerInfo *root,
@@ -830,8 +781,7 @@ match_unsorted_outer(PlannerInfo *root,
JoinType jointype,
SpecialJoinInfo *sjinfo,
SemiAntiJoinFactors *semifactors,
- Relids param_source_rels,
- Relids extra_lateral_rels)
+ Relids param_source_rels)
{
JoinType save_jointype = jointype;
bool nestjoinOK;
@@ -961,7 +911,6 @@ match_unsorted_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
- extra_lateral_rels,
outerpath,
inner_cheapest_total,
restrictlist,
@@ -987,7 +936,6 @@ match_unsorted_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
- extra_lateral_rels,
outerpath,
innerpath,
restrictlist,
@@ -1002,7 +950,6 @@ match_unsorted_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
- extra_lateral_rels,
outerpath,
matpath,
restrictlist,
@@ -1058,7 +1005,6 @@ match_unsorted_outer(PlannerInfo *root,
jointype,
sjinfo,
param_source_rels,
- extra_lateral_rels,
outerpath,
inner_cheapest_total,
restrictlist,
@@ -1157,7 +1103,6 @@ match_unsorted_outer(PlannerInfo *root,
jointype,
sjinfo,
param_source_rels,
- extra_lateral_rels,
outerpath,
innerpath,
restrictlist,
@@ -1203,7 +1148,6 @@ match_unsorted_outer(PlannerInfo *root,
jointype,
sjinfo,
param_source_rels,
- extra_lateral_rels,
outerpath,
innerpath,
restrictlist,
@@ -1238,7 +1182,6 @@ match_unsorted_outer(PlannerInfo *root,
* 'sjinfo' is extra info about the join for selectivity estimation
* 'semifactors' contains valid data if jointype is SEMI or ANTI
* 'param_source_rels' are OK targets for parameterization of result paths
- * 'extra_lateral_rels' are additional parameterization for result paths
*/
static void
hash_inner_and_outer(PlannerInfo *root,
@@ -1249,8 +1192,7 @@ hash_inner_and_outer(PlannerInfo *root,
JoinType jointype,
SpecialJoinInfo *sjinfo,
SemiAntiJoinFactors *semifactors,
- Relids param_source_rels,
- Relids extra_lateral_rels)
+ Relids param_source_rels)
{
bool isouterjoin = IS_OUTER_JOIN(jointype);
List *hashclauses;
@@ -1324,7 +1266,6 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
- extra_lateral_rels,
cheapest_total_outer,
cheapest_total_inner,
restrictlist,
@@ -1344,7 +1285,6 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
- extra_lateral_rels,
cheapest_total_outer,
cheapest_total_inner,
restrictlist,
@@ -1357,7 +1297,6 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
- extra_lateral_rels,
cheapest_startup_outer,
cheapest_total_inner,
restrictlist,
@@ -1382,7 +1321,6 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
- extra_lateral_rels,
cheapest_startup_outer,
cheapest_total_inner,
restrictlist,
@@ -1420,7 +1358,6 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
- extra_lateral_rels,
outerpath,
innerpath,
restrictlist,
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index fab5cd4d8b9..79842bbdaca 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -376,7 +376,7 @@ build_join_rel(PlannerInfo *root,
joinrel->attr_needed = NULL;
joinrel->attr_widths = NULL;
joinrel->lateral_vars = NIL;
- joinrel->lateral_relids = NULL;
+ joinrel->lateral_relids = min_join_parameterization(root, joinrel->relids);
joinrel->lateral_referencers = NULL;
joinrel->indexlist = NIL;
joinrel->pages = 0;
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index d5513ffb316..1cbc6b2ea9a 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -349,7 +349,7 @@ typedef struct PlannerInfo
* lateral_vars - lateral cross-references of rel, if any (list of
* Vars and PlaceHolderVars)
* lateral_relids - required outer rels for LATERAL, as a Relids set
- * (for child rels this can be more than lateral_vars)
+ * (this is now used for join rels too, but we won't move it till 9.5)
* lateral_referencers - relids of rels that reference this one laterally
* indexlist - list of IndexOptInfo nodes for relation's indexes
* (always NIL if it's not a table)
@@ -368,7 +368,7 @@ typedef struct PlannerInfo
* and fdw_private are filled during initial path creation.
*
* For otherrels that are appendrel members, these fields are filled
- * in just as for a baserel.
+ * in just as for a baserel, except we don't bother with lateral_vars.
*
* The presence of the remaining fields depends on the restrictions
* and joins that the relation participates in: