BUG #18583: jsonb_populate_record return values cannot be queried correctly in subselects

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: robert(dot)j(dot)greig(at)gmail(dot)com
Subject: BUG #18583: jsonb_populate_record return values cannot be queried correctly in subselects
Date: 2024-08-14 14:53:42
Message-ID: 18583-b8f0198539f29ccb@postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 18583
Logged by: Robert Greig
Email address: robert(dot)j(dot)greig(at)gmail(dot)com
PostgreSQL version: 16.4
Operating system: Windows
Description:

I have created a small example that illustrates this issue, but before
describing that let me provide a little more context which would not be
obvious from the example. The real use case here is that we have a number of
tables containing some columns with type jsonb. There are views that select
from those tables and use jsonb_populate_record to populate custom types
from the JSON. For example:

CREATE TABLE t1 AS (id varchar(20), some_data jsonb);
CREATE VIEW v1 AS SELECT id, jsonb_populate(null::some_type, somedata) AS
data FROM t1;

However this was not working in some circumstances where rows that contained
non-null values in the data column of the view were not being returned by a
query of the form SELECT * FROM v1 WHERE data IS NOT NULL. However just
running the SELECT statement without any WHERE clause you could see the data
was being returned.

Further testing showed that this was happening with any subselect not just
views, and that the issue was occurring when there were any null or missing
elements in the JSON. The type was still constructed as expected but for
some reason the query on it was failing.

I am sure this is as clear as mud so I have put together a very simple test
case that illustrates the issue.

create type test_simple_type as (
f1 varchar(20),
f2 int
);

select
*
from (
values
(10, (jsonb_populate_record(null::test_simple_type, '{"f1": "banana",
"f2": 44}')::test_simple_type)),
(11, (jsonb_populate_record(null::test_simple_type, '{"f1": "pear", "f2":
null}')::test_simple_type)),
(12, (jsonb_populate_record(null::test_simple_type, '{"f1":
"strawberry"}')::test_simple_type)),
(13, null)
) x(key, val);

select
*
from (
values
(10, (jsonb_populate_record(null::test_simple_type, '{"f1": "banana",
"f2": 44}')::test_simple_type)),
(11, (jsonb_populate_record(null::test_simple_type, '{"f1": "pear", "f2":
null}')::test_simple_type)),
(12, (jsonb_populate_record(null::test_simple_type, '{"f1":
"strawberry"}')::test_simple_type)),
(13, null)
) x(key, val)
where val is not null;

If you run the first query above, you can see that the val column is
correctly populated for the rows with key 10, 11 and 12. However if you run
the second query only one row is returned whereas the expected output is
three rows (with keys 10, 11 and 12).

It is not obvious to me why it is not working but I believe this is a defect
and I can't find a workaround.

Thanks,
Robert

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Tomas Vondra 2024-08-14 17:54:32 Re: Certain options in pg_upgrade don't seem to work.
Previous Message Dmytro Astapov 2024-08-14 14:09:17 Using current_user as an argument of pl/pgsql function affects collation of other arguments