1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-19 13:42:17 +03:00

Redo postgres_fdw's planner code so it can handle parameterized paths.

I wasn't going to ship this without having at least some example of how
to do that.  This version isn't terribly bright; in particular it won't
consider any combinations of multiple join clauses.  Given the cost of
executing a remote EXPLAIN, I'm not sure we want to be very aggressive
about doing that, anyway.

In support of this, refactor generate_implied_equalities_for_indexcol
so that it can be used to extract equivalence clauses that aren't
necessarily tied to an index.
This commit is contained in:
Tom Lane
2013-03-21 19:43:59 -04:00
parent 08af1a0a2a
commit 9cbc4b80dd
8 changed files with 943 additions and 577 deletions

View File

@@ -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;
}