| From: | Rui Zhao <zhaorui126(at)gmail(dot)com> |
|---|---|
| To: | PostgreSQL mailing lists <pgsql-bugs(at)lists(dot)postgresql(dot)org> |
| Cc: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> |
| Subject: | GIN jsonb_ops misses root strings in strict jsonpath queries |
| Date: | 2026-10-20 15:43:41 |
| Message-ID: | CAHWVJhHH0k3PxWmS==V1p_PONOMUaSm6LjUV487fwnOqd0jTQw@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
Hi,
A GIN jsonb_ops scan can miss a root string when a jsonpath comparison
uses strict mode. I reproduced this on master at e75fcc9867f.
Using the existing test_jsonb data in jsonb.sql, which includes the
root string "a scalar":
SELECT test_json FROM test_jsonb
WHERE test_json @@ 'strict $ == "a scalar"';
-- "a scalar"
SELECT test_json FROM test_jsonb
WHERE test_json @? 'strict $ ? (@ == "a scalar")';
-- "a scalar"
CREATE INDEX test_jsonb_idx ON test_jsonb USING gin (test_json);
SET enable_seqscan = off;
SELECT test_json FROM test_jsonb
WHERE test_json @@ 'strict $ == "a scalar"';
-- 0 rows
SELECT test_json FROM test_jsonb
WHERE test_json @? 'strict $ ? (@ == "a scalar")';
-- 0 rows
The index stores root strings with JGINFLAG_KEY. Internally, a root
scalar is wrapped in an array. JsonbValueToJsonb() does this inside
its IsAJsonbScalar(val) branch:
scalarArray.type = jbvArray;
scalarArray.val.array.rawScalar = true;
scalarArray.val.array.nElems = 1;
pushJsonbValue(&pstate, WJB_BEGIN_ARRAY, &scalarArray); /* [ */
pushJsonbValue(&pstate, WJB_ELEM, val); /* original value */
pushJsonbValue(&pstate, WJB_END_ARRAY, NULL); /* ] */
gin_extract_jsonb() therefore sees WJB_ELEM and stores the root string
in the GIN index with the JGINFLAG_KEY marker.
But when processing the SQL query, jsonb_ops__extract_nodes() sets
key_entry to GIN_FALSE for the root in strict mode. That searches for
JGINFLAG_STR instead, so it cannot find the matching root string.
The attached patch changes that root case to GIN_TRUE. Both queries
then return "a scalar" using the existing index; no REINDEX is needed.
This bug affects only strict-mode queries using jsonb_ops.
The patch adds the queries above to jsonb.sql. make check passed all
239 tests. Without the code fix, only the two new indexed queries fail.
Regards,
Rui
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0001-Fix-GIN-lookups-for-root-strings-in-strict-jsonpa.patch | application/octet-stream | 3.8 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Fujii Masao | 2026-10-20 16:05:23 | Re: BUG #19644: byteaout, float8out and float4out are marked IMMUTABLE but depend on GUCs |
| Previous Message | Michael Ries | 2026-10-20 15:36:44 | Re: Bug in statement trigger for MERGE operations that move rows between partitions |