Commit b32a25c3 authored by Tom Lane's avatar Tom Lane

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.
parent 10a509d8
...@@ -1529,31 +1529,29 @@ booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, ...@@ -1529,31 +1529,29 @@ booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg,
/* /*
* No most-common-value info available. Still have null fraction * No most-common-value info available. Still have null fraction
* information, so use it for IS [NOT] UNKNOWN. Otherwise adjust * 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) switch (booltesttype)
{ {
case IS_UNKNOWN: case IS_UNKNOWN:
/* select only NULL values */
/*
* Use freq_null directly.
*/
selec = freq_null; selec = freq_null;
break; break;
case IS_NOT_UNKNOWN: case IS_NOT_UNKNOWN:
/* select non-NULL values */
/*
* Select not unknown (not null) values. Calculate from
* freq_null.
*/
selec = 1.0 - freq_null; selec = 1.0 - freq_null;
break; break;
case IS_TRUE: case IS_TRUE:
case IS_NOT_TRUE:
case IS_FALSE: case IS_FALSE:
case IS_NOT_FALSE: /* Assume we select half of the non-NULL values */
selec = (1.0 - freq_null) / 2.0; selec = (1.0 - freq_null) / 2.0;
break; 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: default:
elog(ERROR, "unrecognized booltesttype: %d", elog(ERROR, "unrecognized booltesttype: %d",
(int) booltesttype); (int) booltesttype);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment