In cost_mergejoin, the early-exit effect should not apply to the
authorTom Lane <[email protected]>
Mon, 4 Apr 2005 01:43:33 +0000 (01:43 +0000)
committerTom Lane <[email protected]>
Mon, 4 Apr 2005 01:43:33 +0000 (01:43 +0000)
outer side of an outer join.  Per andrew@supernews.

src/backend/optimizer/path/costsize.c

index c151ddd5f167eed5261d468fd7900780ef61c5f3..3406f9708c7d58f80c1e7fe92cca4c8aa5bf42f8 100644 (file)
@@ -49,7 +49,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.115.2.2 2004/04/06 18:46:25 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.115.2.3 2005/04/04 01:43:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -919,16 +919,17 @@ cost_mergejoin(MergePath *path, Query *root)
    rescanratio = 1.0 + (rescannedtuples / inner_path_rows);
 
    /*
-    * A merge join will stop as soon as it exhausts either input stream.
-    * Estimate fraction of the left and right inputs that will actually
-    * need to be scanned.  We use only the first (most significant) merge
-    * clause for this purpose.
+    * A merge join will stop as soon as it exhausts either input stream
+    * (unless it's an outer join, in which case the outer side has to be
+    * scanned all the way anyway).  Estimate fraction of the left and right
+    * inputs that will actually need to be scanned. We use only the first
+    * (most significant) merge clause for this purpose.
     *
     * Since this calculation is somewhat expensive, and will be the same for
     * all mergejoin paths associated with the merge clause, we cache the
     * results in the RestrictInfo node.
     */
-   if (mergeclauses)
+   if (mergeclauses && path->jpath.jointype != JOIN_FULL)
    {
        firstclause = (RestrictInfo *) lfirst(mergeclauses);
        if (firstclause->left_mergescansel < 0) /* not computed yet? */
@@ -948,10 +949,14 @@ cost_mergejoin(MergePath *path, Query *root)
            outerscansel = firstclause->right_mergescansel;
            innerscansel = firstclause->left_mergescansel;
        }
+       if (path->jpath.jointype == JOIN_LEFT)
+           outerscansel = 1.0;
+       else if (path->jpath.jointype == JOIN_RIGHT)
+           innerscansel = 1.0;
    }
    else
    {
-       /* cope with clauseless mergejoin */
+       /* cope with clauseless or full mergejoin */
        outerscansel = innerscansel = 1.0;
    }