Re: json/jsonb cleanup + FmgrInfo caching

From: Manu <manuelreyesbravo(at)gmail(dot)com>
To: shihao zhong <zhong950419(at)gmail(dot)com>
Cc: jian he <jian(dot)universality(at)gmail(dot)com>, Robert Haas <robertmhaas(at)gmail(dot)com>, pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: json/jsonb cleanup + FmgrInfo caching
Date: 2026-10-18 04:32:10
Message-ID: 179229793051.2378320.14800418190474533566@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

shihao zhong <zhong950419(at)gmail(dot)com> writes:
> Named composite types still have the problem. ALTER TYPE can add a
> timestamptz after the index is built.

I measured this on 18.6, 19rc1 and master, and it is broader than a mutable
attribute: a pure structural change does it too, with no mutable type and no
GUC. Adding a plain int attribute is enough.

CREATE TYPE c1 AS (x int);
CREATE TABLE t1 (v c1);
INSERT INTO t1 VALUES (row(1));
CREATE INDEX t1_i ON t1 ((json_array(v returning jsonb)));
ALTER TYPE c1 ADD ATTRIBUTE y int;
SELECT count(*) FROM t1
WHERE json_array(v returning jsonb) =
json_array(row(1, null)::c1 returning jsonb);

The index scan returns 0 and a seq scan returns 1; REINDEX restores 1, so the
entries are stale. 18 rejects the CREATE INDEX. RENAME ATTRIBUTE and DROP
ATTRIBUTE do the same, and so does ALTER TABLE ... RENAME COLUMN / ADD COLUMN
on a table's rowtype.

The reason is that the jsonb output carries the attribute names and their
number. The immutability verdict is computed once, at CREATE INDEX, from the
type's definition at that moment, and the catalog does not block a later
ADD / RENAME / DROP ATTRIBUTE (only ALTER ATTRIBUTE ... TYPE is rejected). So
the timestamptz case is one instance of a more general problem, and a recheck
that only looks for a mutable attribute would leave the structural changes
open.

The same expression misbehaves in the other places it can be used, all on
19rc1 and master and all rejected by 18:
- a unique index takes a second row with the same key, and a later REINDEX
fails with "could not create unique index";
- a partial index returns a row that no longer matches its predicate;
- a STORED generated column keeps [{"x": 1}] while a recompute gives
[{"z": 1}];
- a partition key stops pruning to the right partition, and the row ends up
violating its partition constraint.
It also reaches through a nested composite, a domain over a composite and an
array of a composite.

The full matrix, the minimal repro and the per-version output on
18.6 / 19rc1 / master are in the attached evidence.txt.

regards,
Manu

Attachment Content-Type Size
evidence.txt text/plain 7.0 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message shihao zhong 2026-10-18 04:39:13 [PG19] A canceled notify read leaves the NOTIFY queue stuck
Previous Message shihao zhong 2026-10-18 04:22:30 Re: Improving scalability of Parallel Bitmap Heap/Index Scan