diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/optimizer/path/equivclass.c | 35 | ||||
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 41 | ||||
-rw-r--r-- | src/include/optimizer/paths.h | 18 |
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, |