@@ -141,9 +141,11 @@ static double ineq_histogram_selectivity(PlannerInfo *root,
141141FmgrInfo * opproc ,bool isgt ,
142142Datum constval ,Oid consttype );
143143static double eqjoinsel_inner (Oid operator ,
144- VariableStatData * vardata1 ,VariableStatData * vardata2 );
144+ VariableStatData * vardata1 ,VariableStatData * vardata2 ,
145+ RelOptInfo * rel1 ,RelOptInfo * rel2 );
145146static double eqjoinsel_semi (Oid operator ,
146- VariableStatData * vardata1 ,VariableStatData * vardata2 );
147+ VariableStatData * vardata1 ,VariableStatData * vardata2 ,
148+ RelOptInfo * rel1 ,RelOptInfo * rel2 );
147149static bool convert_to_scalar (Datum value ,Oid valuetypid ,double * scaledvalue ,
148150Datum lobound ,Datum hibound ,Oid boundstypid ,
149151double * scaledlobound ,double * scaledhibound );
@@ -172,6 +174,7 @@ static bool get_actual_variable_range(PlannerInfo *root,
172174VariableStatData * vardata ,
173175Oid sortop ,
174176Datum * min ,Datum * max );
177+ static RelOptInfo * find_join_input_rel (PlannerInfo * root ,Relids relids );
175178static Selectivity prefix_selectivity (PlannerInfo * root ,
176179VariableStatData * vardata ,
177180Oid vartype ,Oid opfamily ,Const * prefixcon );
@@ -2007,24 +2010,47 @@ eqjoinsel(PG_FUNCTION_ARGS)
20072010VariableStatData vardata1 ;
20082011VariableStatData vardata2 ;
20092012bool join_is_reversed ;
2013+ RelOptInfo * rel1 ;
2014+ RelOptInfo * rel2 ;
20102015
20112016get_join_variables (root ,args ,sjinfo ,
20122017& vardata1 ,& vardata2 ,& join_is_reversed );
20132018
2019+ /*
2020+ * Identify the join's direct input relations. We use the min lefthand
2021+ * and min righthand as the inputs, even though the join might actually
2022+ * get done with larger input relations. The min inputs are guaranteed to
2023+ * have been formed by now, though, and always using them ensures
2024+ * consistency of estimates.
2025+ */
2026+ if (!join_is_reversed )
2027+ {
2028+ rel1 = find_join_input_rel (root ,sjinfo -> min_lefthand );
2029+ rel2 = find_join_input_rel (root ,sjinfo -> min_righthand );
2030+ }
2031+ else
2032+ {
2033+ rel1 = find_join_input_rel (root ,sjinfo -> min_righthand );
2034+ rel2 = find_join_input_rel (root ,sjinfo -> min_lefthand );
2035+ }
2036+
20142037switch (sjinfo -> jointype )
20152038{
20162039case JOIN_INNER :
20172040case JOIN_LEFT :
20182041case JOIN_FULL :
2019- selec = eqjoinsel_inner (operator ,& vardata1 ,& vardata2 );
2042+ selec = eqjoinsel_inner (operator ,& vardata1 ,& vardata2 ,
2043+ rel1 ,rel2 );
20202044break ;
20212045case JOIN_SEMI :
20222046case JOIN_ANTI :
20232047if (!join_is_reversed )
2024- selec = eqjoinsel_semi (operator ,& vardata1 ,& vardata2 );
2048+ selec = eqjoinsel_semi (operator ,& vardata1 ,& vardata2 ,
2049+ rel1 ,rel2 );
20252050else
20262051selec = eqjoinsel_semi (get_commutator (operator ),
2027- & vardata2 ,& vardata1 );
2052+ & vardata2 ,& vardata1 ,
2053+ rel2 ,rel1 );
20282054break ;
20292055default :
20302056/* other values not expected here */
@@ -2050,7 +2076,8 @@ eqjoinsel(PG_FUNCTION_ARGS)
20502076 */
20512077static double
20522078eqjoinsel_inner (Oid operator ,
2053- VariableStatData * vardata1 ,VariableStatData * vardata2 )
2079+ VariableStatData * vardata1 ,VariableStatData * vardata2 ,
2080+ RelOptInfo * rel1 ,RelOptInfo * rel2 )
20542081{
20552082double selec ;
20562083double nd1 ;
@@ -2251,15 +2278,19 @@ eqjoinsel_inner(Oid operator,
22512278 * be, providing a crude correction for the selectivity of restriction
22522279 * clauses on those relations.(We don't do that in the other path
22532280 * since there we are comparing the nd values to stats for the whole
2254- * relations.)
2281+ * relations.) We can apply this clamp both with respect to the base
2282+ * relations from which the join variables come, and to the immediate
2283+ * input relations of the current join.
22552284 */
22562285double nullfrac1 = stats1 ?stats1 -> stanullfrac :0.0 ;
22572286double nullfrac2 = stats2 ?stats2 -> stanullfrac :0.0 ;
22582287
22592288if (vardata1 -> rel )
22602289nd1 = Min (nd1 ,vardata1 -> rel -> rows );
2290+ nd1 = Min (nd1 ,rel1 -> rows );
22612291if (vardata2 -> rel )
22622292nd2 = Min (nd2 ,vardata2 -> rel -> rows );
2293+ nd2 = Min (nd2 ,rel2 -> rows );
22632294
22642295selec = (1.0 - nullfrac1 )* (1.0 - nullfrac2 );
22652296if (nd1 > nd2 )
@@ -2286,7 +2317,8 @@ eqjoinsel_inner(Oid operator,
22862317 */
22872318static double
22882319eqjoinsel_semi (Oid operator ,
2289- VariableStatData * vardata1 ,VariableStatData * vardata2 )
2320+ VariableStatData * vardata1 ,VariableStatData * vardata2 ,
2321+ RelOptInfo * rel1 ,RelOptInfo * rel2 )
22902322{
22912323double selec ;
22922324double nd1 ;
@@ -2434,8 +2466,10 @@ eqjoinsel_semi(Oid operator,
24342466{
24352467if (vardata1 -> rel )
24362468nd1 = Min (nd1 ,vardata1 -> rel -> rows );
2469+ nd1 = Min (nd1 ,rel1 -> rows );
24372470if (vardata2 -> rel )
24382471nd2 = Min (nd2 ,vardata2 -> rel -> rows );
2472+ nd2 = Min (nd2 ,rel2 -> rows );
24392473
24402474if (nd1 <=nd2 || nd2 <=0 )
24412475selec = 1.0 - nullfrac1 ;
@@ -4758,6 +4792,37 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata,
47584792return have_data ;
47594793}
47604794
4795+ /*
4796+ * find_join_input_rel
4797+ *Look up the input relation for a join.
4798+ *
4799+ * We assume that the input relation's RelOptInfo must have been constructed
4800+ * already.
4801+ */
4802+ static RelOptInfo *
4803+ find_join_input_rel (PlannerInfo * root ,Relids relids )
4804+ {
4805+ RelOptInfo * rel = NULL ;
4806+
4807+ switch (bms_membership (relids ))
4808+ {
4809+ case BMS_EMPTY_SET :
4810+ /* should not happen */
4811+ break ;
4812+ case BMS_SINGLETON :
4813+ rel = find_base_rel (root ,bms_singleton_member (relids ));
4814+ break ;
4815+ case BMS_MULTIPLE :
4816+ rel = find_join_rel (root ,relids );
4817+ break ;
4818+ }
4819+
4820+ if (rel == NULL )
4821+ elog (ERROR ,"could not find RelOptInfo for given relids" );
4822+
4823+ return rel ;
4824+ }
4825+
47614826
47624827/*-------------------------------------------------------------------------
47634828 *