| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | 303677365(at)qq(dot)com |
| Subject: | BUG #19825: JSON_VALUE(... RETURNING <domain over json/jsonb>) loses the re-quoting of scalar strings and silent |
| Date: | 2026-11-01 14:40:41 |
| Message-ID: | 19825-809e30f37ee98bf4@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19825
Logged by: chunling qin
Email address: 303677365(at)qq(dot)com
PostgreSQL version: 18.6
Operating system: Linux (TencentOS 4.4, x86_64)
Description:
Hello,
For JSON_VALUE with RETURNING json / jsonb, a scalar *string* result is
re-quoted on output (locked in by the regression suite:
SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING jsonb) -> "aaa").
When the RETURNING type is a domain over json / jsonb -- semantically
equivalent, no constraint -- that re-quoting is lost and the value
silently becomes NULL:
CREATE DOMAIN djb AS jsonb;
CREATE DOMAIN djs AS json;
SELECT JSON_VALUE(jsonb '"x"', '$' RETURNING jsonb); -- "x" (correct)
SELECT JSON_VALUE(jsonb '"x"', '$' RETURNING djb); -- NULL (wrong,
want "x")
SELECT JSON_VALUE(jsonb '"x"', '$' RETURNING json); -- "x" (correct)
SELECT JSON_VALUE(jsonb '"x"', '$' RETURNING djs); -- NULL (wrong,
want "x")
SELECT JSON_VALUE(jsonb '"x"', '$' RETURNING djb ERROR ON ERROR);
-- ERROR: invalid input syntax for type json
-- DETAIL: Token "x" is invalid.
Both coercion routes fail: adding a trivially-true CHECK switches the
domain to the use_json_coercion path (json_populate_type()), which
still returns NULL / the same error, because JSON_VALUE always sets
omit_quotes = true (src/backend/parser/parse_expr.c:4694), so
json_populate_type() unquotes first and then tries to parse "x" as
jsonb.
Controls that isolate the defect to string values over domains:
JSON_VALUE(jsonb '1', '$' RETURNING jsonb) = 1 and RETURNING djb = 1
JSON_QUERY(... RETURNING jsonb) and RETURNING djb both -> "x"
non-scalar inputs fail identically on both sides
Expected: a domain over json / jsonb should behave exactly like its
base type here (the domain carries no constraint); i.e. RETURNING djb
should return "x", as the base-type path and the JSON_QUERY path do.
Actual: the same query with the domain as RETURNING type silently
drops the value (NULL under the default NULL ON ERROR), or fails with
an error that points at JSON parsing. Anyone using domains over
json/jsonb to tighten a schema loses the extracted string values.
Root cause pointer: the special-casing in
ExecEvalJsonExprPath() (src/backend/executor/execExpr.c) tests
"typid == JSONOID || typid == JSONBOID" and does not include domains
over those types (compare getBaseType()).
Reproduced on:
- PostgreSQL 18.6 (REL_18_STABLE, self-built, snapshot 2026-10-26)
- PostgreSQL 20devel (snapshot of 2026-10-29)
Regards,
Chunling Qin
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Fujii Masao | 2026-11-01 15:31:58 | Re: BUG #19774: Incremental backup loses re-extended blocks when WAL summaries are merged out of LSN order |
| Previous Message | Nidal FAKIH | 2026-11-01 09:27:43 | Wrong result: count(DISTINCT x COLLATE "C") with GROUP BY x on a nondeterministic collation |