Hi,
I've found out that currently in some situations jsonb_to_recordset can lead to
a crash. Minimal example that I've managed to create looks like this:
CREATE OR REPLACE FUNCTION test(data JSONB)
RETURNS INTEGER AS $$
DECLARE
test_var int;
BEGIN
WITH jsonb_values AS (
SELECT
(SELECT SUM(value)
FROM jsonb_to_recordset(element #> '{values}')
AS q(value INTEGER)) AS value_sum
FROM jsonb_array_elements(data) AS element
) SELECT SUM(value_sum) FROM jsonb_values INTO test_var;
RETURN test_var;
END;
$$ LANGUAGE plpgsql;
And then:
=# SELECT test('[
{
"values": [
{
"value": 1
},
{
"value": 3
}
]
},
{
"values": [
{
"value": 1
},
{
"value": 3
}
]
}
]' :: JSONB);
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
After brief investigation it looks like an issue with tupdesc from the function
cache:
if (!cache)
{
fcinfo->flinfo->fn_extra = cache =
MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*cache));
//...
rsi->setDesc = cache->c.io.composite.tupdesc;
Then after the first call of populate_recordset_worker rsi->setDesc is being
reset since we never increased tdrefcount and the next call will use wrong
cache data. Apparently, it can be fixed by incrementing a tdrefcount (see the
attached patch).