Skip to content

Commit 90d68c7

Browse files
author
Nikita Glukhov
committed
Add generic json support in user functions
1 parent 113e5ce commit 90d68c7

File tree

5 files changed

+235
-8
lines changed

5 files changed

+235
-8
lines changed

src/backend/tsearch/to_tsany.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,11 @@ Datum
314314
json_to_tsvector_byid(PG_FUNCTION_ARGS)
315315
{
316316
Oid cfgId = PG_GETARG_OID(0);
317+
#ifndef JSON_GENERIC
317318
text *json = PG_GETARG_TEXT_P(1);
319+
#else
320+
Jsonb *json = DatumGetJsont(PG_GETARG_DATUM(1));
321+
#endif
318322
TSVectorBuildState state;
319323
ParsedText *prs = (ParsedText *) palloc(sizeof(ParsedText));
320324

@@ -323,7 +327,11 @@ json_to_tsvector_byid(PG_FUNCTION_ARGS)
323327
state.cfgId = cfgId;
324328
state.prs = prs;
325329

330+
#ifndef JSON_GENERIC
326331
iterate_json_string_values(json, &state, (JsonIterateStringValuesAction) add_to_tsvector);
332+
#else
333+
iterate_jsonb_string_values(json, &state, (JsonIterateStringValuesAction) add_to_tsvector);
334+
#endif
327335

328336
PG_FREE_IF_COPY(json, 1);
329337
if (state.result == NULL)

src/backend/tsearch/wparser.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
385385
TSQuery query = PG_GETARG_TSQUERY(2);
386386
text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
387387
JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
388-
388+
JsonValue jv;
389389
HeadlineParsedText prs;
390390
HeadlineJsonState *state = palloc0(sizeof(HeadlineJsonState));
391391

@@ -409,6 +409,9 @@ ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
409409

410410
out = transform_jsonb_string_values(jb, state, action);
411411

412+
/* flatten result to jsonb before jb freeing */
413+
out = DatumGetJsonb(PointerGetDatum(JsonValueToJsonb(JsonToJsonValue(out, &jv))));
414+
412415
PG_FREE_IF_COPY(jb, 1);
413416
PG_FREE_IF_COPY(query, 2);
414417
if (opt)
@@ -456,7 +459,11 @@ ts_headline_jsonb_opt(PG_FUNCTION_ARGS)
456459
Datum
457460
ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
458461
{
462+
#ifndef JSON_GENERIC
459463
text *json = PG_GETARG_TEXT_P(1);
464+
#else
465+
Jsonb *json = DatumGetJsont(PG_GETARG_DATUM(1));
466+
#endif
460467
TSQuery query = PG_GETARG_TSQUERY(2);
461468
text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
462469
text *out;
@@ -483,7 +490,18 @@ ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
483490
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
484491
errmsg("text search parser does not support headline creation")));
485492

493+
#ifndef JSON_GENERIC
486494
out = transform_json_string_values(json, state, action);
495+
#else
496+
{
497+
Jsonb *jsonb = transform_jsonb_string_values(json, state, action);
498+
char *str = JsonToCString(&jsonb->root);
499+
500+
out = cstring_to_text(str);
501+
502+
pfree(str);
503+
}
504+
#endif
487505

488506
PG_FREE_IF_COPY(json, 1);
489507
PG_FREE_IF_COPY(query, 2);

