Skip to content

Commit 3f1356e

Browse files
committed
Fix handling of NULLs when merging BRIN summaries
When merging BRIN summaries, union_tuples() did not correctly update the target hasnulls/allnulls flags. When merging all-NULL summary into a summary without any NULL values, the result had both flags set to false (instead of having hasnulls=true). This happened because the code only considered the hasnulls flags, ignoring the possibility the source summary has allnulls=true. Discovered while investigating issues with handling empty BRIN ranges and handling of NULL values, but it's a separate problem (has nothing to do with empty ranges). Fixed by considering both flags on the source summary, and updating the hasnulls flag on the target summary. Backpatch to 11. The bug exists since 9.5 (where BRIN indexes were introduced), but those releases are EOL already. Discussion: https://postgr.es/m/9d993d0d-e431-2196-9ccc-0554d0e60154%40enterprisedb.com
1 parent ccd3623 commit 3f1356e

File tree

1 file changed

+9
-1
lines changed

1 file changed

+9
-1
lines changed

src/backend/access/brin/brin.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1623,8 +1623,11 @@ union_tuples(BrinDesc *bdesc, BrinMemTuple *a, BrinTuple *b)
16231623

16241624
if (opcinfo->oi_regular_nulls)
16251625
{
1626+
/* Does the "b" summary represent any NULL values? */
1627+
bool b_has_nulls = (col_b->bv_hasnulls || col_b->bv_allnulls);
1628+
16261629
/* Adjust "hasnulls". */
1627-
if (!col_a->bv_hasnulls && col_b->bv_hasnulls)
1630+
if (!col_a->bv_allnulls && b_has_nulls)
16281631
col_a->bv_hasnulls = true;
16291632

16301633
/* If there are no values in B, there's nothing left to do. */
@@ -1636,12 +1639,17 @@ union_tuples(BrinDesc *bdesc, BrinMemTuple *a, BrinTuple *b)
16361639
* values from B into A, and we're done. We cannot run the
16371640
* operators in this case, because values in A might contain
16381641
* garbage. Note we already established that B contains values.
1642+
*
1643+
* Also adjust "hasnulls" in order not to forget the summary
1644+
* represents NULL values. This is not redundant with the earlier
1645+
* update, because that only happens when allnulls=false.
16391646
*/
16401647
if (col_a->bv_allnulls)
16411648
{
16421649
int i;
16431650

16441651
col_a->bv_allnulls = false;
1652+
col_a->bv_hasnulls = true;
16451653

16461654
for (i = 0; i < opcinfo->oi_nstored; i++)
16471655
col_a->bv_values[i] =

0 commit comments

Comments
 (0)