From 5d6658367843cc2464ec3f680e6a4670098fa272 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 24 Jan 2004 00:37:28 +0000 Subject: [PATCH] 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. --- src/backend/optimizer/path/joinrels.c | 46 ++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 26ff2e5758..50b9aef011 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.65 2003/12/17 17:07:48 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.66 2004/01/24 00:37:28 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 { @@ -347,6 +360,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 -- GitLab