aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-08-17 20:22:41 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2013-08-17 20:22:41 -0400
commit517db4945560358a82b9152d01cfad3bbd2af17e (patch)
treeebc6a2807696fdb860aec87e19b806430500a4b3 /src/backend/optimizer/path
parent2505aaed7be290018f999f6e9250c24b26db97d0 (diff)
downloadpostgresql-517db4945560358a82b9152d01cfad3bbd2af17e.tar.gz
postgresql-517db4945560358a82b9152d01cfad3bbd2af17e.zip
Fix planner problems with LATERAL references in PlaceHolderVars.
The planner largely failed to consider the possibility that a PlaceHolderVar's expression might contain a lateral reference to a Var coming from somewhere outside the PHV's syntactic scope. We had a previous report of a problem in this area, which I tried to fix in a quick-hack way in commit 4da6439bd8553059766011e2a42c6e39df08717f, but Antonin Houska pointed out that there were still some problems, and investigation turned up other issues. This patch largely reverts that commit in favor of a more thoroughly thought-through solution. The new theory is that a PHV's ph_eval_at level cannot be higher than its original syntactic level. If it contains lateral references, those don't change the ph_eval_at level, but rather they create a lateral-reference requirement for the ph_eval_at join relation. The code in joinpath.c needs to handle that. Another issue is that createplan.c wasn't handling nested PlaceHolderVars properly. In passing, push knowledge of lateral-reference checks for join clauses into join_clause_is_movable_to. This is mainly so that FDWs don't need to deal with it. This patch doesn't fix the original join-qual-placement problem reported by Jeremy Evans (and indeed, one of the new regression test cases shows the wrong answer because of that). But the PlaceHolderVar problems need to be fixed before that issue can be addressed, so committing this separately seems reasonable.
Diffstat (limited to 'src/backend/optimizer/path')
-rw-r--r--src/backend/optimizer/path/allpaths.c16
-rw-r--r--src/backend/optimizer/path/costsize.c7
-rw-r--r--src/backend/optimizer/path/indxpath.c52
-rw-r--r--src/backend/optimizer/path/joinpath.c103
-rw-r--r--src/backend/optimizer/path/joinrels.c10
-rw-r--r--src/backend/optimizer/path/orindxpath.c2
-rw-r--r--src/backend/optimizer/path/tidpath.c3
7 files changed, 121 insertions, 72 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 4b8a73d60f4..bfd3809a007 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -386,8 +386,7 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
/*
* We don't support pushing join clauses into the quals of a seqscan, but
* it could still have required parameterization due to LATERAL refs in
- * its tlist. (That can only happen if the seqscan is on a relation
- * pulled up out of a UNION ALL appendrel.)
+ * its tlist.
*/
required_outer = rel->lateral_relids;
@@ -550,8 +549,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
* Note: the resulting childrel->reltargetlist may contain arbitrary
* expressions, which otherwise would not occur in a reltargetlist.
* Code that might be looking at an appendrel child must cope with
- * such. Note in particular that "arbitrary expression" can include
- * "Var belonging to another relation", due to LATERAL references.
+ * such. (Normally, a reltargetlist would only include Vars and
+ * PlaceHolderVars.)
*/
childrel->joininfo = (List *)
adjust_appendrel_attrs(root,
@@ -1355,8 +1354,7 @@ set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
/*
* We don't support pushing join clauses into the quals of a CTE scan, but
* it could still have required parameterization due to LATERAL refs in
- * its tlist. (That can only happen if the CTE scan is on a relation
- * pulled up out of a UNION ALL appendrel.)
+ * its tlist.
*/
required_outer = rel->lateral_relids;
@@ -1408,10 +1406,8 @@ set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
/*
* We don't support pushing join clauses into the quals of a worktable
* scan, but it could still have required parameterization due to LATERAL
- * refs in its tlist. (That can only happen if the worktable scan is on a
- * relation pulled up out of a UNION ALL appendrel. I'm not sure this is
- * actually possible given the restrictions on recursive references, but
- * it's easy enough to support.)
+ * refs in its tlist. (I'm not sure this is actually possible given the
+ * restrictions on recursive references, but it's easy enough to support.)
*/
required_outer = rel->lateral_relids;
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 3507f18007e..a2cc6979594 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -3935,10 +3935,9 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel)
/*
* Ordinarily, a Var in a rel's reltargetlist must belong to that rel;
- * but there are corner cases involving LATERAL references in
- * appendrel members where that isn't so (see set_append_rel_size()).
- * If the Var has the wrong varno, fall through to the generic case
- * (it doesn't seem worth the trouble to be any smarter).
+ * but there are corner cases involving LATERAL references where that
+ * isn't so. If the Var has the wrong varno, fall through to the
+ * generic case (it doesn't seem worth the trouble to be any smarter).
*/
if (IsA(node, Var) &&
((Var *) node)->varno == rel->relid)
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 65eb344cde4..606734a1221 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -141,12 +141,10 @@ static void match_restriction_clauses_to_index(RelOptInfo *rel,
IndexClauseSet *clauseset);
static void match_join_clauses_to_index(PlannerInfo *root,
RelOptInfo *rel, IndexOptInfo *index,
- Relids lateral_referencers,
IndexClauseSet *clauseset,
List **joinorclauses);
static void match_eclass_clauses_to_index(PlannerInfo *root,
IndexOptInfo *index,
- Relids lateral_referencers,
IndexClauseSet *clauseset);
static void match_clauses_to_index(IndexOptInfo *index,
List *clauses,
@@ -220,14 +218,14 @@ static Const *string_to_const(const char *str, Oid datatype);
*
* Note: check_partial_indexes() must have been run previously for this rel.
*
- * Note: in corner cases involving LATERAL appendrel children, it's possible
- * that rel->lateral_relids is nonempty. Currently, we include lateral_relids
- * into the parameterization reported for each path, but don't take it into
- * account otherwise. The fact that any such rels *must* be available as
- * parameter sources perhaps should influence our choices of index quals ...
- * but for now, it doesn't seem worth troubling over. In particular, comments
- * below about "unparameterized" paths should be read as meaning
- * "unparameterized so far as the indexquals are concerned".
+ * Note: in cases involving LATERAL references in the relation's tlist, it's
+ * possible that rel->lateral_relids is nonempty. Currently, we include
+ * lateral_relids into the parameterization reported for each path, but don't
+ * take it into account otherwise. The fact that any such rels *must* be
+ * available as parameter sources perhaps should influence our choices of
+ * index quals ... but for now, it doesn't seem worth troubling over.
+ * In particular, comments below about "unparameterized" paths should be read
+ * as meaning "unparameterized so far as the indexquals are concerned".
*/
void
create_index_paths(PlannerInfo *root, RelOptInfo *rel)
@@ -236,7 +234,6 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
List *bitindexpaths;
List *bitjoinpaths;
List *joinorclauses;
- Relids lateral_referencers;
IndexClauseSet rclauseset;
IndexClauseSet jclauseset;
IndexClauseSet eclauseset;
@@ -246,23 +243,6 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
if (rel->indexlist == NIL)
return;
- /*
- * If there are any rels that have LATERAL references to this one, we
- * cannot use join quals referencing them as index quals for this one,
- * since such rels would have to be on the inside not the outside of a
- * nestloop join relative to this one. Create a Relids set listing all
- * such rels, for use in checks of potential join clauses.
- */
- lateral_referencers = NULL;
- foreach(lc, root->lateral_info_list)
- {
- LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(lc);
-
- if (bms_is_member(rel->relid, ljinfo->lateral_lhs))
- lateral_referencers = bms_add_member(lateral_referencers,
- ljinfo->lateral_rhs);
- }
-
/* Bitmap paths are collected and then dealt with at the end */
bitindexpaths = bitjoinpaths = joinorclauses = NIL;
@@ -303,7 +283,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
* EquivalenceClasses. Also, collect join OR clauses for later.
*/
MemSet(&jclauseset, 0, sizeof(jclauseset));
- match_join_clauses_to_index(root, rel, index, lateral_referencers,
+ match_join_clauses_to_index(root, rel, index,
&jclauseset, &joinorclauses);
/*
@@ -311,7 +291,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
* the index.
*/
MemSet(&eclauseset, 0, sizeof(eclauseset));
- match_eclass_clauses_to_index(root, index, lateral_referencers,
+ match_eclass_clauses_to_index(root, index,
&eclauseset);
/*
@@ -1957,7 +1937,6 @@ match_restriction_clauses_to_index(RelOptInfo *rel, IndexOptInfo *index,
static void
match_join_clauses_to_index(PlannerInfo *root,
RelOptInfo *rel, IndexOptInfo *index,
- Relids lateral_referencers,
IndexClauseSet *clauseset,
List **joinorclauses)
{
@@ -1969,11 +1948,7 @@ match_join_clauses_to_index(PlannerInfo *root,
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
/* Check if clause can be moved to this rel */
- if (!join_clause_is_movable_to(rinfo, rel->relid))
- continue;
-
- /* Not useful if it conflicts with any LATERAL references */
- if (bms_overlap(rinfo->clause_relids, lateral_referencers))
+ if (!join_clause_is_movable_to(rinfo, rel))
continue;
/* Potentially usable, so see if it matches the index or is an OR */
@@ -1991,7 +1966,6 @@ match_join_clauses_to_index(PlannerInfo *root,
*/
static void
match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index,
- Relids lateral_referencers,
IndexClauseSet *clauseset)
{
int indexcol;
@@ -2012,7 +1986,7 @@ match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index,
index->rel,
ec_member_matches_indexcol,
(void *) &arg,
- lateral_referencers);
+ index->rel->lateral_referencers);
/*
* We have to check whether the results actually do match the index,
@@ -2644,7 +2618,7 @@ check_partial_indexes(PlannerInfo *root, RelOptInfo *rel)
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
/* Check if clause can be moved to this rel */
- if (!join_clause_is_movable_to(rinfo, rel->relid))
+ if (!join_clause_is_movable_to(rinfo, rel))
continue;
clauselist = lappend(clauselist, rinfo);
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index d6050a616c7..5b477e52d3f 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 param_source_rels, Relids extra_lateral_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 param_source_rels, Relids extra_lateral_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 param_source_rels, Relids extra_lateral_rels);
static List *select_mergejoin_clauses(PlannerInfo *root,
RelOptInfo *joinrel,
RelOptInfo *outerrel,
@@ -87,6 +87,7 @@ add_paths_to_joinrel(PlannerInfo *root,
bool mergejoin_allowed = true;
SemiAntiJoinFactors semifactors;
Relids param_source_rels = NULL;
+ Relids extra_lateral_rels = NULL;
ListCell *lc;
/*
@@ -162,20 +163,58 @@ add_paths_to_joinrel(PlannerInfo *root,
{
LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(lc);
- if (bms_is_member(ljinfo->lateral_rhs, joinrel->relids))
+ 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;
+
+ /*
* 1. Consider mergejoin paths where both relations must be explicitly
* sorted. Skip this if we can't mergejoin.
*/
if (mergejoin_allowed)
sort_inner_and_outer(root, joinrel, outerrel, innerrel,
restrictlist, mergeclause_list, jointype,
- sjinfo, param_source_rels);
+ sjinfo,
+ param_source_rels, extra_lateral_rels);
/*
* 2. Consider paths where the outer relation need not be explicitly
@@ -187,7 +226,8 @@ add_paths_to_joinrel(PlannerInfo *root,
if (mergejoin_allowed)
match_unsorted_outer(root, joinrel, outerrel, innerrel,
restrictlist, mergeclause_list, jointype,
- sjinfo, &semifactors, param_source_rels);
+ sjinfo, &semifactors,
+ param_source_rels, extra_lateral_rels);
#ifdef NOT_USED
@@ -205,7 +245,8 @@ add_paths_to_joinrel(PlannerInfo *root,
if (mergejoin_allowed)
match_unsorted_inner(root, joinrel, outerrel, innerrel,
restrictlist, mergeclause_list, jointype,
- sjinfo, &semifactors, param_source_rels);
+ sjinfo, &semifactors,
+ param_source_rels, extra_lateral_rels);
#endif
/*
@@ -216,7 +257,8 @@ add_paths_to_joinrel(PlannerInfo *root,
if (enable_hashjoin || jointype == JOIN_FULL)
hash_inner_and_outer(root, joinrel, outerrel, innerrel,
restrictlist, jointype,
- sjinfo, &semifactors, param_source_rels);
+ sjinfo, &semifactors,
+ param_source_rels, extra_lateral_rels);
}
/*
@@ -231,6 +273,7 @@ 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,
@@ -254,6 +297,12 @@ try_nestloop_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);
+
+ /*
* Do a precheck to quickly eliminate obviously-inferior paths. We
* calculate a cheap lower bound on the path's cost and then use
* add_path_precheck() to see if the path is clearly going to be dominated
@@ -301,6 +350,7 @@ 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,
@@ -327,6 +377,12 @@ 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);
+
+ /*
* If the given paths are already well enough ordered, we can skip doing
* an explicit sort.
*/
@@ -383,6 +439,7 @@ 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,
@@ -406,6 +463,12 @@ 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);
+
+ /*
* See comments in try_nestloop_path(). Also note that hashjoin paths
* never have any output pathkeys, per comments in create_hashjoin_path.
*/
@@ -483,6 +546,7 @@ 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,
@@ -493,7 +557,8 @@ sort_inner_and_outer(PlannerInfo *root,
List *mergeclause_list,
JoinType jointype,
SpecialJoinInfo *sjinfo,
- Relids param_source_rels)
+ Relids param_source_rels,
+ Relids extra_lateral_rels)
{
Path *outer_path;
Path *inner_path;
@@ -623,6 +688,7 @@ sort_inner_and_outer(PlannerInfo *root,
jointype,
sjinfo,
param_source_rels,
+ extra_lateral_rels,
outer_path,
inner_path,
restrictlist,
@@ -668,6 +734,7 @@ 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,
@@ -679,7 +746,8 @@ match_unsorted_outer(PlannerInfo *root,
JoinType jointype,
SpecialJoinInfo *sjinfo,
SemiAntiJoinFactors *semifactors,
- Relids param_source_rels)
+ Relids param_source_rels,
+ Relids extra_lateral_rels)
{
JoinType save_jointype = jointype;
bool nestjoinOK;
@@ -809,6 +877,7 @@ match_unsorted_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
+ extra_lateral_rels,
outerpath,
inner_cheapest_total,
restrictlist,
@@ -834,6 +903,7 @@ match_unsorted_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
+ extra_lateral_rels,
outerpath,
innerpath,
restrictlist,
@@ -848,6 +918,7 @@ match_unsorted_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
+ extra_lateral_rels,
outerpath,
matpath,
restrictlist,
@@ -903,6 +974,7 @@ match_unsorted_outer(PlannerInfo *root,
jointype,
sjinfo,
param_source_rels,
+ extra_lateral_rels,
outerpath,
inner_cheapest_total,
restrictlist,
@@ -1001,6 +1073,7 @@ match_unsorted_outer(PlannerInfo *root,
jointype,
sjinfo,
param_source_rels,
+ extra_lateral_rels,
outerpath,
innerpath,
restrictlist,
@@ -1046,6 +1119,7 @@ match_unsorted_outer(PlannerInfo *root,
jointype,
sjinfo,
param_source_rels,
+ extra_lateral_rels,
outerpath,
innerpath,
restrictlist,
@@ -1080,6 +1154,7 @@ 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,
@@ -1090,7 +1165,8 @@ hash_inner_and_outer(PlannerInfo *root,
JoinType jointype,
SpecialJoinInfo *sjinfo,
SemiAntiJoinFactors *semifactors,
- Relids param_source_rels)
+ Relids param_source_rels,
+ Relids extra_lateral_rels)
{
bool isouterjoin = IS_OUTER_JOIN(jointype);
List *hashclauses;
@@ -1164,6 +1240,7 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
+ extra_lateral_rels,
cheapest_total_outer,
cheapest_total_inner,
restrictlist,
@@ -1183,6 +1260,7 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
+ extra_lateral_rels,
cheapest_total_outer,
cheapest_total_inner,
restrictlist,
@@ -1195,6 +1273,7 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
+ extra_lateral_rels,
cheapest_startup_outer,
cheapest_total_inner,
restrictlist,
@@ -1219,6 +1298,7 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
+ extra_lateral_rels,
cheapest_startup_outer,
cheapest_total_inner,
restrictlist,
@@ -1256,6 +1336,7 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo,
semifactors,
param_source_rels,
+ extra_lateral_rels,
outerpath,
innerpath,
restrictlist,
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 819498a4281..d627f9e130c 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -526,7 +526,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
{
LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(l);
- if (bms_is_member(ljinfo->lateral_rhs, rel2->relids) &&
+ if (bms_is_subset(ljinfo->lateral_rhs, rel2->relids) &&
bms_overlap(ljinfo->lateral_lhs, rel1->relids))
{
/* has to be implemented as nestloop with rel1 on left */
@@ -539,7 +539,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
(reversed || match_sjinfo->jointype == JOIN_FULL))
return false; /* not implementable as nestloop */
}
- if (bms_is_member(ljinfo->lateral_rhs, rel1->relids) &&
+ if (bms_is_subset(ljinfo->lateral_rhs, rel1->relids) &&
bms_overlap(ljinfo->lateral_lhs, rel2->relids))
{
/* has to be implemented as nestloop with rel2 on left */
@@ -829,10 +829,10 @@ have_join_order_restriction(PlannerInfo *root,
{
LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(l);
- if (bms_is_member(ljinfo->lateral_rhs, rel2->relids) &&
+ if (bms_is_subset(ljinfo->lateral_rhs, rel2->relids) &&
bms_overlap(ljinfo->lateral_lhs, rel1->relids))
return true;
- if (bms_is_member(ljinfo->lateral_rhs, rel1->relids) &&
+ if (bms_is_subset(ljinfo->lateral_rhs, rel1->relids) &&
bms_overlap(ljinfo->lateral_lhs, rel2->relids))
return true;
}
@@ -928,7 +928,7 @@ has_join_restriction(PlannerInfo *root, RelOptInfo *rel)
{
LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(l);
- if (bms_is_member(ljinfo->lateral_rhs, rel->relids) ||
+ if (bms_is_subset(ljinfo->lateral_rhs, rel->relids) ||
bms_overlap(ljinfo->lateral_lhs, rel->relids))
return true;
}
diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c
index e51e5c08b52..16f29d350fd 100644
--- a/src/backend/optimizer/path/orindxpath.c
+++ b/src/backend/optimizer/path/orindxpath.c
@@ -103,7 +103,7 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel)
RestrictInfo *rinfo = (RestrictInfo *) lfirst(i);
if (restriction_is_or_clause(rinfo) &&
- join_clause_is_movable_to(rinfo, rel->relid))
+ join_clause_is_movable_to(rinfo, rel))
{
/*
* Use the generate_bitmap_or_paths() machinery to estimate the
diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c
index f49d0f96d04..256856da35e 100644
--- a/src/backend/optimizer/path/tidpath.c
+++ b/src/backend/optimizer/path/tidpath.c
@@ -255,8 +255,7 @@ create_tidscan_paths(PlannerInfo *root, RelOptInfo *rel)
/*
* We don't support pushing join clauses into the quals of a tidscan, but
* it could still have required parameterization due to LATERAL refs in
- * its tlist. (That can only happen if the tidscan is on a relation
- * pulled up out of a UNION ALL appendrel.)
+ * its tlist.
*/
required_outer = rel->lateral_relids;