Skip to content

Commit 0ab9809

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

File tree

6 files changed

+271
-17
lines changed

6 files changed

+271
-17
lines changed

src/backend/tsearch/to_tsany.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ typedef struct TSVectorBuildState
4242
Oid cfgId;
4343
} TSVectorBuildState;
4444

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

4747

4848
Datum
@@ -360,7 +360,13 @@ jsonb_to_tsvector(PG_FUNCTION_ARGS)
360360
* Worker function for json(_string)_to_tsvector(_byid)
361361
*/
362362
static TSVector
363-
json_to_tsvector_worker(Oid cfgId, text *json, uint32 flags)
363+
json_to_tsvector_worker(Oid cfgId,
364+
#ifndef JSON_GENERIC
365+
text *json,
366+
#else
367+
Jsonb *json,
368+
#endif
369+
uint32 flags)
364370
{
365371
TSVectorBuildState state;
366372
ParsedText prs;
@@ -370,7 +376,11 @@ json_to_tsvector_worker(Oid cfgId, text *json, uint32 flags)
370376
state.prs = &prs;
371377
state.cfgId = cfgId;
372378

379+
#ifndef JSON_GENERIC
373380
iterate_json_values(json, flags, &state, add_to_tsvector);
381+
#else
382+
iterate_jsonb_values(json, flags, &state, add_to_tsvector);
383+
#endif
374384

375385
return make_tsvector(&prs);
376386
}
@@ -379,7 +389,11 @@ Datum
379389
json_string_to_tsvector_byid(PG_FUNCTION_ARGS)
380390
{
381391
Oid cfgId = PG_GETARG_OID(0);
392+
#ifndef JSON_GENERIC
382393
text *json = PG_GETARG_TEXT_P(1);
394+
#else
395+
Jsonb *json = DatumGetJsontP(PG_GETARG_DATUM(1));
396+
#endif
383397
TSVector result;
384398

385399
result = json_to_tsvector_worker(cfgId, json, jtiString);
@@ -391,7 +405,11 @@ json_string_to_tsvector_byid(PG_FUNCTION_ARGS)
391405
Datum
392406
json_string_to_tsvector(PG_FUNCTION_ARGS)
393407
{
408+
#ifndef JSON_GENERIC
394409
text *json = PG_GETARG_TEXT_P(0);
410+
#else
411+
Jsonb *json = DatumGetJsontP(PG_GETARG_DATUM(0));
412+
#endif
395413
Oid cfgId;
396414
TSVector result;
397415

@@ -406,7 +424,11 @@ Datum
406424
json_to_tsvector_byid(PG_FUNCTION_ARGS)
407425
{
408426
Oid cfgId = PG_GETARG_OID(0);
427+
#ifndef JSON_GENERIC
409428
text *json = PG_GETARG_TEXT_P(1);
429+
#else
430+
Jsonb *json = DatumGetJsontP(PG_GETARG_DATUM(1));
431+
#endif
410432
Jsonb *jbFlags = PG_GETARG_JSONB_P(2);
411433
TSVector result;
412434
uint32 flags = parse_jsonb_index_flags(jbFlags);
@@ -421,7 +443,11 @@ json_to_tsvector_byid(PG_FUNCTION_ARGS)
421443
Datum
422444
json_to_tsvector(PG_FUNCTION_ARGS)
423445
{
446+
#ifndef JSON_GENERIC
424447
text *json = PG_GETARG_TEXT_P(0);
448+
#else
449+
Jsonb *json = DatumGetJsontP(PG_GETARG_DATUM(0));
450+
#endif
425451
Jsonb *jbFlags = PG_GETARG_JSONB_P(1);
426452
Oid cfgId;
427453
TSVector result;
@@ -439,7 +465,7 @@ json_to_tsvector(PG_FUNCTION_ARGS)
439465
* Parse lexemes in an element of a json(b) value, add to TSVectorBuildState.
440466
*/
441467
static void
442-
add_to_tsvector(void *_state, char *elem_value, int elem_len)
468+
add_to_tsvector(void *_state, const char *elem_value, int elem_len)
443469
{
444470
TSVectorBuildState *state = (TSVectorBuildState *) _state;
445471
ParsedText *prs = state->prs;
@@ -459,7 +485,7 @@ add_to_tsvector(void *_state, char *elem_value, int elem_len)
459485

460486
prevwords = prs->curwords;
461487

462-
parsetext(state->cfgId, prs, elem_value, elem_len);
488+
parsetext(state->cfgId, prs, (char *) elem_value, elem_len);
463489

464490
/*
465491
* 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: 76 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 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+
#define jsonb_get_element json_get_element
68+
#define jsonb_set_element json_set_element
69+
70+
#define JsonxContainerOps (&jsontContainerOps)
71+
#define JsonxPGetDatum(json) JsontPGetDatum(json)
72+
1473
#include "postgres.h"
1574

1675
#include "catalog/pg_type.h"
@@ -66,9 +125,11 @@ static void json_categorize_type(Oid typoid,
66125
static void datum_to_json(Datum val, bool is_null, StringInfo result,
67126
JsonTypeCategory tcategory, Oid outfuncoid,
68127
bool key_scalar);
128+
#ifndef JSON_GENERIC
69129
static void add_json(Datum val, bool is_null, StringInfo result,
70130
Oid val_type, bool key_scalar);
71131
static text *catenate_stringinfo_string(StringInfo buffer, const char *addon);
132+
#endif
72133

73134
/*
74135
* Input.
@@ -88,6 +149,7 @@ json_in(PG_FUNCTION_ARGS)
88149
PG_RETURN_TEXT_P(result);
89150
}
90151

152+
#ifndef JSON_GENERIC
91153
/*
92154
* Output.
93155
*/
@@ -113,6 +175,7 @@ json_send(PG_FUNCTION_ARGS)
113175
pq_sendtext(&buf, VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
114176
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
115177
}
178+
#endif
116179

117180
/*
118181
* Binary receive.
@@ -626,6 +689,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
626689
ReleaseTupleDesc(tupdesc);
627690
}
628691

692+
#ifndef JSON_GENERIC
693+
629694
/*
630695
* Append JSON text for "val" to "result".
631696
*
@@ -657,6 +722,8 @@ add_json(Datum val, bool is_null, StringInfo result,
657722
datum_to_json(val, is_null, result, tcategory, outfuncoid, key_scalar);
658723
}
659724

725+
#endif
726+
660727
/*
661728
* SQL function array_to_json(row)
662729
*/
@@ -723,6 +790,8 @@ row_to_json_pretty(PG_FUNCTION_ARGS)
723790
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
724791
}
725792

793+
#ifndef JSON_GENERIC
794+
726795
/*
727796
* SQL function to_json(anyvalue)
728797
*/
@@ -1271,7 +1340,7 @@ json_object_two_arg(PG_FUNCTION_ARGS)
12711340

12721341
PG_RETURN_TEXT_P(rval);
12731342
}
1274-
1343+
#endif
12751344

12761345
/*
12771346
* Produce a JSON string literal, properly escaping characters in the text.
@@ -1318,6 +1387,7 @@ escape_json(StringInfo buf, const char *str)
13181387
appendStringInfoCharMacro(buf, '"');
13191388
}
13201389

1390+
#ifndef JSON_GENERIC
13211391
/*
13221392
* SQL function json_typeof(json) -> text
13231393
*
@@ -1375,3 +1445,8 @@ json_typeof(PG_FUNCTION_ARGS)
13751445

13761446
PG_RETURN_TEXT_P(cstring_to_text(type));
13771447
}
1448+
1449+
#endif
1450+
1451+
#include "jsonb.c"
1452+
#include "jsonfuncs.c"

0 commit comments

Comments
 (0)