src/backend/utils/adt/json.c

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,65 @@
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
14+
15+
#define JSON_C
16+
17+
#define jsonb_in _json_in
18+
#define jsonb_recv _json_recv
19+
20+
#define jsonb_out json_out
21+
#define jsonb_send json_send
22+
#define array_to_jsonb array_to_json
23+
#define row_to_jsonb row_to_json
24+
#define row_to_jsonb_pretty row_to_json_pretty
25+
#define to_jsonb to_json
26+
#define jsonb_agg_transfn json_agg_transfn
27+
#define jsonb_agg_finalfn json_agg_finalfn
28+
#define jsonb_object_agg_transfn json_object_agg_transfn
29+
#define jsonb_object_agg_finalfn json_object_agg_finalfn
30+
#define jsonb_build_object json_build_object
31+
#define jsonb_build_object_noargs json_build_object_noargs
32+
#define jsonb_build_array json_build_array
33+
#define jsonb_build_array_noargs json_build_array_noargs
34+
#define jsonb_object json_object
35+
#define jsonb_object_two_arg json_object_two_arg
36+
#define jsonb_typeof json_typeof
37+
38+
#define jsonb_array_element json_array_element
39+
#define jsonb_array_element_text json_array_element_text
40+
#define jsonb_array_elements json_array_elements
41+
#define jsonb_array_elements_text json_array_elements_text
42+
#define jsonb_array_length json_array_length
43+
#define jsonb_canonical json_canonical
44+
#define jsonb_concat json_concat
45+
#define jsonb_delete json_delete
46+
#define jsonb_delete_idx json_delete_idx
47+
#define jsonb_delete_path json_delete_path
48+
#define jsonb_delete_array json_delete_array
49+
#define jsonb_each json_each
50+
#define jsonb_each_text json_each_text
51+
#define jsonb_insert json_insert
52+
#define jsonb_extract_path json_extract_path
53+
#define jsonb_extract_path_text json_extract_path_text
54+
#define jsonb_object_field json_object_field
55+
#define jsonb_object_field_text json_object_field_text
56+
#define jsonb_object_keys json_object_keys
57+
#define jsonb_populate_record json_populate_record
58+
#define jsonb_populate_recordset json_populate_recordset
59+
#define jsonb_pretty json_pretty
60+
#define jsonb_set json_set
61+
#define jsonb_strip_nulls json_strip_nulls
62+
#define jsonb_to_record json_to_record
63+
#define jsonb_to_recordset json_to_recordset
64+
65+
#define JsonxContainerOps (&jsontContainerOps)
66+
#ifdef JSON_FLATTEN_INTO_TARGET
67+
# define JsonxGetDatum(json) \
68+
PointerGetDatum(cstring_to_text(JsonToCString(JsonRoot(json))))
69+
#else
70+
# define JsonxGetDatum(json) JsontGetDatum(json)
71+
#endif
72+
1473
#include "postgres.h"
1574

1675
#include "access/htup_details.h"
@@ -33,6 +92,15 @@
3392
#include "utils/typcache.h"
3493
#include "utils/syscache.h"
3594

95+
#ifndef JSON_FLATTEN_INTO_TARGET
96+
static inline Datum
97+
JsontGetDatum(Json *json)
98+
{
99+
json->is_json = true;
100+
return JsonGetEOHDatum(json);
101+
}
102+
#endif
103+
36104
/*
37105
* The context of the parser is maintained by the recursive descent
38106
* mechanism, but is passed explicitly to the error reporting routine
@@ -102,9 +170,11 @@ static void json_categorize_type(Oid typoid,
102170
static void datum_to_json(Datum val, bool is_null, StringInfo result,
103171
JsonTypeCategory tcategory, Oid outfuncoid,
104172
bool key_scalar);
173+
#ifndef JSON_GENERIC
105174
static void add_json(Datum val, bool is_null, StringInfo result,
106175
Oid val_type, bool key_scalar);
107176
static text *catenate_stringinfo_string(StringInfo buffer, const char *addon);
177+
#endif
108178

109179
/* the null action object used for pure validation */
110180
static JsonSemAction nullSemAction =
@@ -241,6 +311,7 @@ json_in(PG_FUNCTION_ARGS)
241311
PG_RETURN_TEXT_P(result);
242312
}
243313

314+
#ifndef JSON_GENERIC
244315
/*
245316
* Output.
246317
*/
@@ -266,6 +337,7 @@ json_send(PG_FUNCTION_ARGS)
266337
pq_sendtext(&buf, VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
267338
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
268339
}
340+
#endif
269341

270342
/*
271343
* Binary receive.
@@ -1747,6 +1819,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
17471819
ReleaseTupleDesc(tupdesc);
17481820
}
17491821

1822+
#ifndef JSON_GENERIC
1823+
17501824
/*
17511825
* Append JSON text for "val" to "result".
17521826
*
@@ -1778,6 +1852,8 @@ add_json(Datum val, bool is_null, StringInfo result,
17781852
datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
17791853
}
17801854

1855+
#endif
1856+
17811857
/*
17821858
* SQL function array_to_json(row)
17831859
*/
@@ -1844,6 +1920,8 @@ row_to_json_pretty(PG_FUNCTION_ARGS)
18441920
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
18451921
}
18461922

1923+
#ifndef JSON_GENERIC
1924+
18471925
/*
18481926
* SQL function to_json(anyvalue)
18491927
*/
@@ -2427,7 +2505,7 @@ json_object_two_arg(PG_FUNCTION_ARGS)
24272505

