Hi Jian, Manu, v3 with Manu's diff fixes my case, and all tests pass.
float8out is STABLE on master now, but v3 still lists FLOAT4OID and FLOAT8OID as immutable. So this is accepted: CREATE INDEX ON tf ((json_array(f returning jsonb))); -- f float8 and gives wrong results after SET extra_float_digits = 0. Dropping those two case labels fixes it on master and changes nothing on 19. Thanks, Shihao On Thu, Oct 22, 2026 at 11:51 AM Manu <[email protected]> wrote: > Hi Jian, > > On Thu, Oct 22, 2026 at 9:12 PM jian he > <[email protected]> wrote: > > The attached patch should resolve these issues. > > It does. v3 applies cleanly to master and REL_19_STABLE, and make > check passes. Every case from my earlier matrix is now rejected at > CREATE INDEX, as in 18: ADD / RENAME / DROP ATTRIBUTE, the table > rowtype, nested composites, domains over composites, arrays of > composites, JSON_OBJECT, RETURNING json, and the unique, partial, > generated column and partition key forms. Anonymous ROW(), record[] > and JSON_SCALAR are rejected too. > > One case still gets through, in the range branch. A range is printed > by range_out, which calls the subtype's output function and never a > cast to json. But when the range has no cast of its own, > json_check_mutability() recurses into the subtype and judges the > subtype's cast to json instead. So an immutable cast on an enum makes > a range over that enum look immutable, while what actually prints it > is enum_out: > > CREATE TYPE e AS ENUM ('a', 'b'); > CREATE FUNCTION e_json(e) RETURNS json IMMUTABLE LANGUAGE sql > AS $$ SELECT '"x"'::json $$; > CREATE CAST (e AS json) WITH FUNCTION e_json(e); > CREATE TYPE er AS RANGE (subtype = e); > CREATE TABLE t (v er); > INSERT INTO t VALUES (er('a', 'b')); > CREATE INDEX t_i ON t ((json_array(v returning jsonb))); > ALTER TYPE e RENAME VALUE 'a' TO 'z'; > SELECT count(*) FROM t > WHERE json_array(v returning jsonb) = > json_array(er('z', 'b') returning jsonb); > > The index scan returns 0 and a seq scan returns 1; REINDEX restores 1. > Without the cast on the enum the CREATE INDEX is rejected, and 18 > rejects it either way. The multirange behaves the same. Master has > this without v3 as well. > > The attached diff, on top of v3, stops looking up casts once the > recursion is below a range or multirange. With it both cases are > rejected, nothing else in my matrix changes (int4range is still > accepted), and make check passes. It's named .txt so it doesn't > disturb the CF bot; feel free to fold it into v4 if you agree. > > regards, > Manu >
