Re: BUG #19644: byteaout, float8out and float4out are marked IMMUTABLE but depend on GUCs

From: Staroverov Ilja <i(dot)staroverov(at)ftdata(dot)ru>
To: Fujii Masao <masao(dot)fujii(at)gmail(dot)com>, Peter Eisentraut <peter(at)eisentraut(dot)org>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, "jj-zhang25(at)mails(dot)tsinghua(dot)edu(dot)cn" <jj-zhang25(at)mails(dot)tsinghua(dot)edu(dot)cn>, "pgsql-bugs(at)lists(dot)postgresql(dot)org" <pgsql-bugs(at)lists(dot)postgresql(dot)org>
Subject: Re: BUG #19644: byteaout, float8out and float4out are marked IMMUTABLE but depend on GUCs
Date: 2026-10-20 13:20:41
Message-ID: C79ADC9A-5DFE-4B5C-8C78-012802D31531@localhost.localdomain
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Hi,

hstore has the same problem. hstore(record) calls the output functions
of the record's column types, and populate_record(), which the #=
operator also uses, calls their input functions. But both are marked
IMMUTABLE, unlike the core functions that do the same, such as
row_to_json() and jsonb_populate_record(), which are STABLE. So they
are accepted in expression indexes and generated columns, although
their results depend on TimeZone, DateStyle, extra_float_digits and so
on. On master, as of e75fcc986:

CREATE EXTENSION hstore;
SET TimeZone = 'UTC';
CREATE TABLE ev (ts timestamptz);
CREATE INDEX ON ev ((hstore(ROW(ts)) -> 'f1'));
INSERT INTO ev VALUES ('2026-01-01 00:00+00');
SET TimeZone = 'Europe/Moscow';
SELECT count(*) FROM ev
WHERE hstore(ROW(ts)) -> 'f1' = '2026-01-01 03:00:00+03';
count
-------
0

The plan uses the index; with enable_indexscan and enable_bitmapscan
off, the same query returns 1. Likewise, a stored generated column
defined as (populate_record(NULL::rt, h)).ts, where rt is a composite
type with a timestamptz field, gets different values for the same h,
depending on the TimeZone at insert time.

It also leaves a way around e75fcc986: with x float8, ((x / 3)::text)
is now rejected in an index expression, but (hstore(ROW(x / 3)) -> 'f1')
is still accepted.

Both functions have been IMMUTABLE since they were added in 9.0. The
attached patch marks them STABLE, along the lines of the cube patch
upthread, bumps the hstore version to 1.9, and adds a test that such
indexes are rejected. Like the other changes here, I'd think this is
for master only.

I also checked core and the other contrib modules for IMMUTABLE
functions that call the I/O functions of arbitrary types, and found no
others.

--
Ilya Staroverov

Attachment Content-Type Size
v1-0001-hstore-Mark-hstore-record-and-populate_record-as-.patch application/octet-stream 5.0 KB

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Michael Ries 2026-10-20 15:36:44 Re: Bug in statement trigger for MERGE operations that move rows between partitions
Previous Message Hayato Kuroda (Fujitsu) 2026-10-20 11:29:38 RE: START_REPLICATION silently truncates an overlong LSN component