]> granicus.if.org Git - postgresql/commitdiff
Remove the "last ditch" code path in join_search_one_level().
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 13 Apr 2012 20:03:16 +0000 (16:03 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 13 Apr 2012 20:07:18 +0000 (16:07 -0400)
So far as I can tell, it is no longer possible for this heuristic to do
anything useful, because the new weaker definition of
have_relevant_joinclause means that any relation with a joinclause must be
considered joinable to at least one other relation.  It would still be
possible for the code block to be entered, for example if there are join
order restrictions that prevent any join of the current level from being
formed; but in that case it's just a waste of cycles to attempt to form
cartesian joins, since the restrictions will still apply.

Furthermore, IMO the existence of this code path can mask bugs elsewhere;
we would have noticed the problem with cartesian joins a lot sooner if
this code hadn't compensated for it in the simplest case.

Accordingly, let's remove it and see what happens.  I'm committing this
separately from the prerequisite changes in have_relevant_joinclause,
just to make the question easier to revisit if there is some fault in
my logic.

src/backend/optimizer/path/joinrels.c

index 2ad0b969d2510d59a698699ad3e161f6309fec2e..ea297db907de3354c2a665fb395d0bc77fb59070 100644 (file)
@@ -169,61 +169,26 @@ join_search_one_level(PlannerInfo *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 those clauses yet.  An example is
+       /*----------
+        * Normally, we should always have made at least one join of the current
+        * level.  However, when special joins 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 ...)
         *
-        * SELECT * FROM a,b,c WHERE (a.f1 + b.f2 + c.f3) = 0;
+        * We will flatten this query to a 5-way join problem, but there are
+        * no 4-way joins that join_is_legal() will consider legal.  We have
+        * to accept failure at level 4 and go on to discover a workable
+        * bushy plan at level 5.
         *
-        * 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).
+        * However, if there are no special joins then join_is_legal() should
+        * never fail, and so the following sanity check is useful.
+        *----------
         */
-       if (joinrels[level] == NIL)
-       {
-               /*
-                * This loop is just like the first one, except we always call
-                * make_rels_by_clauseless_joins().
-                */
-               foreach(r, joinrels[level - 1])
-               {
-                       RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
-                       ListCell   *other_rels;
-
-                       if (level == 2)
-                               other_rels = lnext(r);  /* only consider remaining initial
-                                                                                * rels */
-                       else
-                               other_rels = list_head(joinrels[1]);    /* consider all initial
-                                                                                                                * rels */
-
-                       make_rels_by_clauseless_joins(root,
-                                                                                 old_rel,
-                                                                                 other_rels);
-               }
-
-               /*----------
-                * When special joins 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 join_is_legal() 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 special joins then join_is_legal() should
-                * never fail, and so the following sanity check is useful.
-                *----------
-                */
-               if (joinrels[level] == NIL && root->join_info_list == NIL)
-                       elog(ERROR, "failed to build any %d-way joins", level);
-       }
+       if (joinrels[level] == NIL && root->join_info_list == NIL)
+               elog(ERROR, "failed to build any %d-way joins", level);
 }
 
 /*
@@ -751,13 +716,6 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
  * could be merged with that function, but it seems clearer to separate the
  * two concerns.  We need this test because there are degenerate cases where
  * a clauseless join must be performed to satisfy join-order restrictions.
- *
- * Note: this is only a problem if one side of a degenerate outer join
- * contains multiple rels, or a clauseless join is required within an
- * IN/EXISTS RHS; else we will find a join path via the "last ditch" case in
- * join_search_one_level().  We could dispense with this test if we were
- * willing to try bushy plans in the "last ditch" case, but that seems much
- * less efficient.
  */
 bool
 have_join_order_restriction(PlannerInfo *root,