diff options
Diffstat (limited to 'src/backend/utils/adt/jsonfuncs.c')
-rw-r--r-- | src/backend/utils/adt/jsonfuncs.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 18e7b9c8798..3a36a83b3c6 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2607,26 +2607,37 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, rsi->returnMode = SFRM_Materialize; - /* - * get the tupdesc from the result set info - it must be a record type - * because we already checked that arg1 is a record type, or we're in a - * to_record function which returns a setof record. - */ - if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("function returning record called in context " - "that cannot accept type record"))); - /* if the json is null send back an empty set */ if (PG_ARGISNULL(json_arg_num)) PG_RETURN_NULL(); if (!have_record_arg || PG_ARGISNULL(0)) + { rec = NULL; + + /* + * get the tupdesc from the result set info - it must be a record type + * because we already checked that arg1 is a record type, or we're in + * a to_record function which returns a setof record. + */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function returning record called in context " + "that cannot accept type record"))); + } else + { rec = PG_GETARG_HEAPTUPLEHEADER(0); + /* + * use the input record's own type marking to find a tupdesc for it. + */ + tupType = HeapTupleHeaderGetTypeId(rec); + tupTypmod = HeapTupleHeaderGetTypMod(rec); + tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + } + tupType = tupdesc->tdtypeid; tupTypmod = tupdesc->tdtypmod; ncolumns = tupdesc->natts; @@ -2670,6 +2681,9 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, false, work_mem); MemoryContextSwitchTo(old_cxt); + /* unnecessary, but harmless, if tupdesc came from get_call_result_type: */ + ReleaseTupleDesc(tupdesc); + state->function_name = funcname; state->my_extra = my_extra; state->rec = rec; |