summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2013-07-24 04:44:09 +0000
committerTom Lane2013-07-24 04:44:36 +0000
commit9f8254c18cd73404abce53d832723fe104caef14 (patch)
treead880924c74696522d17466e2cdb95477a1efa07
parent980c24e1e80223ccd70e50d9d64c2b38cf50879e (diff)
Fix booltestsel() for case where we have NULL stats but not MCV stats.
In a boolean column that contains mostly nulls, ANALYZE might not find enough non-null values to populate the most-common-values stats, but it would still create a pg_statistic entry with stanullfrac set. The logic in booltestsel() for this situation did the wrong thing for "col IS NOT TRUE" and "col IS NOT FALSE" tests, forgetting that null values would satisfy these tests (so that the true selectivity would be close to one, not close to zero). Per bug #8274. Fix by Andrew Gierth, some comment-smithing by me.
-rw-r--r--src/backend/utils/adt/selfuncs.c22
1 files changed, 10 insertions, 12 deletions
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index de2d7f98b27..a5a9fa69ab6 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -1527,31 +1527,29 @@ booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg,
/*
* No most-common-value info available. Still have null fraction
* information, so use it for IS [NOT] UNKNOWN. Otherwise adjust
- * for null fraction and assume an even split for boolean tests.
+ * for null fraction and assume a 50-50 split of TRUE and FALSE.
*/
switch (booltesttype)
{
case IS_UNKNOWN:
-
- /*
- * Use freq_null directly.
- */
+ /* select only NULL values */
selec = freq_null;
break;
case IS_NOT_UNKNOWN:
-
- /*
- * Select not unknown (not null) values. Calculate from
- * freq_null.
- */
+ /* select non-NULL values */
selec = 1.0 - freq_null;
break;
case IS_TRUE:
- case IS_NOT_TRUE:
case IS_FALSE:
- case IS_NOT_FALSE:
+ /* Assume we select half of the non-NULL values */
selec = (1.0 - freq_null) / 2.0;
break;
+ case IS_NOT_TRUE:
+ case IS_NOT_FALSE:
+ /* Assume we select NULLs plus half of the non-NULLs */
+ /* equiv. to freq_null + (1.0 - freq_null) / 2.0 */
+ selec = (freq_null + 1.0) / 2.0;
+ break;
default:
elog(ERROR, "unrecognized booltesttype: %d",
(int) booltesttype);