24282506
PG_RETURN_TEXT_P(rval);
24292507
}
2430-
2508+
#endif
24312509

24322510
/*
24332511
* Produce a JSON string literal, properly escaping characters in the text.
@@ -2474,6 +2552,7 @@ escape_json(StringInfo buf, const char *str)
24742552
appendStringInfoCharMacro(buf, '"');
24752553
}
24762554

2555+
#ifndef JSON_GENERIC
24772556
/*
24782557
* SQL function json_typeof(json) -> text
24792558
*
@@ -2528,6 +2607,12 @@ json_typeof(PG_FUNCTION_ARGS)
25282607

25292608
PG_RETURN_TEXT_P(cstring_to_text(type));
25302609
}
2610+
2611+
#endif
2612+
2613+
#include "jsonb.c"
2614+
#include "jsonfuncs.c"
2615+
25312616
extern JsonContainerOps jsontContainerOps;
25322617

25332618
static void

src/backend/utils/adt/jsonb.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ static void jsonb_in_object_end(void *pstate);
7474
static void jsonb_in_array_start(void *pstate);
7575
static void jsonb_in_array_end(void *pstate);
7676
static void jsonb_in_object_field_start(void *pstate, char *fname, bool isnull);
77+
#ifndef JSON_C
7778
static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal);
79+
#endif
7880
static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
7981
static void jsonb_categorize_type(Oid typoid,
8082
JsonbTypeCategory *tcategory,
@@ -92,9 +94,11 @@ static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
9294
bool key_scalar);
9395
static void add_jsonb(Datum val, bool is_null, JsonbInState *result,
9496
Oid val_type, bool key_scalar);
97+
#ifndef JSON_C
9598
static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in,
9699
int estimated_len, JsonFormat format);
97100
static void add_indent(StringInfo out, bool indent, int level);
101+
#endif
98102

99103
/*
100104
* jsonb type input function
@@ -222,6 +226,7 @@ jsonb_typeof(PG_FUNCTION_ARGS)
222226
PG_RETURN_TEXT_P(cstring_to_text(result));
223227
}
224228

229+
#ifndef JSON_C
225230
JsonbValue *
226231
JsonValueFromCString(char *json, int len)
227232
{
@@ -247,6 +252,7 @@ JsonValueFromCString(char *json, int len)
247252
/* after parsing, the item member has the composed jsonb structure */
248253
return state.res;
249254
}
255+
#endif
250256

251257
/*
252258
* jsonb_from_cstring
@@ -307,6 +313,7 @@ jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
307313
_state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
308314
}
309315

316+
#ifndef JSON_C
310317
static void
311318
jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal)
312319
{
@@ -333,7 +340,7 @@ jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal)
333340
elog(ERROR, "unknown jsonb scalar type");
334341
}
335342
}
336-
343+
#endif
337344

338345
/*
339346
* For jsonb we always want the de-escaped value - that's what's in token
@@ -386,6 +393,7 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
386393
_state->res = pushScalarJsonbValue(&_state->parseState, &v, false);
387394
}
388395

396+
#ifndef JSON_C
389397
/*
390398
* JsonbToCString
391399
* Converts jsonb value to a C-string.
@@ -559,7 +567,7 @@ add_indent(StringInfo out, bool indent, int level)
559567
appendBinaryStringInfo(out, " ", 4);
560568
}
561569
}
562-
570+
#endif
563571

564572
/*
565573
* Determine how we want to render values of a given type in datum_to_jsonb.
@@ -833,7 +841,10 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
833841
}
834842
break;
835843
case JSONBTYPE_JSONCAST:
844+
#ifndef JSON_GENERIC
836845
case JSONBTYPE_JSON:
846+
847+
#endif
837848
{
838849
/* parse the json right into the existing result object */
839850
JsonLexContext *lex;
@@ -857,9 +868,18 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
857868

858869
}
859870
break;
871+
#ifdef JSON_GENERIC
872+
case JSONBTYPE_JSON:
873+
#endif
860874
case JSONBTYPE_JSONB:
861875
{
876+
#ifndef JSON_GENERIC
862877
Jsonb *jsonb = DatumGetJsonb(val);
878+
#else
879+
Jsonb *jsonb = tcategory == JSONBTYPE_JSON
880+
? DatumGetJsont(val)
881+
: DatumGetJsonb(val);
882+
#endif
863883
JsonbIterator *it;
864884

865885
it = JsonbIteratorInit(&jsonb->root);

0 commit comments

Comments
 (0)