5454 * Portions Copyright (c) 1994, Regents of the University of California
5555 *
5656 * IDENTIFICATION
57- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.167 2006/10/04 00:29:53 momjian Exp $
57+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.168 2006/11/10 01:21:41 tgl Exp $
5858 *
5959 *-------------------------------------------------------------------------
6060 */
@@ -1948,7 +1948,8 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
19481948JoinType jointype ,
19491949List * restrictlist )
19501950{
1951- Selectivity selec ;
1951+ Selectivity jselec ;
1952+ Selectivity pselec ;
19521953double nrows ;
19531954UniquePath * upath ;
19541955
@@ -1957,20 +1958,60 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
19571958 * clauses that become restriction clauses at this join level; we are not
19581959 * double-counting them because they were not considered in estimating the
19591960 * sizes of the component rels.
1961+ *
1962+ * For an outer join, we have to distinguish the selectivity of the
1963+ * join's own clauses (JOIN/ON conditions) from any clauses that were
1964+ * "pushed down". For inner joins we just count them all as joinclauses.
19601965 */
1961- selec = clauselist_selectivity (root ,
1962- restrictlist ,
1963- 0 ,
1964- jointype );
1966+ if (IS_OUTER_JOIN (jointype ))
1967+ {
1968+ List * joinquals = NIL ;
1969+ List * pushedquals = NIL ;
1970+ ListCell * l ;
1971+
1972+ /* Grovel through the clauses to separate into two lists */
1973+ foreach (l ,restrictlist )
1974+ {
1975+ RestrictInfo * rinfo = (RestrictInfo * )lfirst (l );
1976+
1977+ Assert (IsA (rinfo ,RestrictInfo ));
1978+ if (rinfo -> is_pushed_down )
1979+ pushedquals = lappend (pushedquals ,rinfo );
1980+ else
1981+ joinquals = lappend (joinquals ,rinfo );
1982+ }
1983+
1984+ /* Get the separate selectivities */
1985+ jselec = clauselist_selectivity (root ,
1986+ joinquals ,
1987+ 0 ,
1988+ jointype );
1989+ pselec = clauselist_selectivity (root ,
1990+ pushedquals ,
1991+ 0 ,
1992+ jointype );
1993+
1994+ /* Avoid leaking a lot of ListCells */
1995+ list_free (joinquals );
1996+ list_free (pushedquals );
1997+ }
1998+ else
1999+ {
2000+ jselec = clauselist_selectivity (root ,
2001+ restrictlist ,
2002+ 0 ,
2003+ jointype );
2004+ pselec = 0.0 ;/* not used, keep compiler quiet */
2005+ }
19652006
19662007/*
19672008 * Basically, we multiply size of Cartesian product by selectivity.
19682009 *
1969- * If we are doing an outer join, take that into account: theoutput must
1970- *be at least as large as thenon-nullable input.(Is there any chance
1971- *of being even smarter?)(XXX this is not really right, because it
1972- *assumes all the restriction clauses are join clauses; we should figure
1973- *pushed-down clauses separately.)
2010+ * If we are doing an outer join, take that into account: thejoinqual
2011+ *selectivity has to be clamped using theknowledge that the output must
2012+ *be at least as large as the non-nullable input. However, any
2013+ *pushed-down quals are applied after the outer join, so their
2014+ *selectivity applies fully.
19742015 *
19752016 * For JOIN_IN and variants, the Cartesian product is figured with respect
19762017 * to a unique-ified input, and then we can clamp to the size of the other
@@ -1979,38 +2020,41 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
19792020switch (jointype )
19802021{
19812022case JOIN_INNER :
1982- nrows = outer_rel -> rows * inner_rel -> rows * selec ;
2023+ nrows = outer_rel -> rows * inner_rel -> rows * jselec ;
19832024break ;
19842025case JOIN_LEFT :
1985- nrows = outer_rel -> rows * inner_rel -> rows * selec ;
2026+ nrows = outer_rel -> rows * inner_rel -> rows * jselec ;
19862027if (nrows < outer_rel -> rows )
19872028nrows = outer_rel -> rows ;
2029+ nrows *=pselec ;
19882030break ;
19892031case JOIN_RIGHT :
1990- nrows = outer_rel -> rows * inner_rel -> rows * selec ;
2032+ nrows = outer_rel -> rows * inner_rel -> rows * jselec ;
19912033if (nrows < inner_rel -> rows )
19922034nrows = inner_rel -> rows ;
2035+ nrows *=pselec ;
19932036break ;
19942037case JOIN_FULL :
1995- nrows = outer_rel -> rows * inner_rel -> rows * selec ;
2038+ nrows = outer_rel -> rows * inner_rel -> rows * jselec ;
19962039if (nrows < outer_rel -> rows )
19972040nrows = outer_rel -> rows ;
19982041if (nrows < inner_rel -> rows )
19992042nrows = inner_rel -> rows ;
2043+ nrows *=pselec ;
20002044break ;
20012045case JOIN_IN :
20022046case JOIN_UNIQUE_INNER :
20032047upath = create_unique_path (root ,inner_rel ,
20042048inner_rel -> cheapest_total_path );
2005- nrows = outer_rel -> rows * upath -> rows * selec ;
2049+ nrows = outer_rel -> rows * upath -> rows * jselec ;
20062050if (nrows > outer_rel -> rows )
20072051nrows = outer_rel -> rows ;
20082052break ;
20092053case JOIN_REVERSE_IN :
20102054case JOIN_UNIQUE_OUTER :
20112055upath = create_unique_path (root ,outer_rel ,
20122056outer_rel -> cheapest_total_path );
2013- nrows = upath -> rows * inner_rel -> rows * selec ;
2057+ nrows = upath -> rows * inner_rel -> rows * jselec ;
20142058if (nrows > inner_rel -> rows )
20152059nrows = inner_rel -> rows ;
20162060break ;