Re: [***DKIM violation***] Re: [PATCH] Fix JSON_SERIALIZE() coercion placeholder type for jsonb input

From: Nikhil Sontakke <nikkhils(at)gmail(dot)com>
To: Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com>
Cc: Staroverov Ilja <i(dot)staroverov(at)ftdata(dot)ru>, pgsql-hackers(at)lists(dot)postgresql(dot)org, Matt Blewitt <mble(at)planetscale(dot)com>, solai(dot)cdac(at)gmail(dot)com
Subject: Re: [***DKIM violation***] Re: [PATCH] Fix JSON_SERIALIZE() coercion placeholder type for jsonb input
Date: 2026-11-06 19:08:38
Message-ID: CANgU5Zd9gyWNF7ktM4DUATD0gr3EX5itw0kG694ty+q2Ln24Kg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

On Thu, 15 Oct 2026, Staroverov Ilja <i(dot)staroverov(at)ftdata(dot)ru> wrote:
> Given that, I think the fix should be back-patched to 17,

On Tue, 27 Oct 2026, Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com> wrote:
> Since this can affect both indexes and stored generated columns, I
> think the commit message should mention that this can 1. possibly
> require a reindex 2. doesn't fix existing stored generated columns
> affected by this issue.

I had asked (with a question mark) about the need to backpatch. Ilya's example
shows that the wrong output gets stored and then breaks restore, so it indeed
makes sense to back-patch to 17.

I checked and v3 applies cleanly to REL_17_STABLE, REL_18_STABLE, REL_19_STABLE
and master, with no conflicts and an identical diff on every branch. With
assertions enabled, make check passes on all four.

I also tested what happens to objects created before the fix, using an
index, a stored generated column and a view, each on
json_serialize(jsonb_col). Since the fix is in the parser, the outcome
depends on how the cluster reaches a fixed release.

1. Minor update (data directory from stock 17.11 / 18.6 started under
the patched 17 / 18 binaries):

Only re-parsing fixes them: DROP/CREATE INDEX, CREATE OR REPLACE VIEW,
and ALTER TABLE ... ALTER COLUMN ... SET EXPRESSION, which also
recomputes the stored values.

2. pg_upgrade from an affected release into a fixed one (17.11 -> 18,
18.6 -> 19, 18.6 -> master, 19beta3 -> master; the
target was patched each time, with identical results):

The expressions are re-parsed during the upgrade, so all three trees
come out correct and the view gives the right output immediately.
However, the index files are copied, so the index now holds the old
wrong values under a correct expression, and the planner uses it.
Stored generated column values also stay wrong (including
Ilya's invalid-UTF-8 0xc8 row, which pg_upgrade copies without
complaint).

So REINDEX alone is not enough after a minor update, and after
pg_upgrade it is required, since the index silently misses rows.

Attached is v4, which is v3 with only the commit message changed: it
adds the following back-patch note. The code is identical to v3, and
the same patch applies with git am to REL_17_STABLE, REL_18_STABLE,
REL_19_STABLE and master.

Back-patch to v17, where JSON_SERIALIZE() was introduced. The fix
applies at parse time, so views, index expressions and stored
generated columns that use JSON_SERIALIZE() on a jsonb argument and
were created before this fix keep the incorrect coercion; REINDEX
does not repair them. Recreate such views and indexes, and
re-specify such generated columns with ALTER TABLE ... ALTER COLUMN
... SET EXPRESSION. Clusters upgraded with pg_upgrade from an
affected release get corrected expressions, but affected indexes
must be reindexed, since until then they can return wrong results,
and stored generated column values must be recomputed.

The release notes will probably need the same text.

Regards,
Nikhil

Attachment Content-Type Size
v4-0001-Fix-JSON_SERIALIZE-coercion-placeholder-type-for-.patch application/octet-stream 5.2 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message surya poondla 2026-11-06 19:43:30 Re: Reject access to unlogged tables in contrib modules
Previous Message Jim Jones 2026-11-06 18:59:14 Re: Reject access to unlogged tables in contrib modules