diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 06f8d281685..5c3f2fb9f6f 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -3658,6 +3658,12 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, if (PG_ARGISNULL(json_arg_num)) PG_RETURN_NULL(); + /* + * Forcibly update the cached tupdesc, to ensure we have the right tupdesc + * to return even if the JSON contains no rows. + */ + update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt); + state = palloc0(sizeof(PopulateRecordsetState)); /* make tuplestore in a sufficiently long-lived memory context */ diff --git a/src/test/regress/expected/json.out b/src/test/regress/expected/json.out index 6020feeea41..ea1be61effc 100644 --- a/src/test/regress/expected/json.out +++ b/src/test/regress/expected/json.out @@ -1851,6 +1851,19 @@ FROM (VALUES (1),(2)) v(i); 2 | (2,43) (4 rows) +-- empty array is a corner case +SELECT json_populate_recordset(null::record, '[]'); +ERROR: record type has not been registered +SELECT json_populate_recordset(row(1,2), '[]'); + json_populate_recordset +------------------------- +(0 rows) + +SELECT * FROM json_populate_recordset(NULL::jpop,'[]') q; + a | b | c +---+---+--- +(0 rows) + -- composite domain SELECT json_populate_recordset(null::j_ordered_pair, '[{"x": 0, "y": 1}]'); json_populate_recordset diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index f045e085384..4fddd2de140 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -2533,6 +2533,19 @@ FROM (VALUES (1),(2)) v(i); 2 | (2,43) (4 rows) +-- empty array is a corner case +SELECT jsonb_populate_recordset(null::record, '[]'); +ERROR: record type has not been registered +SELECT jsonb_populate_recordset(row(1,2), '[]'); + jsonb_populate_recordset +-------------------------- +(0 rows) + +SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[]') q; + a | b | c +---+---+--- +(0 rows) + -- composite domain SELECT jsonb_populate_recordset(null::jb_ordered_pair, '[{"x": 0, "y": 1}]'); jsonb_populate_recordset diff --git a/src/test/regress/sql/json.sql b/src/test/regress/sql/json.sql index 97c75420e9c..d1e40084277 100644 --- a/src/test/regress/sql/json.sql +++ b/src/test/regress/sql/json.sql @@ -550,6 +550,11 @@ SELECT json_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]'); SELECT i, json_populate_recordset(row(i,50), '[{"f1":"42"},{"f2":"43"}]') FROM (VALUES (1),(2)) v(i); +-- empty array is a corner case +SELECT json_populate_recordset(null::record, '[]'); +SELECT json_populate_recordset(row(1,2), '[]'); +SELECT * FROM json_populate_recordset(NULL::jpop,'[]') q; + -- composite domain SELECT json_populate_recordset(null::j_ordered_pair, '[{"x": 0, "y": 1}]'); SELECT json_populate_recordset(row(1,2)::j_ordered_pair, '[{"x": 0}, {"y": 3}]'); diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index bd82fd13f7d..6cbdfe43958 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -666,6 +666,11 @@ SELECT jsonb_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]'); SELECT i, jsonb_populate_recordset(row(i,50), '[{"f1":"42"},{"f2":"43"}]') FROM (VALUES (1),(2)) v(i); +-- empty array is a corner case +SELECT jsonb_populate_recordset(null::record, '[]'); +SELECT jsonb_populate_recordset(row(1,2), '[]'); +SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[]') q; + -- composite domain SELECT jsonb_populate_recordset(null::jb_ordered_pair, '[{"x": 0, "y": 1}]'); SELECT jsonb_populate_recordset(row(1,2)::jb_ordered_pair, '[{"x": 0}, {"y": 3}]');