OSDN Git Service

Repair planner failure when there are multiple IN clauses, each with
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 17 Dec 2003 17:07:48 +0000 (17:07 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 17 Dec 2003 17:07:48 +0000 (17:07 +0000)
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
src/backend/optimizer/path/joinrels.c

index cc6a1cd..1f979dd 100644 (file)
@@ -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]);
index 1ac9a30..26ff2e5 100644 (file)
@@ -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);
        }