Some refactoring to export json(b) conversion functions
This is to export datum_to_json(), datum_to_jsonb(), and jsonb_from_cstring(), though the last one is exported as jsonb_from_text(). A subsequent commit to add new SQL/JSON constructor functions will need them for calling from the executor. Discussion: https://postgr.es/m/20230720160252.ldk7jy6jqclxfxkq%40alvherre.pgsql
This commit is contained in:
parent
bd88404d3c
commit
b22391a2ff
@ -91,9 +91,9 @@ static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
|
||||
bool use_line_feeds);
|
||||
static void array_to_json_internal(Datum array, StringInfo result,
|
||||
bool use_line_feeds);
|
||||
static void datum_to_json(Datum val, bool is_null, StringInfo result,
|
||||
JsonTypeCategory tcategory, Oid outfuncoid,
|
||||
bool key_scalar);
|
||||
static void datum_to_json_internal(Datum val, bool is_null, StringInfo result,
|
||||
JsonTypeCategory tcategory, Oid outfuncoid,
|
||||
bool key_scalar);
|
||||
static void add_json(Datum val, bool is_null, StringInfo result,
|
||||
Oid val_type, bool key_scalar);
|
||||
static text *catenate_stringinfo_string(StringInfo buffer, const char *addon);
|
||||
@ -173,9 +173,9 @@ json_recv(PG_FUNCTION_ARGS)
|
||||
* it's of an acceptable type, and force it to be quoted.
|
||||
*/
|
||||
static void
|
||||
datum_to_json(Datum val, bool is_null, StringInfo result,
|
||||
JsonTypeCategory tcategory, Oid outfuncoid,
|
||||
bool key_scalar)
|
||||
datum_to_json_internal(Datum val, bool is_null, StringInfo result,
|
||||
JsonTypeCategory tcategory, Oid outfuncoid,
|
||||
bool key_scalar)
|
||||
{
|
||||
char *outputstr;
|
||||
text *jsontext;
|
||||
@ -421,8 +421,9 @@ array_dim_to_json(StringInfo result, int dim, int ndims, int *dims, Datum *vals,
|
||||
|
||||
if (dim + 1 == ndims)
|
||||
{
|
||||
datum_to_json(vals[*valcount], nulls[*valcount], result, tcategory,
|
||||
outfuncoid, false);
|
||||
datum_to_json_internal(vals[*valcount], nulls[*valcount],
|
||||
result, tcategory,
|
||||
outfuncoid, false);
|
||||
(*valcount)++;
|
||||
}
|
||||
else
|
||||
@ -549,7 +550,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
|
||||
json_categorize_type(att->atttypid, false, &tcategory,
|
||||
&outfuncoid);
|
||||
|
||||
datum_to_json(val, isnull, result, tcategory, outfuncoid, false);
|
||||
datum_to_json_internal(val, isnull, result, tcategory, outfuncoid,
|
||||
false);
|
||||
}
|
||||
|
||||
appendStringInfoChar(result, '}');
|
||||
@ -584,7 +586,8 @@ add_json(Datum val, bool is_null, StringInfo result,
|
||||
json_categorize_type(val_type, false,
|
||||
&tcategory, &outfuncoid);
|
||||
|
||||
datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
|
||||
datum_to_json_internal(val, is_null, result, tcategory, outfuncoid,
|
||||
key_scalar);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -704,7 +707,6 @@ to_json(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Datum val = PG_GETARG_DATUM(0);
|
||||
Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
|
||||
StringInfo result;
|
||||
JsonTypeCategory tcategory;
|
||||
Oid outfuncoid;
|
||||
|
||||
@ -716,11 +718,23 @@ to_json(PG_FUNCTION_ARGS)
|
||||
json_categorize_type(val_type, false,
|
||||
&tcategory, &outfuncoid);
|
||||
|
||||
result = makeStringInfo();
|
||||
PG_RETURN_DATUM(datum_to_json(val, tcategory, outfuncoid));
|
||||
}
|
||||
|
||||
datum_to_json(val, false, result, tcategory, outfuncoid, false);
|
||||
/*
|
||||
* Turn a Datum into JSON text.
|
||||
*
|
||||
* tcategory and outfuncoid are from a previous call to json_categorize_type.
|
||||
*/
|
||||
Datum
|
||||
datum_to_json(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
|
||||
{
|
||||
StringInfo result = makeStringInfo();
|
||||
|
||||
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
|
||||
datum_to_json_internal(val, false, result, tcategory, outfuncoid,
|
||||
false);
|
||||
|
||||
return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -780,8 +794,8 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
|
||||
/* fast path for NULLs */
|
||||
if (PG_ARGISNULL(1))
|
||||
{
|
||||
datum_to_json((Datum) 0, true, state->str, JSONTYPE_NULL,
|
||||
InvalidOid, false);
|
||||
datum_to_json_internal((Datum) 0, true, state->str, JSONTYPE_NULL,
|
||||
InvalidOid, false);
|
||||
PG_RETURN_POINTER(state);
|
||||
}
|
||||
|
||||
@ -795,8 +809,8 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
|
||||
appendStringInfoString(state->str, "\n ");
|
||||
}
|
||||
|
||||
datum_to_json(val, false, state->str, state->val_category,
|
||||
state->val_output_func, false);
|
||||
datum_to_json_internal(val, false, state->str, state->val_category,
|
||||
state->val_output_func, false);
|
||||
|
||||
/*
|
||||
* The transition type for json_agg() is declared to be "internal", which
|
||||
@ -1059,8 +1073,8 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
|
||||
key_offset = out->len;
|
||||
|
||||
datum_to_json(arg, false, out, state->key_category,
|
||||
state->key_output_func, true);
|
||||
datum_to_json_internal(arg, false, out, state->key_category,
|
||||
state->key_output_func, true);
|
||||
|
||||
if (unique_keys)
|
||||
{
|
||||
@ -1082,8 +1096,9 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
else
|
||||
arg = PG_GETARG_DATUM(2);
|
||||
|
||||
datum_to_json(arg, PG_ARGISNULL(2), state->str, state->val_category,
|
||||
state->val_output_func, false);
|
||||
datum_to_json_internal(arg, PG_ARGISNULL(2), state->str,
|
||||
state->val_category,
|
||||
state->val_output_func, false);
|
||||
|
||||
PG_RETURN_POINTER(state);
|
||||
}
|
||||
|
@ -59,9 +59,9 @@ static void array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *di
|
||||
Datum *vals, bool *nulls, int *valcount,
|
||||
JsonTypeCategory tcategory, Oid outfuncoid);
|
||||
static void array_to_jsonb_internal(Datum array, JsonbInState *result);
|
||||
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
|
||||
JsonTypeCategory tcategory, Oid outfuncoid,
|
||||
bool key_scalar);
|
||||
static void datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result,
|
||||
JsonTypeCategory tcategory, Oid outfuncoid,
|
||||
bool key_scalar);
|
||||
static void add_jsonb(Datum val, bool is_null, JsonbInState *result,
|
||||
Oid val_type, bool key_scalar);
|
||||
static JsonbParseState *clone_parse_state(JsonbParseState *state);
|
||||
@ -141,6 +141,19 @@ jsonb_send(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* jsonb_from_text
|
||||
*
|
||||
* Turns json text string into a jsonb Datum.
|
||||
*/
|
||||
Datum
|
||||
jsonb_from_text(text *js)
|
||||
{
|
||||
return jsonb_from_cstring(VARDATA_ANY(js),
|
||||
VARSIZE_ANY_EXHDR(js),
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the type name of a jsonb container.
|
||||
*/
|
||||
@ -622,9 +635,9 @@ add_indent(StringInfo out, bool indent, int level)
|
||||
* will be thrown.
|
||||
*/
|
||||
static void
|
||||
datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
|
||||
JsonTypeCategory tcategory, Oid outfuncoid,
|
||||
bool key_scalar)
|
||||
datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result,
|
||||
JsonTypeCategory tcategory, Oid outfuncoid,
|
||||
bool key_scalar)
|
||||
{
|
||||
char *outputstr;
|
||||
bool numeric_error;
|
||||
@ -859,8 +872,8 @@ array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *v
|
||||
{
|
||||
if (dim + 1 == ndims)
|
||||
{
|
||||
datum_to_jsonb(vals[*valcount], nulls[*valcount], result, tcategory,
|
||||
outfuncoid, false);
|
||||
datum_to_jsonb_internal(vals[*valcount], nulls[*valcount], result, tcategory,
|
||||
outfuncoid, false);
|
||||
(*valcount)++;
|
||||
}
|
||||
else
|
||||
@ -982,7 +995,8 @@ composite_to_jsonb(Datum composite, JsonbInState *result)
|
||||
json_categorize_type(att->atttypid, true, &tcategory,
|
||||
&outfuncoid);
|
||||
|
||||
datum_to_jsonb(val, isnull, result, tcategory, outfuncoid, false);
|
||||
datum_to_jsonb_internal(val, isnull, result, tcategory, outfuncoid,
|
||||
false);
|
||||
}
|
||||
|
||||
result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
|
||||
@ -1018,9 +1032,11 @@ add_jsonb(Datum val, bool is_null, JsonbInState *result,
|
||||
json_categorize_type(val_type, true,
|
||||
&tcategory, &outfuncoid);
|
||||
|
||||
datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
|
||||
datum_to_jsonb_internal(val, is_null, result, tcategory, outfuncoid,
|
||||
key_scalar);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Is the given type immutable when coming out of a JSONB context?
|
||||
*
|
||||
@ -1072,7 +1088,6 @@ to_jsonb(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Datum val = PG_GETARG_DATUM(0);
|
||||
Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
|
||||
JsonbInState result;
|
||||
JsonTypeCategory tcategory;
|
||||
Oid outfuncoid;
|
||||
|
||||
@ -1084,11 +1099,25 @@ to_jsonb(PG_FUNCTION_ARGS)
|
||||
json_categorize_type(val_type, true,
|
||||
&tcategory, &outfuncoid);
|
||||
|
||||
PG_RETURN_DATUM(datum_to_jsonb(val, tcategory, outfuncoid));
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn a Datum into jsonb.
|
||||
*
|
||||
* tcategory and outfuncoid are from a previous call to json_categorize_type.
|
||||
*/
|
||||
Datum
|
||||
datum_to_jsonb(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
|
||||
{
|
||||
JsonbInState result;
|
||||
|
||||
memset(&result, 0, sizeof(JsonbInState));
|
||||
|
||||
datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
|
||||
datum_to_jsonb_internal(val, false, &result, tcategory, outfuncoid,
|
||||
false);
|
||||
|
||||
PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
|
||||
return JsonbPGetDatum(JsonbValueToJsonb(result.res));
|
||||
}
|
||||
|
||||
Datum
|
||||
@ -1525,8 +1554,8 @@ jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
|
||||
|
||||
memset(&elem, 0, sizeof(JsonbInState));
|
||||
|
||||
datum_to_jsonb(val, PG_ARGISNULL(1), &elem, state->val_category,
|
||||
state->val_output_func, false);
|
||||
datum_to_jsonb_internal(val, PG_ARGISNULL(1), &elem, state->val_category,
|
||||
state->val_output_func, false);
|
||||
|
||||
jbelem = JsonbValueToJsonb(elem.res);
|
||||
|
||||
@ -1726,8 +1755,8 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
|
||||
memset(&elem, 0, sizeof(JsonbInState));
|
||||
|
||||
datum_to_jsonb(val, false, &elem, state->key_category,
|
||||
state->key_output_func, true);
|
||||
datum_to_jsonb_internal(val, false, &elem, state->key_category,
|
||||
state->key_output_func, true);
|
||||
|
||||
jbkey = JsonbValueToJsonb(elem.res);
|
||||
|
||||
@ -1735,8 +1764,8 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
|
||||
|
||||
memset(&elem, 0, sizeof(JsonbInState));
|
||||
|
||||
datum_to_jsonb(val, PG_ARGISNULL(2), &elem, state->val_category,
|
||||
state->val_output_func, false);
|
||||
datum_to_jsonb_internal(val, PG_ARGISNULL(2), &elem, state->val_category,
|
||||
state->val_output_func, false);
|
||||
|
||||
jbval = JsonbValueToJsonb(elem.res);
|
||||
|
||||
|
@ -82,5 +82,10 @@ typedef enum
|
||||
|
||||
extern void json_categorize_type(Oid typoid, bool is_jsonb,
|
||||
JsonTypeCategory *tcategory, Oid *outfuncoid);
|
||||
extern Datum datum_to_json(Datum val, JsonTypeCategory tcategory,
|
||||
Oid outfuncoid);
|
||||
extern Datum datum_to_jsonb(Datum val, JsonTypeCategory tcategory,
|
||||
Oid outfuncoid);
|
||||
extern Datum jsonb_from_text(text *js);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user