aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/path/equivclass.c10
-rw-r--r--src/backend/optimizer/path/indxpath.c41
-rw-r--r--src/include/optimizer/paths.h3
3 files changed, 46 insertions, 8 deletions
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index e34b9553bd4..562177296ca 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -1969,11 +1969,15 @@ mutate_eclass_expressions(PlannerInfo *root,
* is no value in using more than one. (But it *is* worthwhile to create
* a separate parameterized path for each one, since that leads to different
* join orders.)
+ *
+ * The caller can pass a Relids set of rels we aren't interested in joining
+ * to, so as to save the work of creating useless clauses.
*/
List *
generate_implied_equalities_for_indexcol(PlannerInfo *root,
IndexOptInfo *index,
- int indexcol)
+ int indexcol,
+ Relids prohibited_rels)
{
List *result = NIL;
RelOptInfo *rel = index->rel;
@@ -2050,6 +2054,10 @@ generate_implied_equalities_for_indexcol(PlannerInfo *root,
bms_overlap(other_em->em_relids, rel->relids))
continue;
+ /* Forget it if caller doesn't want joins to this rel */
+ if (bms_overlap(other_em->em_relids, prohibited_rels))
+ continue;
+
/*
* Also, if this is a child rel, avoid generating a useless join
* to its parent rel.
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 69fcf90e361..6a321739100 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -121,10 +121,12 @@ 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,
@@ -211,22 +213,40 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
List *bitindexpaths;
List *bitjoinpaths;
List *joinorclauses;
+ Relids lateral_referencers;
IndexClauseSet rclauseset;
IndexClauseSet jclauseset;
IndexClauseSet eclauseset;
- ListCell *ilist;
+ ListCell *lc;
/* Skip the whole mess if no indexes */
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;
/* Examine each index in turn */
- foreach(ilist, rel->indexlist)
+ foreach(lc, rel->indexlist)
{
- IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);
+ IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
/* Protect limited-size array in IndexClauseSets */
Assert(index->ncolumns <= INDEX_MAX_KEYS);
@@ -260,7 +280,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,
+ match_join_clauses_to_index(root, rel, index, lateral_referencers,
&jclauseset, &joinorclauses);
/*
@@ -268,7 +288,8 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel)
* the index.
*/
MemSet(&eclauseset, 0, sizeof(eclauseset));
- match_eclass_clauses_to_index(root, index, &eclauseset);
+ match_eclass_clauses_to_index(root, index, lateral_referencers,
+ &eclauseset);
/*
* If we found any plain or eclass join clauses, decide what to do
@@ -1796,6 +1817,7 @@ 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)
{
@@ -1810,6 +1832,10 @@ match_join_clauses_to_index(PlannerInfo *root,
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))
+ continue;
+
/* Potentially usable, so see if it matches the index or is an OR */
if (restriction_is_or_clause(rinfo))
*joinorclauses = lappend(*joinorclauses, rinfo);
@@ -1825,6 +1851,7 @@ 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;
@@ -1837,9 +1864,11 @@ match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index,
{
List *clauses;
+ /* Generate clauses, skipping any that join to lateral_referencers */
clauses = generate_implied_equalities_for_indexcol(root,
index,
- indexcol);
+ indexcol,
+ lateral_referencers);
/*
* We have to check whether the results actually do match the index,
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index b6fb8ee5ce9..165856de0bc 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -127,7 +127,8 @@ extern void mutate_eclass_expressions(PlannerInfo *root,
void *context);
extern List *generate_implied_equalities_for_indexcol(PlannerInfo *root,
IndexOptInfo *index,
- int indexcol);
+ int indexcol,
+ Relids prohibited_rels);
extern bool have_relevant_eclass_joinclause(PlannerInfo *root,
RelOptInfo *rel1, RelOptInfo *rel2);
extern bool has_relevant_eclass_joinclause(PlannerInfo *root,