From 99e922a01db6d9ff7f68bea67ecfed62f2bad948 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 17 Dec 2003 17:07:48 +0000 Subject: [PATCH] Repair planner failure when there are multiple IN clauses, each with a join in its subselect. In this situation we *must* build a bushy plan because there are no valid left-sided or right-sided join trees. Accordingly, hoary sanity check needs an update. Per report from Alessandro Depase. --- src/backend/optimizer/path/allpaths.c | 4 +++- src/backend/optimizer/path/joinrels.c | 21 +++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index cc6a1cdf40..1f979dd409 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.109 2003/11/29 19:51:50 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.110 2003/12/17 17:07:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -545,6 +545,8 @@ make_one_rel_by_joins(Query *root, int levels_needed, List *initial_rels) /* * We should have a single rel at the final level. */ + if (joinitems[levels_needed] == NIL) + elog(ERROR, "failed to build any %d-way joins", levels_needed); Assert(length(joinitems[levels_needed]) == 1); rel = (RelOptInfo *) lfirst(joinitems[levels_needed]); diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 1ac9a3064b..26ff2e5758 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.64 2003/11/29 19:51:50 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.65 2003/12/17 17:07:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -226,7 +226,24 @@ make_rels_by_joins(Query *root, int level, List **joinrels) } } - if (result_rels == NIL) + /*---------- + * When IN clauses are involved, there may be no legal way to make + * an N-way join for some values of N. For example consider + * + * SELECT ... FROM t1 WHERE + * x IN (SELECT ... FROM t2,t3 WHERE ...) AND + * y IN (SELECT ... FROM t4,t5 WHERE ...) + * + * We will flatten this query to a 5-way join problem, but there are + * no 4-way joins that make_join_rel() will consider legal. We have + * to accept failure at level 4 and go on to discover a workable + * bushy plan at level 5. + * + * However, if there are no IN clauses then make_join_rel() should + * never fail, and so the following sanity check is useful. + *---------- + */ + if (result_rels == NIL && root->in_info_list == NIL) elog(ERROR, "failed to build any %d-way joins", level); }