4949 * Portions Copyright (c) 1994, Regents of the University of California
5050 *
5151 * IDENTIFICATION
52- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.122 2004/01/06 04:31:01 tgl Exp $
52+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.123 2004/01/19 03:52:28 tgl Exp $
5353 *
5454 *-------------------------------------------------------------------------
5555 */
@@ -763,9 +763,7 @@ cost_nestloop(NestPath *path, Query *root)
763763 * an outer tuple as soon as we have one match. Account for the
764764 * effects of this by scaling down the cost estimates in proportion to
765765 * the JOIN_IN selectivity. (This assumes that all the quals
766- * attached to the join are IN quals, which should be true.) This would
767- * probably be the wrong approach if an input path is a UniquePath, but
768- * we'd never have that with JOIN_IN join type.
766+ * attached to the join are IN quals, which should be true.)
769767 */
770768joininfactor = join_in_selectivity (path ,root );
771769
@@ -1001,9 +999,7 @@ cost_mergejoin(MergePath *path, Query *root)
1001999 * for an outer tuple as soon as we have one match. Account for the
10021000 * effects of this by scaling down the cost estimates in proportion to
10031001 * the expected output size. (This assumes that all the quals
1004- * attached to the join are IN quals, which should be true.) This would
1005- * probably be the wrong approach if an input path is a UniquePath, but
1006- * we'd never have that with JOIN_IN join type.
1002+ * attached to the join are IN quals, which should be true.)
10071003 */
10081004joininfactor = join_in_selectivity (& path -> jpath ,root );
10091005
@@ -1208,9 +1204,7 @@ cost_hashjoin(HashPath *path, Query *root)
12081204 * an outer tuple as soon as we have one match. Account for the
12091205 * effects of this by scaling down the cost estimates in proportion to
12101206 * the expected output size. (This assumes that all the quals
1211- * attached to the join are IN quals, which should be true.) This would
1212- * probably be the wrong approach if an input path is a UniquePath, but
1213- * we'd never have that with JOIN_IN join type.
1207+ * attached to the join are IN quals, which should be true.)
12141208 */
12151209joininfactor = join_in_selectivity (& path -> jpath ,root );
12161210
@@ -1779,12 +1773,31 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
17791773static Selectivity
17801774join_in_selectivity (JoinPath * path ,Query * root )
17811775{
1776+ RelOptInfo * innerrel ;
1777+ UniquePath * innerunique ;
17821778Selectivity selec ;
17831779double nrows ;
17841780
1781+ /* Return 1.0 whenever it's not JOIN_IN */
17851782if (path -> jointype != JOIN_IN )
17861783return 1.0 ;
17871784
1785+ /*
1786+ * Return 1.0 if the inner side is already known unique. The case where
1787+ * the inner path is already a UniquePath probably cannot happen in
1788+ * current usage, but check it anyway for completeness. The interesting
1789+ * case is where we've determined the inner relation itself is unique,
1790+ * which we can check by looking at the rows estimate for its UniquePath.
1791+ */
1792+ if (IsA (path -> innerjoinpath ,UniquePath ))
1793+ return 1.0 ;
1794+ innerrel = path -> innerjoinpath -> parent ;
1795+ innerunique = create_unique_path (root ,
1796+ innerrel ,
1797+ innerrel -> cheapest_total_path );
1798+ if (innerunique -> rows >=innerrel -> rows )
1799+ return 1.0 ;
1800+
17881801/*
17891802 * Compute same result set_joinrel_size_estimates would compute
17901803 * for JOIN_INNER. Note that we use the input rels' absolute size
@@ -1796,8 +1809,7 @@ join_in_selectivity(JoinPath *path, Query *root)
17961809path -> joinrestrictinfo ,
179718100 ,
17981811JOIN_INNER );
1799- nrows = path -> outerjoinpath -> parent -> rows *
1800- path -> innerjoinpath -> parent -> rows * selec ;
1812+ nrows = path -> outerjoinpath -> parent -> rows * innerrel -> rows * selec ;
18011813
18021814nrows = clamp_row_est (nrows );
18031815