summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2000-04-27 18:35:04 +0000
committerTom Lane2000-04-27 18:35:04 +0000
commitd6eac08f110f7e611b84d4f92ce68f3385ae5f55 (patch)
tree5696ab4bfab1e255e8bb713824aef5cd3547b587
parent85a53038778e8d0d7b8230aae72768b055f83037 (diff)
Repair problem noted by Elphick: make_rels_by_joins failed to handle
cases where joinclauses were present but some joins have to be made by cartesian-product join anyway. An example is SELECT * FROM a,b,c WHERE (a.f1 + b.f2 + c.f3) = 0; Even though all the rels have joinclauses, we must join two of them in cartesian style before we can use the join clause...
-rw-r--r--src/backend/optimizer/path/joinrels.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 09003eb9fa8..df37c58fc72 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.44 2000/04/12 17:15:20 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.45 2000/04/27 18:35:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,6 +39,7 @@ static RelOptInfo *make_join_rel(Query *root, RelOptInfo *rel1,
void
make_rels_by_joins(Query *root, int level)
{
+ List *first_old_rel = root->join_rel_list;
List *r;
/*
@@ -85,7 +86,9 @@ make_rels_by_joins(Query *root, int level)
* Note that if all available join clauses for this rel
* require more than one other rel, we will fail to make any
* joins against it here. That's OK; it'll be considered by
- * "bushy plan" join code in a higher-level pass.
+ * "bushy plan" join code in a higher-level pass where we
+ * have those other rels collected into a join rel. See also
+ * the last-ditch case below.
*/
make_rels_by_clause_joins(root,
old_rel,
@@ -161,6 +164,52 @@ make_rels_by_joins(Query *root, int level)
}
}
}
+
+ /*
+ * Last-ditch effort: if we failed to find any usable joins so far,
+ * force a set of cartesian-product joins to be generated. This
+ * handles the special case where all the available rels have join
+ * clauses but we cannot use any of the joins yet. An example is
+ *
+ * SELECT * FROM a,b,c WHERE (a.f1 + b.f2 + c.f3) = 0;
+ *
+ * The join clause will be usable at level 3, but at level 2 we have
+ * no choice but to make cartesian joins. We consider only left-sided
+ * and right-sided cartesian joins in this case (no bushy).
+ */
+ if (root->join_rel_list == first_old_rel)
+ {
+ /* This loop is just like the first one, except we always call
+ * make_rels_by_clauseless_joins().
+ */
+ if (level == 2)
+ r = root->base_rel_list; /* level-1 is base rels */
+ else
+ r = root->join_rel_list;
+ for (; r != NIL; r = lnext(r))
+ {
+ RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
+ int old_level = length(old_rel->relids);
+ List *other_rels;
+
+ if (old_level != level - 1)
+ break;
+
+ if (level == 2)
+ other_rels = lnext(r); /* only consider remaining base
+ * rels */
+ else
+ other_rels = root->base_rel_list; /* consider all base rels */
+
+ make_rels_by_clauseless_joins(root,
+ old_rel,
+ other_rels);
+ }
+
+ if (root->join_rel_list == first_old_rel)
+ elog(ERROR, "make_rels_by_joins: failed to build any %d-way joins",
+ level);
+ }
}
/*