Skip to content

Commit 9f8254c

Browse files
committed
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.
1 parent 980c24e commit 9f8254c

File tree

1 file changed

+10
-12
lines changed

1 file changed

+10
-12
lines changed

src/backend/utils/adt/selfuncs.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,31 +1527,29 @@ booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg,
15271527
/*
15281528
* No most-common-value info available. Still have null fraction
15291529
* information, so use it for IS [NOT] UNKNOWN. Otherwise adjust
1530-
* for null fraction and assume an even split for boolean tests.
1530+
* for null fraction and assume a 50-50 split of TRUE and FALSE.
15311531
*/
15321532
switch (booltesttype)
15331533
{
15341534
case IS_UNKNOWN:
1535-
1536-
/*
1537-
* Use freq_null directly.
1538-
*/
1535+
/* select only NULL values */
15391536
selec = freq_null;
15401537
break;
15411538
case IS_NOT_UNKNOWN:
1542-
1543-
/*
1544-
* Select not unknown (not null) values. Calculate from
1545-
* freq_null.
1546-
*/
1539+
/* select non-NULL values */
15471540
selec = 1.0 - freq_null;
15481541
break;
15491542
case IS_TRUE:
1550-
case IS_NOT_TRUE:
15511543
case IS_FALSE:
1552-
case IS_NOT_FALSE:
1544+
/* Assume we select half of the non-NULL values */
15531545
selec = (1.0 - freq_null) / 2.0;
15541546
break;
1547+
case IS_NOT_TRUE:
1548+
case IS_NOT_FALSE:
1549+
/* Assume we select NULLs plus half of the non-NULLs */
1550+
/* equiv. to freq_null + (1.0 - freq_null) / 2.0 */
1551+
selec = (freq_null + 1.0) / 2.0;
1552+
break;
15551553
default:
15561554
elog(ERROR, "unrecognized booltesttype: %d",
15571555
(int) booltesttype);

0 commit comments

Comments
 (0)