aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/path/equivclass.c35
-rw-r--r--src/backend/optimizer/path/indxpath.c41
-rw-r--r--src/include/optimizer/paths.h18
3 files changed, 60 insertions, 34 deletions
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index e2df448db6c..5c4ac066a52 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -512,7 +512,7 @@ add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids,
* be more than one EC that matches the expression; if so it's order-dependent
* which one you get. This is annoying but it only happens in corner cases,
* so for now we live with just reporting the first match. See also
- * generate_implied_equalities_for_indexcol and match_pathkeys_to_index.)
+ * generate_implied_equalities_for_column and match_pathkeys_to_index.)
*
* If create_it is TRUE, we'll build a new EquivalenceClass when there is no
* match. If create_it is FALSE, we just return NULL when no match.
@@ -2013,15 +2013,21 @@ mutate_eclass_expressions(PlannerInfo *root,
/*
- * generate_implied_equalities_for_indexcol
- * Create EC-derived joinclauses usable with a specific index column.
+ * generate_implied_equalities_for_column
+ * Create EC-derived joinclauses usable with a specific column.
*
- * We assume that any given index column could appear in only one EC.
+ * This is used by indxpath.c to extract potentially indexable joinclauses
+ * from ECs, and can be used by foreign data wrappers for similar purposes.
+ * We assume that only expressions in Vars of a single table are of interest,
+ * but the caller provides a callback function to identify exactly which
+ * such expressions it would like to know about.
+ *
+ * We assume that any given table/index column could appear in only one EC.
* (This should be true in all but the most pathological cases, and if it
* isn't, we stop on the first match anyway.) Therefore, what we return
- * is a redundant list of clauses equating the index column to each of
+ * is a redundant list of clauses equating the table/index column to each of
* the other-relation values it is known to be equal to. Any one of
- * these clauses can be used to create a parameterized indexscan, and there
+ * these clauses can be used to create a parameterized path, and there
* 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.)
@@ -2030,13 +2036,13 @@ mutate_eclass_expressions(PlannerInfo *root,
* to, so as to save the work of creating useless clauses.
*/
List *
-generate_implied_equalities_for_indexcol(PlannerInfo *root,
- IndexOptInfo *index,
- int indexcol,
- Relids prohibited_rels)
+generate_implied_equalities_for_column(PlannerInfo *root,
+ RelOptInfo *rel,
+ ec_matches_callback_type callback,
+ void *callback_arg,
+ Relids prohibited_rels)
{
List *result = NIL;
- RelOptInfo *rel = index->rel;
bool is_child_rel = (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
Index parent_relid;
ListCell *lc1;
@@ -2069,11 +2075,11 @@ generate_implied_equalities_for_indexcol(PlannerInfo *root,
continue;
/*
- * Scan members, looking for a match to the indexable column. Note
+ * Scan members, looking for a match to the target column. Note
* that child EC members are considered, but only when they belong to
* the target relation. (Unlike regular members, the same expression
* could be a child member of more than one EC. Therefore, it's
- * potentially order-dependent which EC a child relation's index
+ * potentially order-dependent which EC a child relation's target
* column gets matched to. This is annoying but it only happens in
* corner cases, so for now we live with just reporting the first
* match. See also get_eclass_for_sort_expr.)
@@ -2083,8 +2089,7 @@ generate_implied_equalities_for_indexcol(PlannerInfo *root,
{
cur_em = (EquivalenceMember *) lfirst(lc2);
if (bms_equal(cur_em->em_relids, rel->relids) &&
- eclass_member_matches_indexcol(cur_ec, cur_em,
- index, indexcol))
+ callback(root, rel, cur_ec, cur_em, callback_arg))
break;
cur_em = NULL;
}
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 8e13c1fddcd..d74603983bc 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -78,6 +78,13 @@ typedef struct
Bitmapset *clauseids; /* quals+preds represented as a bitmapset */
} PathClauseUsage;
+/* Callback argument for ec_member_matches_indexcol */
+typedef struct
+{
+ IndexOptInfo *index; /* index we're considering */
+ int indexcol; /* index column we want to match to */
+} ec_member_matches_arg;
+
static void consider_index_join_clauses(PlannerInfo *root, RelOptInfo *rel,
IndexOptInfo *index,
@@ -162,6 +169,9 @@ static void match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys,
List **clause_columns_p);
static Expr *match_clause_to_ordering_op(IndexOptInfo *index,
int indexcol, Expr *clause, Oid pk_opfamily);
+static bool ec_member_matches_indexcol(PlannerInfo *root, RelOptInfo *rel,
+ EquivalenceClass *ec, EquivalenceMember *em,
+ void *arg);
static bool match_boolean_index_clause(Node *clause, int indexcol,
IndexOptInfo *index);
static bool match_special_index_operator(Expr *clause,
@@ -645,7 +655,7 @@ get_join_index_paths(PlannerInfo *root, RelOptInfo *rel,
/*
* Add applicable eclass join clauses. The clauses generated for each
- * column are redundant (cf generate_implied_equalities_for_indexcol),
+ * column are redundant (cf generate_implied_equalities_for_column),
* so we need at most one. This is the only exception to the general
* rule of using all available index clauses.
*/
@@ -1992,18 +2002,22 @@ match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index,
for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
{
+ ec_member_matches_arg arg;
List *clauses;
/* Generate clauses, skipping any that join to lateral_referencers */
- clauses = generate_implied_equalities_for_indexcol(root,
- index,
- indexcol,
- lateral_referencers);
+ arg.index = index;
+ arg.indexcol = indexcol;
+ clauses = generate_implied_equalities_for_column(root,
+ index->rel,
+ ec_member_matches_indexcol,
+ (void *) &arg,
+ lateral_referencers);
/*
* We have to check whether the results actually do match the index,
* since for non-btree indexes the EC's equality operators might not
- * be in the index opclass (cf eclass_member_matches_indexcol).
+ * be in the index opclass (cf ec_member_matches_indexcol).
*/
match_clauses_to_index(index, clauses, clauseset);
}
@@ -2682,15 +2696,18 @@ check_partial_indexes(PlannerInfo *root, RelOptInfo *rel)
****************************************************************************/
/*
- * eclass_member_matches_indexcol
+ * ec_member_matches_indexcol
* Test whether an EquivalenceClass member matches an index column.
*
- * This is exported for use by generate_implied_equalities_for_indexcol.
+ * This is a callback for use by generate_implied_equalities_for_column.
*/
-bool
-eclass_member_matches_indexcol(EquivalenceClass *ec, EquivalenceMember *em,
- IndexOptInfo *index, int indexcol)
+static bool
+ec_member_matches_indexcol(PlannerInfo *root, RelOptInfo *rel,
+ EquivalenceClass *ec, EquivalenceMember *em,
+ void *arg)
{
+ IndexOptInfo *index = ((ec_member_matches_arg *) arg)->index;
+ int indexcol = ((ec_member_matches_arg *) arg)->indexcol;
Oid curFamily = index->opfamily[indexcol];
Oid curCollation = index->indexcollations[indexcol];
@@ -2701,7 +2718,7 @@ eclass_member_matches_indexcol(EquivalenceClass *ec, EquivalenceMember *em,
* whether clauses generated from the EC could be used with the index, so
* don't check the opfamily. This might mean we return "true" for a
* useless EC, so we have to recheck the results of
- * generate_implied_equalities_for_indexcol; see
+ * generate_implied_equalities_for_column; see
* match_eclass_clauses_to_index.
*/
if (index->relam == BTREE_AM_OID &&
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index 8091b08234d..88ab4630fea 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -49,9 +49,6 @@ extern List *generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
extern bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
List *restrictlist,
List *exprlist, List *oprlist);
-extern bool eclass_member_matches_indexcol(EquivalenceClass *ec,
- EquivalenceMember *em,
- IndexOptInfo *index, int indexcol);
extern bool match_index_to_operand(Node *operand, int indexcol,
IndexOptInfo *index);
extern void expand_indexqual_conditions(IndexOptInfo *index,
@@ -99,6 +96,12 @@ extern bool have_join_order_restriction(PlannerInfo *root,
* equivclass.c
* routines for managing EquivalenceClasses
*/
+typedef bool (*ec_matches_callback_type) (PlannerInfo *root,
+ RelOptInfo *rel,
+ EquivalenceClass *ec,
+ EquivalenceMember *em,
+ void *arg);
+
extern bool process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
bool below_outer_join);
extern Expr *canonicalize_ec_expression(Expr *expr,
@@ -126,10 +129,11 @@ extern void mutate_eclass_expressions(PlannerInfo *root,
Node *(*mutator) (),
void *context,
bool include_child_exprs);
-extern List *generate_implied_equalities_for_indexcol(PlannerInfo *root,
- IndexOptInfo *index,
- int indexcol,
- Relids prohibited_rels);
+extern List *generate_implied_equalities_for_column(PlannerInfo *root,
+ RelOptInfo *rel,
+ ec_matches_callback_type callback,
+ void *callback_arg,
+ Relids prohibited_rels);
extern bool have_relevant_eclass_joinclause(PlannerInfo *root,
RelOptInfo *rel1, RelOptInfo *rel2);
extern bool has_relevant_eclass_joinclause(PlannerInfo *root,