aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-12-12 21:31:02 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-12-12 21:31:02 +0000
commitf18c57fdf1dd255cc26c4b6b3d6716c8a54ab890 (patch)
treeb1f24719d0c4d25579aeb07ce141aa292873c2f4 /src
parent0afabecbfdcbcd79c13f150daf180334f6db4b27 (diff)
downloadpostgresql-f18c57fdf1dd255cc26c4b6b3d6716c8a54ab890.tar.gz
postgresql-f18c57fdf1dd255cc26c4b6b3d6716c8a54ab890.zip
Fix planner to do the right thing when a degenerate outer join (one whose
joinclause doesn't use any outer-side vars) requires a "bushy" plan to be created. The normal heuristic to avoid joins with no joinclause has to be overridden in that case. Problem is new in 8.2; before that we forced the outer join order anyway. Per example from Teodor.
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/geqo/geqo_eval.c4
-rw-r--r--src/backend/optimizer/path/joinrels.c15
-rw-r--r--src/backend/optimizer/util/joininfo.c39
-rw-r--r--src/include/optimizer/joininfo.h5
4 files changed, 52 insertions, 11 deletions
diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c
index 240672edaf5..197efac4345 100644
--- a/src/backend/optimizer/geqo/geqo_eval.c
+++ b/src/backend/optimizer/geqo/geqo_eval.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.81 2006/10/24 17:50:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.82 2006/12/12 21:31:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -258,7 +258,7 @@ desirable_join(PlannerInfo *root,
/*
* Join if there is an applicable join clause.
*/
- if (have_relevant_joinclause(outer_rel, inner_rel))
+ if (have_relevant_joinclause(root, outer_rel, inner_rel))
return true;
/*
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 17b5f31915a..98017959943 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.81 2006/10/24 17:50:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.82 2006/12/12 21:31:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -147,8 +147,13 @@ make_rels_by_joins(PlannerInfo *root, int level, List **joinrels)
ListCell *other_rels;
ListCell *r2;
- if (old_rel->joininfo == NIL)
- continue; /* we ignore clauseless joins here */
+ /*
+ * We can ignore clauseless joins here, *except* when there are
+ * outer joins --- then we might have to force a bushy outer
+ * join. See have_relevant_joinclause().
+ */
+ if (old_rel->joininfo == NIL && root->oj_info_list == NIL)
+ continue;
if (k == other_level)
other_rels = lnext(r); /* only consider remaining rels */
@@ -166,7 +171,7 @@ make_rels_by_joins(PlannerInfo *root, int level, List **joinrels)
* pair of rels. Do so if there is at least one usable
* join clause.
*/
- if (have_relevant_joinclause(old_rel, new_rel))
+ if (have_relevant_joinclause(root, old_rel, new_rel))
{
RelOptInfo *jrel;
@@ -270,7 +275,7 @@ make_rels_by_clause_joins(PlannerInfo *root,
RelOptInfo *other_rel = (RelOptInfo *) lfirst(l);
if (!bms_overlap(old_rel->relids, other_rel->relids) &&
- have_relevant_joinclause(old_rel, other_rel))
+ have_relevant_joinclause(root, old_rel, other_rel))
{
RelOptInfo *jrel;
diff --git a/src/backend/optimizer/util/joininfo.c b/src/backend/optimizer/util/joininfo.c
index 9aab37753de..bd54a1384b4 100644
--- a/src/backend/optimizer/util/joininfo.c
+++ b/src/backend/optimizer/util/joininfo.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/joininfo.c,v 1.44 2006/03/05 15:58:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/joininfo.c,v 1.45 2006/12/12 21:31:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,7 +24,8 @@
* the two given relations.
*/
bool
-have_relevant_joinclause(RelOptInfo *rel1, RelOptInfo *rel2)
+have_relevant_joinclause(PlannerInfo *root,
+ RelOptInfo *rel1, RelOptInfo *rel2)
{
bool result = false;
Relids join_relids;
@@ -53,6 +54,40 @@ have_relevant_joinclause(RelOptInfo *rel1, RelOptInfo *rel2)
}
}
+ /*
+ * It's possible that the rels correspond to the left and right sides
+ * of a degenerate outer join, that is, one with no joinclause mentioning
+ * the non-nullable side. The above scan will then have failed to locate
+ * any joinclause indicating we should join, but nonetheless we must
+ * allow the join to occur.
+ *
+ * Note: we need no comparable check for IN-joins because we can handle
+ * sequential buildup of an IN-join to multiple outer-side rels; therefore
+ * the "last ditch" case in make_rels_by_joins() always succeeds. We
+ * could dispense with this hack if we were willing to try bushy plans
+ * in the "last ditch" case, but that seems too expensive.
+ */
+ if (!result)
+ {
+ foreach(l, root->oj_info_list)
+ {
+ OuterJoinInfo *ojinfo = (OuterJoinInfo *) lfirst(l);
+
+ /* ignore full joins --- other mechanisms handle them */
+ if (ojinfo->is_full_join)
+ continue;
+
+ if ((bms_is_subset(ojinfo->min_lefthand, rel1->relids) &&
+ bms_is_subset(ojinfo->min_righthand, rel2->relids)) ||
+ (bms_is_subset(ojinfo->min_lefthand, rel2->relids) &&
+ bms_is_subset(ojinfo->min_righthand, rel1->relids)))
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+
bms_free(join_relids);
return result;
diff --git a/src/include/optimizer/joininfo.h b/src/include/optimizer/joininfo.h
index 7c4909ec1c2..1480f77835a 100644
--- a/src/include/optimizer/joininfo.h
+++ b/src/include/optimizer/joininfo.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/joininfo.h,v 1.31 2006/03/05 15:58:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/joininfo.h,v 1.32 2006/12/12 21:31:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,7 +17,8 @@
#include "nodes/relation.h"
-extern bool have_relevant_joinclause(RelOptInfo *rel1, RelOptInfo *rel2);
+extern bool have_relevant_joinclause(PlannerInfo *root,
+ RelOptInfo *rel1, RelOptInfo *rel2);
extern void add_join_clause_to_rels(PlannerInfo *root,
RestrictInfo *restrictinfo,