GIN disagrees with seq scan when NOT and AND operators are combined

Started by Chinmay Kanchi13 days ago2 messagesbugs
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

This thread has been committed, so CI has stopped here. Anything below is the last result it produced.

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t254129
psql -h localhost -U postgres

Built from patchset v2 (message #2), October 12, 2026 at 08:57 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t254129_2 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t254129_2 && git checkout t254129_2

Patchset v2 (message #2) is on t254129_2

Jump to latest
#1Chinmay Kanchi
cgkanchi@gmail.com

Hi all,

When working on pg_lion (https://github.com/cgkanchi/pg_lion), I stumbled
upon a bug where GIN returns fewer rows when multiple ! operators are
specified. I was able to repro this on all versions from 16 to trunk.

Repro:
```
postgres=# CREATE TABLE t (j jsonb);
INSERT INTO t VALUES ('{"a": 1, "b": 10}'), ('{"a": 2, "b": 10}'), ('{"a":
2, "b": 20}');
CREATE TABLE
INSERT 0 3
postgres=# SELECT j FROM t WHERE j @@ '!(!($.a == 1) && $.b == 20)';
j
-------------------
{"a": 1, "b": 10}
{"a": 2, "b": 10}
(2 rows)

postgres=# create index on t using gin(j);
CREATE INDEX
postgres=# SELECT j FROM t WHERE j @@ '!(!($.a == 1) && $.b == 20)';
j
-------------------
{"a": 1, "b": 10}
(1 row)
```

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Chinmay Kanchi (#1)
Re: GIN disagrees with seq scan when NOT and AND operators are combined

Chinmay Kanchi <cgkanchi@gmail.com> writes:

When working on pg_lion (https://github.com/cgkanchi/pg_lion), I stumbled
upon a bug where GIN returns fewer rows when multiple ! operators are
specified. I was able to repro this on all versions from 16 to trunk.

Thanks for the report. (For the archives' sake, note this repro
requires "set enable_seqscan = 0", else you get a seqscan plan
and no bug.)

I'm not too familiar with this code, but it looks like
extract_jsp_bool_expr concludes that !($.b == 20) is not supported
as a GIN scan condition, and then the next recursion level up does
the wrong thing with the negated && condition. The attached quick
hack seems to fix it. I didn't look around for other instances
of the same thinko, but there might be some.

regards, tom lane

Attachments:

t254129_2
wip-fix-jsonb-gin-not-semantics.patchtext/x-diff; charset=us-ascii; name=wip-fix-jsonb-gin-not-semantics.patchDownload+8-2