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.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index e358b5ad133..06f8d281685 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -421,9 +421,9 @@ static void sn_scalar(void *state, char *token, JsonTokenType tokentype);
/* worker functions for populate_record, to_record, populate_recordset and to_recordset */
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
- bool have_record_arg);
+ bool is_json, bool have_record_arg);
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
- bool have_record_arg);
+ bool is_json, bool have_record_arg);
/* helper functions for populate_record[set] */
static HeapTupleHeader populate_record(TupleDesc tupdesc, RecordIOData **record_p,
@@ -2296,25 +2296,29 @@ elements_scalar(void *state, char *token, JsonTokenType tokentype)
Datum
jsonb_populate_record(PG_FUNCTION_ARGS)
{
- return populate_record_worker(fcinfo, "jsonb_populate_record", true);
+ return populate_record_worker(fcinfo, "jsonb_populate_record",
+ false, true);
}
Datum
jsonb_to_record(PG_FUNCTION_ARGS)
{
- return populate_record_worker(fcinfo, "jsonb_to_record", false);
+ return populate_record_worker(fcinfo, "jsonb_to_record",
+ false, false);
}
Datum
json_populate_record(PG_FUNCTION_ARGS)
{
- return populate_record_worker(fcinfo, "json_populate_record", true);
+ return populate_record_worker(fcinfo, "json_populate_record",
+ true, true);
}
Datum
json_to_record(PG_FUNCTION_ARGS)
{
- return populate_record_worker(fcinfo, "json_to_record", false);
+ return populate_record_worker(fcinfo, "json_to_record",
+ true, false);
}
/* helper function for diagnostics */
@@ -3203,12 +3207,15 @@ populate_record(TupleDesc tupdesc,
return res->t_data;
}
+/*
+ * common worker for json{b}_populate_record() and json{b}_to_record()
+ * is_json and have_record_arg identify the specific function
+ */
static Datum
populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
- bool have_record_arg)
+ bool is_json, bool have_record_arg)
{
int json_arg_num = have_record_arg ? 1 : 0;
- Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
JsValue jsv = {0};
HeapTupleHeader rec;
Datum rettuple;
@@ -3216,8 +3223,6 @@ populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
MemoryContext fnmcxt = fcinfo->flinfo->fn_mcxt;
PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
- Assert(jtype == JSONOID || jtype == JSONBOID);
-
/*
* If first time through, identify input/result record type. Note that
* this stanza looks only at fcinfo context, which can't change during the
@@ -3303,9 +3308,9 @@ populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
PG_RETURN_NULL();
}
- jsv.is_json = jtype == JSONOID;
+ jsv.is_json = is_json;
- if (jsv.is_json)
+ if (is_json)
{
text *json = PG_GETARG_TEXT_PP(json_arg_num);
@@ -3489,25 +3494,29 @@ hash_scalar(void *state, char *token, JsonTokenType tokentype)
Datum
jsonb_populate_recordset(PG_FUNCTION_ARGS)
{
- return populate_recordset_worker(fcinfo, "jsonb_populate_recordset", true);
+ return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
+ false, true);
}
Datum
jsonb_to_recordset(PG_FUNCTION_ARGS)
{
- return populate_recordset_worker(fcinfo, "jsonb_to_recordset", false);
+ return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
+ false, false);
}
Datum
json_populate_recordset(PG_FUNCTION_ARGS)
{
- return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
+ return populate_recordset_worker(fcinfo, "json_populate_recordset",
+ true, true);
}
Datum
json_to_recordset(PG_FUNCTION_ARGS)
{
- return populate_recordset_worker(fcinfo, "json_to_recordset", false);
+ return populate_recordset_worker(fcinfo, "json_to_recordset",
+ true, false);
}
static void
@@ -3544,14 +3553,14 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj)
}
/*
- * common worker for json_populate_recordset() and json_to_recordset()
+ * common worker for json{b}_populate_recordset() and json{b}_to_recordset()
+ * is_json and have_record_arg identify the specific function
*/
static Datum
populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
- bool have_record_arg)
+ bool is_json, bool have_record_arg)
{
int json_arg_num = have_record_arg ? 1 : 0;
- Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
ReturnSetInfo *rsi;
MemoryContext old_cxt;
HeapTupleHeader rec;
@@ -3662,7 +3671,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
state->cache = cache;
state->rec = rec;
- if (jtype == JSONOID)
+ if (is_json)
{
text *json = PG_GETARG_TEXT_PP(json_arg_num);
JsonLexContext *lex;
@@ -3693,8 +3702,6 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
bool skipNested = false;
JsonbIteratorToken r;
- Assert(jtype == JSONBOID);
-
if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -3726,8 +3733,13 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
}
}
+ /*
+ * Note: we must copy the cached tupdesc because the executor will free
+ * the passed-back setDesc, but we want to hang onto the cache in case
+ * we're called again in the same query.
+ */
rsi->setResult = state->tuple_store;
- rsi->setDesc = cache->c.io.composite.tupdesc;
+ rsi->setDesc = CreateTupleDescCopy(cache->c.io.composite.tupdesc);
PG_RETURN_NULL();
}