diff options
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r-- | src/backend/optimizer/util/joininfo.c | 110 | ||||
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 13 | ||||
-rw-r--r-- | src/backend/optimizer/util/restrictinfo.c | 28 |
3 files changed, 143 insertions, 8 deletions
diff --git a/src/backend/optimizer/util/joininfo.c b/src/backend/optimizer/util/joininfo.c index c202615b1f5..79a9f7a3bac 100644 --- a/src/backend/optimizer/util/joininfo.c +++ b/src/backend/optimizer/util/joininfo.c @@ -8,13 +8,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/joininfo.c,v 1.32 2003/01/20 18:54:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/joininfo.c,v 1.33 2003/01/24 03:58:43 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "optimizer/joininfo.h" +#include "optimizer/pathnode.h" /* @@ -63,3 +64,110 @@ make_joininfo_node(RelOptInfo *this_rel, Relids join_relids) } return joininfo; } + + +/* + * add_join_clause_to_rels + * For every relation participating in a join clause, add 'restrictinfo' to + * the appropriate joininfo list (creating a new list and adding it to the + * appropriate rel node if necessary). + * + * Note that the same copy of the restrictinfo node is linked to by all the + * lists it is in. This allows us to exploit caching of information about + * the restriction clause (but we must be careful that the information does + * not depend on context). + * + * 'restrictinfo' describes the join clause + * 'join_relids' is the list of relations participating in the join clause + * (there must be more than one) + */ +void +add_join_clause_to_rels(Query *root, + RestrictInfo *restrictinfo, + Relids join_relids) +{ + List *join_relid; + + /* For every relid, find the joininfo, and add the proper join entries */ + foreach(join_relid, join_relids) + { + int cur_relid = lfirsti(join_relid); + Relids unjoined_relids = NIL; + JoinInfo *joininfo; + List *otherrel; + + /* Get the relids not equal to the current relid */ + foreach(otherrel, join_relids) + { + if (lfirsti(otherrel) != cur_relid) + unjoined_relids = lappendi(unjoined_relids, lfirsti(otherrel)); + } + Assert(unjoined_relids != NIL); + + /* + * Find or make the joininfo node for this combination of rels, + * and add the restrictinfo node to it. + */ + joininfo = make_joininfo_node(find_base_rel(root, cur_relid), + unjoined_relids); + joininfo->jinfo_restrictinfo = lappend(joininfo->jinfo_restrictinfo, + restrictinfo); + /* + * Can't freeList(unjoined_relids) because new joininfo node may + * link to it. We could avoid leaking memory by doing listCopy() + * in make_joininfo_node, but for now speed seems better. + */ + } +} + +/* + * remove_join_clause_from_rels + * Delete 'restrictinfo' from all the joininfo lists it is in + * + * This reverses the effect of add_join_clause_to_rels. It's used when we + * discover that a join clause is redundant. + * + * 'restrictinfo' describes the join clause + * 'join_relids' is the list of relations participating in the join clause + * (there must be more than one) + */ +void +remove_join_clause_from_rels(Query *root, + RestrictInfo *restrictinfo, + Relids join_relids) +{ + List *join_relid; + + /* For every relid, find the joininfo */ + foreach(join_relid, join_relids) + { + int cur_relid = lfirsti(join_relid); + Relids unjoined_relids = NIL; + JoinInfo *joininfo; + List *otherrel; + + /* Get the relids not equal to the current relid */ + foreach(otherrel, join_relids) + { + if (lfirsti(otherrel) != cur_relid) + unjoined_relids = lappendi(unjoined_relids, lfirsti(otherrel)); + } + Assert(unjoined_relids != NIL); + + /* + * Find the joininfo node for this combination of rels; it should + * exist already, if add_join_clause_to_rels was called. + */ + joininfo = find_joininfo_node(find_base_rel(root, cur_relid), + unjoined_relids); + Assert(joininfo); + /* + * Remove the restrictinfo from the list. Pointer comparison + * is sufficient. + */ + Assert(ptrMember(restrictinfo, joininfo->jinfo_restrictinfo)); + joininfo->jinfo_restrictinfo = lremove(restrictinfo, + joininfo->jinfo_restrictinfo); + freeList(unjoined_relids); + } +} diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 144fac75501..06a73bf4e9e 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.44 2003/01/20 18:54:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.45 2003/01/24 03:58:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -549,14 +549,19 @@ subbuild_joinrel_joinlist(RelOptInfo *joinrel, /* * These clauses are still join clauses at this level, so find * or make the appropriate JoinInfo item for the joinrel, and - * add the clauses to it (eliminating duplicates). + * add the clauses to it, eliminating 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.) */ JoinInfo *new_joininfo; new_joininfo = make_joininfo_node(joinrel, new_unjoined_relids); new_joininfo->jinfo_restrictinfo = - set_union(new_joininfo->jinfo_restrictinfo, - joininfo->jinfo_restrictinfo); + set_ptrUnion(new_joininfo->jinfo_restrictinfo, + joininfo->jinfo_restrictinfo); } } } diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c index bc1fcc36464..bdcc338d609 100644 --- a/src/backend/optimizer/util/restrictinfo.c +++ b/src/backend/optimizer/util/restrictinfo.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.15 2002/11/24 21:52:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.16 2003/01/24 03:58:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ #include "optimizer/clauses.h" #include "optimizer/paths.h" #include "optimizer/restrictinfo.h" +#include "optimizer/var.h" /* @@ -101,6 +102,13 @@ get_actual_join_clauses(List *restrictinfo_list, * equality between any set member on the left and any member on the right; * by transitivity, all the rest are then equal. * + * However, clauses that are of the form "var expr = const expr" cannot be + * eliminated as redundant. This is because when there are const expressions + * in a pathkey set, generate_implied_equalities() suppresses "var = var" + * clauses in favor of "var = const" clauses. We cannot afford to drop any + * of the latter, even though they might seem redundant by the pathkey + * membership test. + * * Weird special case: if we have two clauses that seem redundant * except one is pushed down into an outer join and the other isn't, * then they're not really redundant, because one constrains the @@ -120,7 +128,7 @@ remove_redundant_join_clauses(Query *root, List *restrictinfo_list, { RestrictInfo *rinfo = (RestrictInfo *) lfirst(item); - /* eliminate duplicates */ + /* always eliminate duplicates */ if (member(rinfo, result)) continue; @@ -132,6 +140,7 @@ remove_redundant_join_clauses(Query *root, List *restrictinfo_list, cache_mergeclause_pathkeys(root, rinfo); + /* do the cheap tests first */ foreach(olditem, result) { RestrictInfo *oldrinfo = (RestrictInfo *) lfirst(olditem); @@ -148,7 +157,20 @@ remove_redundant_join_clauses(Query *root, List *restrictinfo_list, } if (redundant) - continue; + { + /* + * It looks redundant, now check for "var = const" case. + * If left_relids/right_relids are set, then there are + * definitely vars on both sides; else we must check the + * hard way. + */ + if (rinfo->left_relids) + continue; /* var = var, so redundant */ + if (contain_var_clause(get_leftop(rinfo->clause)) && + contain_var_clause(get_rightop(rinfo->clause))) + continue; /* var = var, so redundant */ + /* else var = const, not redundant */ + } } /* otherwise, add it to result list */ |