aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-01-24 00:37:42 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-01-24 00:37:42 +0000
commit67a1bf1bb11ad1a916725f3bc788c5b777326b4d (patch)
tree09237f29169051b2a36ae1ea5936255999e39c0b
parent052cd647c79a2c41811b6c2b91bcfe0365d66b72 (diff)
downloadpostgresql-67a1bf1bb11ad1a916725f3bc788c5b777326b4d.tar.gz
postgresql-67a1bf1bb11ad1a916725f3bc788c5b777326b4d.zip
Repair planner failure for cases involving Cartesian products inside
IN (sub-SELECT) constructs. We must force a clauseless join of the sub-select member relations, but it wasn't happening because the code thought it would be able to use the join clause arising from the IN.
-rw-r--r--src/backend/optimizer/path/joinrels.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 07345d275d5..038e6bee742 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.63.4.1 2003/12/17 17:08:06 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.63.4.2 2004/01/24 00:37:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,6 +24,7 @@ static List *make_rels_by_clause_joins(Query *root,
static List *make_rels_by_clauseless_joins(Query *root,
RelOptInfo *old_rel,
List *other_rels);
+static bool is_inside_IN(Query *root, RelOptInfo *rel);
/*
@@ -76,14 +77,26 @@ make_rels_by_joins(Query *root, int level, List **joinrels)
/*
* 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 where we have
- * those other rels collected into a join rel. See also the
- * last-ditch case below.
+ * joins against it here. In most cases that's OK; it'll be
+ * considered by "bushy plan" join code in a higher-level pass
+ * where we have those other rels collected into a join rel.
*/
new_rels = make_rels_by_clause_joins(root,
old_rel,
other_rels);
+ /*
+ * An exception occurs when there is a clauseless join inside an
+ * IN (sub-SELECT) construct. Here, the members of the subselect
+ * all have join clauses (against the stuff outside the IN), but
+ * they *must* be joined to each other before we can make use of
+ * those join clauses. So do the clauseless join bit.
+ *
+ * See also the last-ditch case below.
+ */
+ if (new_rels == NIL && is_inside_IN(root, old_rel))
+ new_rels = make_rels_by_clauseless_joins(root,
+ old_rel,
+ other_rels);
}
else
{
@@ -348,6 +361,29 @@ make_rels_by_clauseless_joins(Query *root,
/*
+ * is_inside_IN
+ * Detect whether the specified relation is inside an IN (sub-SELECT).
+ *
+ * Note that we are actually only interested in rels that have been pulled up
+ * out of an IN, so the routine name is a slight misnomer.
+ */
+static bool
+is_inside_IN(Query *root, RelOptInfo *rel)
+{
+ List *i;
+
+ foreach(i, root->in_info_list)
+ {
+ InClauseInfo *ininfo = (InClauseInfo *) lfirst(i);
+
+ if (bms_is_subset(rel->relids, ininfo->righthand))
+ return true;
+ }
+ return false;
+}
+
+
+/*
* make_jointree_rel
* Find or build a RelOptInfo join rel representing a specific
* jointree item. For JoinExprs, we only consider the construction