aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/relnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/relnode.c')
-rw-r--r--src/backend/optimizer/util/relnode.c127
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;
}