Re: BUG #18855: Using BRIN index with int8_bloom_ops produces incorrect results

Tomas Vondra <tomas@vondra.me>

From: Tomas Vondra <tomas@vondra.me>
To: arseniy.mukhin.dev@gmail.com, pgsql-bugs@lists.postgresql.org, PG Bug reporting form <noreply@postgresql.org>
Date: 2025-03-19T13:43:34Z
Lists: pgsql-bugs
On 3/18/25 21:39, PG Bug reporting form wrote:
> The following bug has been logged on the website:
> 
> Bug reference:      18855
> Logged by:          Arseniy Mukhin
> Email address:      arseniy.mukhin.dev@gmail.com
> PostgreSQL version: 17.4
> Operating system:   Ubuntu 24.04.2 LTS
> Description:        
> 
> PostgreSQL 17.4 (Debian 17.4-1.pgdg120+2) on x86_64-pc-linux-gnu, compiled
> by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
> 
> In this example, the query using the index returns 0 rows, but the query
> using seqscan returns 1 row.
> 
> How to reproduce:
> 
> -- dataset
> drop table if exists t1;
> create table if not exists t1 (a bigint);
> insert into t1 (a) select x from generate_series(1,300000) as x;
> create index t1_a_brin_idx on t1 using brin (a int8_bloom_ops);
> analyse;
> 

Thanks for the report, I can reproduce it too - but I had to add ANALYZE
before the CREATE INDEX, so that it triggers a parallel BRIN build.

The bug is pretty trivial - the brin_bloom_union() does this with the
summaries it's expected to merge:

  filter_a = (BloomFilter *) PG_DETOAST_DATUM(col_a->bv_values[0]);
  filter_b = (BloomFilter *) PG_DETOAST_DATUM(col_b->bv_values[0]);

and then it merges "b" into "a". But it never updates col_a to point to
the merged summary. The fix is to do something like this:

    if (PointerGetDatum(filter_a) != col_a->bv_values[0])
    {
        pfree(DatumGetPointer(col_a->bv_values[0]));
        col_a->bv_values[0] = PointerGetDatum(filter_a);
    }

I'll get this fixed shortly. Unfortunately, this means the "bloom"
filters may be broken - not just those built in parallel, the union
method can be triggered due to concurrent activity too.


regards

-- 
Tomas Vondra




Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Keep the decompressed filter in brin_bloom_union