Skip to content

Commit 0c2b409

Browse files
author
Nikita Glukhov
committed
Add generic json support in user functions
1 parent b0923d1 commit 0c2b409

File tree

6 files changed

+269
-17
lines changed

6 files changed

+269
-17
lines changed

src/backend/tsearch/to_tsany.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ typedef struct TSVectorBuildState
3232
Oid cfgId;
3333
} TSVectorBuildState;
3434

35-
static void add_to_tsvector(void *_state, char *elem_value, int elem_len);
35+
static void add_to_tsvector(void *_state, const char *elem_value, int elem_len);
3636

3737

3838
Datum
@@ -350,7 +350,13 @@ jsonb_to_tsvector(PG_FUNCTION_ARGS)
350350
* Worker function for json(_string)_to_tsvector(_byid)
351351
*/
352352
static TSVector
353-
json_to_tsvector_worker(Oid cfgId, text *json, uint32 flags)
353+
json_to_tsvector_worker(Oid cfgId,
354+
#ifndef JSON_GENERIC
355+
text *json,
356+
#else
357+
Jsonb *json,
358+
#endif
359+
uint32 flags)
354360
{
355361
TSVectorBuildState state;
356362
ParsedText prs;
@@ -360,7 +366,11 @@ json_to_tsvector_worker(Oid cfgId, text *json, uint32 flags)
360366
state.prs = &prs;
361367
state.cfgId = cfgId;
362368

369+
#ifndef JSON_GENERIC
363370
iterate_json_values(json, flags, &state, add_to_tsvector);
371+
#else
372+
iterate_jsonb_values(json, flags, &state, add_to_tsvector);
373+
#endif
364374

365375
return make_tsvector(&prs);
366376
}
@@ -369,7 +379,11 @@ Datum
369379
json_string_to_tsvector_byid(PG_FUNCTION_ARGS)
370380
{
371381
Oid cfgId = PG_GETARG_OID(0);
382+
#ifndef JSON_GENERIC
372383
text *json = PG_GETARG_TEXT_P(1);
384+
#else
385+
Jsonb *json = DatumGetJsontP(PG_GETARG_DATUM(1));
386+
#endif
373387
TSVector result;
374388

375389
result = json_to_tsvector_worker(cfgId, json, jtiString);
@@ -381,7 +395,11 @@ json_string_to_tsvector_byid(PG_FUNCTION_ARGS)
381395
Datum
382396
json_string_to_tsvector(PG_FUNCTION_ARGS)
383397
{
398+
#ifndef JSON_GENERIC
384399
text *json = PG_GETARG_TEXT_P(0);
400+
#else
401+
Jsonb *json = DatumGetJsontP(PG_GETARG_DATUM(0));
402+
#endif
385403
Oid cfgId;
386404
TSVector result;
387405

@@ -396,7 +414,11 @@ Datum
396414
json_to_tsvector_byid(PG_FUNCTION_ARGS)
397415
{
398416
Oid cfgId = PG_GETARG_OID(0);
417+
#ifndef JSON_GENERIC
399418
text *json = PG_GETARG_TEXT_P(1);
419+
#else
420+
Jsonb *json = DatumGetJsontP(PG_GETARG_DATUM(1));
421+
#endif
400422
Jsonb *jbFlags = PG_GETARG_JSONB_P(2);
401423
TSVector result;
402424
uint32 flags = parse_jsonb_index_flags(jbFlags);
@@ -411,7 +433,11 @@ json_to_tsvector_byid(PG_FUNCTION_ARGS)
411433
Datum
412434
json_to_tsvector(PG_FUNCTION_ARGS)
413435
{
436+
#ifndef JSON_GENERIC
414437
text *json = PG_GETARG_TEXT_P(0);
438+
#else
439+
Jsonb *json = DatumGetJsontP(PG_GETARG_DATUM(0));
440+
#endif
415441
Jsonb *jbFlags = PG_GETARG_JSONB_P(1);
416442
Oid cfgId;
417443
TSVector result;
@@ -429,7 +455,7 @@ json_to_tsvector(PG_FUNCTION_ARGS)
429455
* Parse lexemes in an element of a json(b) value, add to TSVectorBuildState.
430456
*/
431457
static void
432-
add_to_tsvector(void *_state, char *elem_value, int elem_len)
458+
add_to_tsvector(void *_state, const char *elem_value, int elem_len)
433459
{
434460
TSVectorBuildState *state = (TSVectorBuildState *) _state;
435461
ParsedText *prs = state->prs;
@@ -449,7 +475,7 @@ add_to_tsvector(void *_state, char *elem_value, int elem_len)
449475

450476
prevwords = prs->curwords;
451477

452-
parsetext(state->cfgId, prs, elem_value, elem_len);
478+
parsetext(state->cfgId, prs, (char *) elem_value, elem_len);
453479

454480
/*
455481
* If we extracted any words from this JSON element, advance pos to create

src/backend/tsearch/wparser.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,10 @@ ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
379379
text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
380380
Jsonb *out;
381381
JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
382+
JsonValue jv;
382383
HeadlineParsedText prs;
383384
HeadlineJsonState *state = palloc0(sizeof(HeadlineJsonState));
385+
Datum res;
384386

385387
memset(&prs, 0, sizeof(HeadlineParsedText));
386388
prs.lenwords = 32;
@@ -402,6 +404,9 @@ ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
402404

403405
out = transform_jsonb_string_values(jb, state, action);
404406

407+
/* flatten result to jsonb before jb freeing */
408+
res = JsonFlattenToJsonbDatum(out);
409+
405410
PG_FREE_IF_COPY(jb, 1);
406411
PG_FREE_IF_COPY(query, 2);
407412
if (opt)
@@ -415,7 +420,7 @@ ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
415420
pfree(prs.stopsel);
416421
}
417422

418-
PG_RETURN_JSONB_P(out);
423+
PG_RETURN_DATUM(res);
419424
}
420425

421426
Datum
@@ -450,7 +455,11 @@ Datum
450455
ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
451456
{
452457
Oid tsconfig = PG_GETARG_OID(0);
458+
#ifndef JSON_GENERIC
453459
text *json = PG_GETARG_TEXT_P(1);
460+
#else
461+
Jsonb *json = DatumGetJsontP(PG_GETARG_DATUM(1));
462+
#endif
454463
TSQuery query = PG_GETARG_TSQUERY(2);
455464
text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
456465
text *out;
@@ -477,7 +486,18 @@ ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
477486
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
478487
errmsg("text search parser does not support headline creation")));
479488

489+
#ifndef JSON_GENERIC
480490
out = transform_json_string_values(json, state, action);
491+
#else
492+
{
493+
Jsonb *jsonb = transform_jsonb_string_values(json, state, action);
494+
char *str = JsonToCString(&jsonb->root);
495+
496+
out = cstring_to_text(str);
497+
498+
pfree(str);
499+
}
500+
#endif
481501

482502
PG_FREE_IF_COPY(json, 1);
483503
PG_FREE_IF_COPY(query, 2);

src/backend/utils/adt/json.c

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

1673
#include "catalog/pg_type.h"
@@ -66,9 +123,11 @@ static void json_categorize_type(Oid typoid,
66123
static void datum_to_json(Datum val, bool is_null, StringInfo result,
67124
JsonTypeCategory tcategory, Oid outfuncoid,
68125
bool key_scalar);
126+
#ifndef JSON_GENERIC
69127
static void add_json(Datum val, bool is_null, StringInfo result,
70128
Oid val_type, bool key_scalar);
71129
static text *catenate_stringinfo_string(StringInfo buffer, const char *addon);
130+
#endif
72131

73132
/*
74133
* Input.
@@ -88,6 +147,7 @@ json_in(PG_FUNCTION_ARGS)
88147
PG_RETURN_TEXT_P(result);
89148
}
90149

150+
#ifndef JSON_GENERIC
91151
/*
92152
* Output.
93153
*/
@@ -113,6 +173,7 @@ json_send(PG_FUNCTION_ARGS)
113173
pq_sendtext(&buf, VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
114174
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
115175
}
176+
#endif
116177

117178
/*
118179
* Binary receive.
@@ -626,6 +687,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
626687
ReleaseTupleDesc(tupdesc);
627688
}
628689

690+
#ifndef JSON_GENERIC
691+
629692
/*
630693
* Append JSON text for "val" to "result".
631694
*
@@ -657,6 +720,8 @@ add_json(Datum val, bool is_null, StringInfo result,
657720
datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
658721
}
659722

723+
#endif
724+
660725
/*
661726
* SQL function array_to_json(row)
662727
*/
@@ -723,6 +788,8 @@ row_to_json_pretty(PG_FUNCTION_ARGS)
723788
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
724789
}
725790

791+
#ifndef JSON_GENERIC
792+
726793
/*
727794
* SQL function to_json(anyvalue)
728795
*/
@@ -1271,7 +1338,7 @@ json_object_two_arg(PG_FUNCTION_ARGS)
12711338

12721339
PG_RETURN_TEXT_P(rval);
12731340
}
1274-
1341+
#endif
12751342

12761343
/*
12771344
* Produce a JSON string literal, properly escaping characters in the text.
@@ -1318,6 +1385,7 @@ escape_json(StringInfo buf, const char *str)
13181385
appendStringInfoCharMacro(buf, '"');
13191386
}
13201387

1388+
#ifndef JSON_GENERIC
13211389
/*
13221390
* SQL function json_typeof(json) -> text
13231391
*
@@ -1375,3 +1443,8 @@ json_typeof(PG_FUNCTION_ARGS)
13751443

13761444
PG_RETURN_TEXT_P(cstring_to_text(type));
13771445
}
1446+
1447+
#endif
1448+
1449+
#include "jsonb.c"
1450+
#include "jsonfuncs.c"

0 commit comments

Comments
 (0)