aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/jsonfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/jsonfuncs.c')
-rw-r--r--src/backend/utils/adt/jsonfuncs.c36
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;