Skip to content

Commit baeca3c

Browse files
author
Nikita Glukhov
committed
Add generic json support in user functions
1 parent 8da3440 commit baeca3c

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)
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