diff options
Diffstat (limited to 'src/backend/optimizer/util/relnode.c')
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 127 |
1 files changed, 69 insertions, 58 deletions
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 86d8107e631..8cc6c81746f 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.84 2007/01/05 22:19:33 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.85 2007/01/20 20:45:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include "optimizer/cost.h" #include "optimizer/pathnode.h" +#include "optimizer/paths.h" #include "optimizer/plancat.h" #include "optimizer/restrictinfo.h" #include "parser/parsetree.h" @@ -31,17 +32,18 @@ typedef struct JoinHashEntry static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel); static List *build_joinrel_restrictlist(PlannerInfo *root, - RelOptInfo *joinrel, - RelOptInfo *outer_rel, - RelOptInfo *inner_rel, - JoinType jointype); + RelOptInfo *joinrel, + RelOptInfo *outer_rel, + RelOptInfo *inner_rel); static void build_joinrel_joinlist(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel); static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel, - List *joininfo_list); -static void subbuild_joinrel_joinlist(RelOptInfo *joinrel, - List *joininfo_list); + List *joininfo_list, + List *new_restrictlist); +static List *subbuild_joinrel_joinlist(RelOptInfo *joinrel, + List *joininfo_list, + List *new_joininfo); /* @@ -84,6 +86,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) rel->baserestrictcost.startup = 0; rel->baserestrictcost.per_tuple = 0; rel->joininfo = NIL; + rel->has_eclass_joins = false; rel->index_outer_relids = NULL; rel->index_inner_paths = NIL; @@ -303,8 +306,7 @@ build_join_rel(PlannerInfo *root, *restrictlist_ptr = build_joinrel_restrictlist(root, joinrel, outer_rel, - inner_rel, - jointype); + inner_rel); return joinrel; } @@ -335,6 +337,7 @@ build_join_rel(PlannerInfo *root, joinrel->baserestrictcost.startup = 0; joinrel->baserestrictcost.per_tuple = 0; joinrel->joininfo = NIL; + joinrel->has_eclass_joins = false; joinrel->index_outer_relids = NULL; joinrel->index_inner_paths = NIL; @@ -354,16 +357,19 @@ build_join_rel(PlannerInfo *root, * caller might or might not need the restrictlist, but I need it anyway * for set_joinrel_size_estimates().) */ - restrictlist = build_joinrel_restrictlist(root, - joinrel, - outer_rel, - inner_rel, - jointype); + restrictlist = build_joinrel_restrictlist(root, joinrel, + outer_rel, inner_rel); if (restrictlist_ptr) *restrictlist_ptr = restrictlist; build_joinrel_joinlist(joinrel, outer_rel, inner_rel); /* + * This is also the right place to check whether the joinrel has any + * pending EquivalenceClass joins. + */ + joinrel->has_eclass_joins = has_relevant_eclass_joinclause(root, joinrel); + + /* * Set estimates of the joinrel's size. */ set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel, @@ -468,15 +474,15 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, * join paths made from this pair of sub-relations. (It will not need to * be considered further up the join tree.) * - * When building a restriction list, we eliminate redundant clauses. - * We don't try to do that for join clause lists, since the join clauses - * aren't really doing anything, just waiting to become part of higher - * levels' restriction lists. + * In many case we will find the same RestrictInfos in both input + * relations' joinlists, so be careful to eliminate duplicates. + * Pointer equality should be a sufficient test for dups, since all + * the various joinlist entries ultimately refer to RestrictInfos + * pushed into them by distribute_restrictinfo_to_rels(). * * 'joinrel' is a join relation node * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined * to form joinrel. - * 'jointype' is the type of join used. * * build_joinrel_restrictlist() returns a list of relevant restrictinfos, * whereas build_joinrel_joinlist() stores its results in the joinrel's @@ -491,33 +497,27 @@ static List * build_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, - RelOptInfo *inner_rel, - JoinType jointype) + RelOptInfo *inner_rel) { List *result; - List *rlist; /* - * Collect all the clauses that syntactically belong at this level. + * Collect all the clauses that syntactically belong at this level, + * eliminating any duplicates (important since we will see many of the + * same clauses arriving from both input relations). */ - rlist = list_concat(subbuild_joinrel_restrictlist(joinrel, - outer_rel->joininfo), - subbuild_joinrel_restrictlist(joinrel, - inner_rel->joininfo)); - + result = subbuild_joinrel_restrictlist(joinrel, outer_rel->joininfo, NIL); + result = subbuild_joinrel_restrictlist(joinrel, inner_rel->joininfo, result); /* - * Eliminate duplicate and redundant clauses. - * - * We must eliminate duplicates, since we will see many of the same - * clauses arriving from both input relations. Also, if a clause is a - * mergejoinable clause, it's possible that it is redundant with previous - * clauses (see optimizer/README for discussion). We detect that case and - * omit the redundant clause from the result list. + * Add on any clauses derived from EquivalenceClasses. These cannot be + * redundant with the clauses in the joininfo lists, so don't bother + * checking. */ - result = remove_redundant_join_clauses(root, rlist, - IS_OUTER_JOIN(jointype)); - - list_free(rlist); + result = list_concat(result, + generate_join_implied_equalities(root, + joinrel, + outer_rel, + inner_rel)); return result; } @@ -527,15 +527,24 @@ build_joinrel_joinlist(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel) { - subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo); - subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo); + List *result; + + /* + * Collect all the clauses that syntactically belong above this level, + * eliminating any duplicates (important since we will see many of the + * same clauses arriving from both input relations). + */ + result = subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo, NIL); + result = subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo, result); + + joinrel->joininfo = result; } static List * subbuild_joinrel_restrictlist(RelOptInfo *joinrel, - List *joininfo_list) + List *joininfo_list, + List *new_restrictlist) { - List *restrictlist = NIL; ListCell *l; foreach(l, joininfo_list) @@ -546,10 +555,12 @@ subbuild_joinrel_restrictlist(RelOptInfo *joinrel, { /* * This clause becomes a restriction clause for the joinrel, since - * it refers to no outside rels. We don't bother to check for - * duplicates here --- build_joinrel_restrictlist will do that. + * it refers to no outside rels. Add it to the list, being + * careful to eliminate duplicates. (Since RestrictInfo nodes in + * different joinlists will have been multiply-linked rather than + * copied, pointer equality should be a sufficient test.) */ - restrictlist = lappend(restrictlist, rinfo); + new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo); } else { @@ -560,12 +571,13 @@ subbuild_joinrel_restrictlist(RelOptInfo *joinrel, } } - return restrictlist; + return new_restrictlist; } -static void +static List * subbuild_joinrel_joinlist(RelOptInfo *joinrel, - List *joininfo_list) + List *joininfo_list, + List *new_joininfo) { ListCell *l; @@ -585,15 +597,14 @@ subbuild_joinrel_joinlist(RelOptInfo *joinrel, { /* * This clause is still a join clause at this level, so add it to - * the joininfo list for the joinrel, being careful to eliminate - * duplicates. (Since RestrictInfo nodes are normally - * multiply-linked rather than copied, pointer equality should be - * a sufficient test. If two equal() nodes should happen to sneak - * in, no great harm is done --- they'll be detected by - * redundant-clause testing when they reach a restriction list.) + * the new joininfo list, being careful to eliminate + * duplicates. (Since RestrictInfo nodes in different joinlists + * will have been multiply-linked rather than copied, pointer + * equality should be a sufficient test.) */ - joinrel->joininfo = list_append_unique_ptr(joinrel->joininfo, - rinfo); + new_joininfo = list_append_unique_ptr(new_joininfo, rinfo); } } + + return new_joininfo; } |