diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index f51bac9b0e8..463408f26fd 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.82 2006/10/04 00:29:53 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.82.2.1 2007/08/31 23:35:29 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -218,7 +218,9 @@ clauselist_selectivity(PlannerInfo *root, s2 = rqlist->hibound + rqlist->lobound - 1.0; /* Adjust for double-exclusion of NULLs */ - s2 += nulltestsel(root, IS_NULL, rqlist->var, varRelid); + /* HACK: disable nulltestsel's special outer-join logic */ + s2 += nulltestsel(root, IS_NULL, rqlist->var, + varRelid, JOIN_INNER); /* * A zero or slightly negative s2 should be converted into a @@ -701,7 +703,8 @@ clause_selectivity(PlannerInfo *root, s1 = nulltestsel(root, ((NullTest *) clause)->nulltesttype, (Node *) ((NullTest *) clause)->arg, - varRelid); + varRelid, + jointype); } else if (IsA(clause, BooleanTest)) { diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 0fcfdcbf322..56248a93b6a 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.214.2.5 2007/05/05 17:05:55 mha Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.214.2.6 2007/08/31 23:35:29 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1386,11 +1386,24 @@ booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, */ Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, - Node *arg, int varRelid) + Node *arg, int varRelid, JoinType jointype) { VariableStatData vardata; double selec; + /* + * Special hack: an IS NULL test being applied at an outer join should not + * be taken at face value, since it's very likely being used to select the + * outer-side rows that don't have a match, and thus its selectivity has + * nothing whatever to do with the statistics of the original table + * column. We do not have nearly enough context here to determine its + * true selectivity, so for the moment punt and guess at 0.5. Eventually + * the planner should be made to provide enough info about the clause's + * context to let us do better. + */ + if (IS_OUTER_JOIN(jointype) && nulltesttype == IS_NULL) + return (Selectivity) 0.5; + examine_variable(root, arg, varRelid, &vardata); if (HeapTupleIsValid(vardata.statsTuple)) diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h index 69a22b37b56..7976e67b2ee 100644 --- a/src/include/utils/selfuncs.h +++ b/src/include/utils/selfuncs.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.36 2006/10/04 00:30:11 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.36.2.1 2007/08/31 23:35:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -149,7 +149,7 @@ extern Datum icnlikejoinsel(PG_FUNCTION_ARGS); extern Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype); extern Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, - Node *arg, int varRelid); + Node *arg, int varRelid, JoinType jointype); extern Selectivity scalararraysel(PlannerInfo *root, ScalarArrayOpExpr *clause, bool is_join_clause,