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).
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index e358b5a..9250646 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -3728,6 +3728,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, rsi->setResult = state->tuple_store; rsi->setDesc = cache->c.io.composite.tupdesc; + rsi->setDesc->tdrefcount = 1; PG_RETURN_NULL(); }