Skip to content

Commit b22391a

Browse files
committed
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
1 parent bd88404 commit b22391a

File tree

3 files changed

+90
-41
lines changed

3 files changed

+90
-41
lines changed

src/backend/utils/adt/json.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
9191
bool use_line_feeds);
9292
static void array_to_json_internal(Datum array, StringInfo result,
9393
bool use_line_feeds);
94-
static void datum_to_json(Datum val, bool is_null, StringInfo result,
95-
JsonTypeCategory tcategory, Oid outfuncoid,
96-
bool key_scalar);
94+
static void datum_to_json_internal(Datum val, bool is_null, StringInfo result,
95+
JsonTypeCategory tcategory, Oid outfuncoid,
96+
bool key_scalar);
9797
static void add_json(Datum val, bool is_null, StringInfo result,
9898
Oid val_type, bool key_scalar);
9999
static text *catenate_stringinfo_string(StringInfo buffer, const char *addon);
@@ -173,9 +173,9 @@ json_recv(PG_FUNCTION_ARGS)
173173
* it's of an acceptable type, and force it to be quoted.
174174
*/
175175
static void
176-
datum_to_json(Datum val, bool is_null, StringInfo result,
177-
JsonTypeCategory tcategory, Oid outfuncoid,
178-
bool key_scalar)
176+
datum_to_json_internal(Datum val, bool is_null, StringInfo result,
177+
JsonTypeCategory tcategory, Oid outfuncoid,
178+
bool key_scalar)
179179
{
180180
char *outputstr;
181181
text *jsontext;
@@ -421,8 +421,9 @@ array_dim_to_json(StringInfo result, int dim, int ndims, int *dims, Datum *vals,
421421

422422
if (dim + 1 == ndims)
423423
{
424-
datum_to_json(vals[*valcount], nulls[*valcount], result, tcategory,
425-
outfuncoid, false);
424+
datum_to_json_internal(vals[*valcount], nulls[*valcount],
425+
result, tcategory,
426+
outfuncoid, false);
426427
(*valcount)++;
427428
}
428429
else
@@ -549,7 +550,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
549550
json_categorize_type(att->atttypid, false, &tcategory,
550551
&outfuncoid);
551552

552-
datum_to_json(val, isnull, result, tcategory, outfuncoid, false);
553+
datum_to_json_internal(val, isnull, result, tcategory, outfuncoid,
554+
false);
553555
}
554556

555557
appendStringInfoChar(result, '}');
@@ -584,7 +586,8 @@ add_json(Datum val, bool is_null, StringInfo result,
584586
json_categorize_type(val_type, false,
585587
&tcategory, &outfuncoid);
586588

587-
datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
589+
datum_to_json_internal(val, is_null, result, tcategory, outfuncoid,
590+
key_scalar);
588591
}
589592

590593
/*
@@ -704,7 +707,6 @@ to_json(PG_FUNCTION_ARGS)
704707
{
705708
Datum val = PG_GETARG_DATUM(0);
706709
Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
707-
StringInfo result;
708710
JsonTypeCategory tcategory;
709711
Oid outfuncoid;
710712

@@ -716,11 +718,23 @@ to_json(PG_FUNCTION_ARGS)
716718
json_categorize_type(val_type, false,
717719
&tcategory, &outfuncoid);
718720

719-
result = makeStringInfo();
721+
PG_RETURN_DATUM(datum_to_json(val, tcategory, outfuncoid));
722+
}
720723

721-
datum_to_json(val, false, result, tcategory, outfuncoid, false);
724+
/*
725+
* Turn a Datum into JSON text.
726+
*
727+
* tcategory and outfuncoid are from a previous call to json_categorize_type.
728+
*/
729+
Datum
730+
datum_to_json(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
731+
{
732+
StringInfo result = makeStringInfo();
722733

723-
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
734+
datum_to_json_internal(val, false, result, tcategory, outfuncoid,
735+
false);
736+
737+
return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
724738
}
725739

726740
/*
@@ -780,8 +794,8 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
780794
/* fast path for NULLs */
781795
if (PG_ARGISNULL(1))
782796
{
783-
datum_to_json((Datum) 0, true, state->str, JSONTYPE_NULL,
784-
InvalidOid, false);
797+
datum_to_json_internal((Datum) 0, true, state->str, JSONTYPE_NULL,
798+
InvalidOid, false);
785799
PG_RETURN_POINTER(state);
786800
}
787801

@@ -795,8 +809,8 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
795809
appendStringInfoString(state->str, "\n ");
796810
}
797811

798-
datum_to_json(val, false, state->str, state->val_category,
799-
state->val_output_func, false);
812+
datum_to_json_internal(val, false, state->str, state->val_category,
813+
state->val_output_func, false);
800814

801815
/*
802816
* The transition type for json_agg() is declared to be "internal", which
@@ -1059,8 +1073,8 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
10591073

10601074
key_offset = out->len;
10611075

1062-
datum_to_json(arg, false, out, state->key_category,
1063-
state->key_output_func, true);
1076+
datum_to_json_internal(arg, false, out, state->key_category,
1077+
state->key_output_func, true);
10641078

10651079
if (unique_keys)
10661080
{
@@ -1082,8 +1096,9 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
10821096
else
10831097
arg = PG_GETARG_DATUM(2);
10841098

1085-
datum_to_json(arg, PG_ARGISNULL(2), state->str, state->val_category,
1086-
state->val_output_func, false);
1099+
datum_to_json_internal(arg, PG_ARGISNULL(2), state->str,
1100+
state->val_category,
1101+
state->val_output_func, false);
10871102

10881103
PG_RETURN_POINTER(state);
10891104
}

src/backend/utils/adt/jsonb.c

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ static void array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *di
5959
Datum *vals, bool *nulls, int *valcount,
6060
JsonTypeCategory tcategory, Oid outfuncoid);
6161
static void array_to_jsonb_internal(Datum array, JsonbInState *result);
62-
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
63-
JsonTypeCategory tcategory, Oid outfuncoid,
64-
bool key_scalar);
62+
static void datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result,
63+
JsonTypeCategory tcategory, Oid outfuncoid,
64+
bool key_scalar);
6565
static void add_jsonb(Datum val, bool is_null, JsonbInState *result,
6666
Oid val_type, bool key_scalar);
6767
static JsonbParseState *clone_parse_state(JsonbParseState *state);
@@ -141,6 +141,19 @@ jsonb_send(PG_FUNCTION_ARGS)
141141
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
142142
}
143143

144+
/*
145+
* jsonb_from_text
146+
*
147+
* Turns json text string into a jsonb Datum.
148+
*/
149+
Datum
150+
jsonb_from_text(text *js)
151+
{
152+
return jsonb_from_cstring(VARDATA_ANY(js),
153+
VARSIZE_ANY_EXHDR(js),
154+
NULL);
155+
}
156+
144157
/*
145158
* Get the type name of a jsonb container.
146159
*/
@@ -622,9 +635,9 @@ add_indent(StringInfo out, bool indent, int level)
622635
* will be thrown.
623636
*/
624637
static void
625-
datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
626-
JsonTypeCategory tcategory, Oid outfuncoid,
627-
bool key_scalar)
638+
datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result,
639+
JsonTypeCategory tcategory, Oid outfuncoid,
640+
bool key_scalar)
628641
{
629642
char *outputstr;
630643
bool numeric_error;
@@ -859,8 +872,8 @@ array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *v
859872
{
860873
if (dim + 1 == ndims)
861874
{
862-
datum_to_jsonb(vals[*valcount], nulls[*valcount], result, tcategory,
863-
outfuncoid, false);
875+
datum_to_jsonb_internal(vals[*valcount], nulls[*valcount], result, tcategory,
876+
outfuncoid, false);
864877
(*valcount)++;
865878
}
866879
else
@@ -982,7 +995,8 @@ composite_to_jsonb(Datum composite, JsonbInState *result)
982995
json_categorize_type(att->atttypid, true, &tcategory,
983996
&outfuncoid);
984997

985-
datum_to_jsonb(val, isnull, result, tcategory, outfuncoid, false);
998+
datum_to_jsonb_internal(val, isnull, result, tcategory, outfuncoid,
999+
false);
9861000
}
9871001

9881002
result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
@@ -1018,9 +1032,11 @@ add_jsonb(Datum val, bool is_null, JsonbInState *result,
10181032
json_categorize_type(val_type, true,
10191033
&tcategory, &outfuncoid);
10201034

1021-
datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
1035+
datum_to_jsonb_internal(val, is_null, result, tcategory, outfuncoid,
1036+
key_scalar);
10221037
}
10231038

1039+
10241040
/*
10251041
* Is the given type immutable when coming out of a JSONB context?
10261042
*
@@ -1072,7 +1088,6 @@ to_jsonb(PG_FUNCTION_ARGS)
10721088
{
10731089
Datum val = PG_GETARG_DATUM(0);
10741090
Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
1075-
JsonbInState result;
10761091
JsonTypeCategory tcategory;
10771092
Oid outfuncoid;
10781093

@@ -1084,11 +1099,25 @@ to_jsonb(PG_FUNCTION_ARGS)
10841099
json_categorize_type(val_type, true,
10851100
&tcategory, &outfuncoid);
10861101

1102+
PG_RETURN_DATUM(datum_to_jsonb(val, tcategory, outfuncoid));
1103+
}
1104+
1105+
/*
1106+
* Turn a Datum into jsonb.
1107+
*
1108+
* tcategory and outfuncoid are from a previous call to json_categorize_type.
1109+
*/
1110+
Datum
1111+
datum_to_jsonb(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
1112+
{
1113+
JsonbInState result;
1114+
10871115
memset(&result, 0, sizeof(JsonbInState));
10881116

1089-
datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
1117+
datum_to_jsonb_internal(val, false, &result, tcategory, outfuncoid,
1118+
false);
10901119

1091-
PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1120+
return JsonbPGetDatum(JsonbValueToJsonb(result.res));
10921121
}
10931122

10941123
Datum
@@ -1525,8 +1554,8 @@ jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
15251554

15261555
memset(&elem, 0, sizeof(JsonbInState));
15271556

1528-
datum_to_jsonb(val, PG_ARGISNULL(1), &elem, state->val_category,
1529-
state->val_output_func, false);
1557+
datum_to_jsonb_internal(val, PG_ARGISNULL(1), &elem, state->val_category,
1558+
state->val_output_func, false);
15301559

15311560
jbelem = JsonbValueToJsonb(elem.res);
15321561

@@ -1726,17 +1755,17 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
17261755

17271756
memset(&elem, 0, sizeof(JsonbInState));
17281757

1729-
datum_to_jsonb(val, false, &elem, state->key_category,
1730-
state->key_output_func, true);
1758+
datum_to_jsonb_internal(val, false, &elem, state->key_category,
1759+
state->key_output_func, true);
17311760

17321761
jbkey = JsonbValueToJsonb(elem.res);
17331762

17341763
val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
17351764

17361765
memset(&elem, 0, sizeof(JsonbInState));
17371766

1738-
datum_to_jsonb(val, PG_ARGISNULL(2), &elem, state->val_category,
1739-
state->val_output_func, false);
1767+
datum_to_jsonb_internal(val, PG_ARGISNULL(2), &elem, state->val_category,
1768+
state->val_output_func, false);
17401769

17411770
jbval = JsonbValueToJsonb(elem.res);
17421771

src/include/utils/jsonfuncs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,10 @@ typedef enum
8282

8383
extern void json_categorize_type(Oid typoid, bool is_jsonb,
8484
JsonTypeCategory *tcategory, Oid *outfuncoid);
85+
extern Datum datum_to_json(Datum val, JsonTypeCategory tcategory,
86+
Oid outfuncoid);
87+
extern Datum datum_to_jsonb(Datum val, JsonTypeCategory tcategory,
88+
Oid outfuncoid);
89+
extern Datum jsonb_from_text(text *js);
8590

8691
#endif

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy