diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index 4b48ae1e260..f5ee929c56e 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.86 2007/06/11 01:16:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.87 2007/08/31 23:35:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -219,7 +219,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 @@ -702,7 +704,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 60da08b1ec4..ad9f662b68d 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.235 2007/08/21 01:11:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.236 2007/08/31 23:35:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1385,11 +1385,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 f0c6f20427c..fc409d9bddd 100644 --- a/src/include/utils/selfuncs.h +++ b/src/include/utils/selfuncs.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.39 2007/01/22 20:00:40 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.40 2007/08/31 23:35:22 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,