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,
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);
* 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);
/*
* 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
static void
match_join_clauses_to_index(PlannerInfo *root,
RelOptInfo *rel, IndexOptInfo *index,
+ Relids lateral_referencers,
IndexClauseSet *clauseset,
List **joinorclauses)
{
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);
*/
static void
match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index,
+ Relids lateral_referencers,
IndexClauseSet *clauseset)
{
int indexcol;
{
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,