PostgreSQL Source Code  git master
wparser.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * wparser.c
4  * Standard interface to word parser
5  *
6  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7  *
8  *
9  * IDENTIFICATION
10  * src/backend/tsearch/wparser.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "catalog/namespace.h"
17 #include "catalog/pg_type.h"
18 #include "commands/defrem.h"
19 #include "common/jsonapi.h"
20 #include "funcapi.h"
21 #include "tsearch/ts_cache.h"
22 #include "tsearch/ts_utils.h"
23 #include "utils/builtins.h"
24 #include "utils/jsonfuncs.h"
25 #include "utils/varlena.h"
26 
27 /******sql-level interface******/
28 
29 typedef struct
30 {
31  int cur;
34 
35 /* state for ts_headline_json_* */
36 typedef struct HeadlineJsonState
37 {
45 
46 static text *headline_json_value(void *_state, char *elem_value, int elem_len);
47 
48 static void
50  Oid prsid)
51 {
52  TupleDesc tupdesc;
53  MemoryContext oldcontext;
56 
57  if (!OidIsValid(prs->lextypeOid))
58  elog(ERROR, "method lextype isn't defined for text search parser %u",
59  prsid);
60 
61  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
62 
64  st->cur = 0;
65  /* lextype takes one dummy argument */
67  (Datum) 0));
68  funcctx->user_fctx = (void *) st;
69 
70  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
71  elog(ERROR, "return type must be a row type");
72  funcctx->tuple_desc = tupdesc;
73  funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
74 
75  MemoryContextSwitchTo(oldcontext);
76 }
77 
78 static Datum
80 {
82 
83  st = (TSTokenTypeStorage *) funcctx->user_fctx;
84  if (st->list && st->list[st->cur].lexid)
85  {
86  Datum result;
87  char *values[3];
88  char txtid[16];
89  HeapTuple tuple;
90 
91  sprintf(txtid, "%d", st->list[st->cur].lexid);
92  values[0] = txtid;
93  values[1] = st->list[st->cur].alias;
94  values[2] = st->list[st->cur].descr;
95 
96  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
97  result = HeapTupleGetDatum(tuple);
98 
99  pfree(values[1]);
100  pfree(values[2]);
101  st->cur++;
102  return result;
103  }
104  return (Datum) 0;
105 }
106 
107 Datum
109 {
110  FuncCallContext *funcctx;
111  Datum result;
112 
113  if (SRF_IS_FIRSTCALL())
114  {
115  funcctx = SRF_FIRSTCALL_INIT();
116  tt_setup_firstcall(funcctx, fcinfo, PG_GETARG_OID(0));
117  }
118 
119  funcctx = SRF_PERCALL_SETUP();
120 
121  if ((result = tt_process_call(funcctx)) != (Datum) 0)
122  SRF_RETURN_NEXT(funcctx, result);
123  SRF_RETURN_DONE(funcctx);
124 }
125 
126 Datum
128 {
129  FuncCallContext *funcctx;
130  Datum result;
131 
132  if (SRF_IS_FIRSTCALL())
133  {
134  text *prsname = PG_GETARG_TEXT_PP(0);
135  Oid prsId;
136 
137  funcctx = SRF_FIRSTCALL_INIT();
138  prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
139  tt_setup_firstcall(funcctx, fcinfo, prsId);
140  }
141 
142  funcctx = SRF_PERCALL_SETUP();
143 
144  if ((result = tt_process_call(funcctx)) != (Datum) 0)
145  SRF_RETURN_NEXT(funcctx, result);
146  SRF_RETURN_DONE(funcctx);
147 }
148 
149 typedef struct
150 {
151  int type;
152  char *lexeme;
153 } LexemeEntry;
154 
155 typedef struct
156 {
157  int cur;
158  int len;
160 } PrsStorage;
161 
162 
163 static void
165  Oid prsid, text *txt)
166 {
167  TupleDesc tupdesc;
168  MemoryContext oldcontext;
169  PrsStorage *st;
171  char *lex = NULL;
172  int llen = 0,
173  type = 0;
174  void *prsdata;
175 
176  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
177 
178  st = (PrsStorage *) palloc(sizeof(PrsStorage));
179  st->cur = 0;
180  st->len = 16;
181  st->list = (LexemeEntry *) palloc(sizeof(LexemeEntry) * st->len);
182 
183  prsdata = (void *) DatumGetPointer(FunctionCall2(&prs->prsstart,
186 
187  while ((type = DatumGetInt32(FunctionCall3(&prs->prstoken,
188  PointerGetDatum(prsdata),
189  PointerGetDatum(&lex),
190  PointerGetDatum(&llen)))) != 0)
191  {
192  if (st->cur >= st->len)
193  {
194  st->len = 2 * st->len;
195  st->list = (LexemeEntry *) repalloc(st->list, sizeof(LexemeEntry) * st->len);
196  }
197  st->list[st->cur].lexeme = palloc(llen + 1);
198  memcpy(st->list[st->cur].lexeme, lex, llen);
199  st->list[st->cur].lexeme[llen] = '\0';
200  st->list[st->cur].type = type;
201  st->cur++;
202  }
203 
204  FunctionCall1(&prs->prsend, PointerGetDatum(prsdata));
205 
206  st->len = st->cur;
207  st->cur = 0;
208 
209  funcctx->user_fctx = (void *) st;
210  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
211  elog(ERROR, "return type must be a row type");
212  funcctx->tuple_desc = tupdesc;
213  funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
214  MemoryContextSwitchTo(oldcontext);
215 }
216 
217 static Datum
219 {
220  PrsStorage *st;
221 
222  st = (PrsStorage *) funcctx->user_fctx;
223  if (st->cur < st->len)
224  {
225  Datum result;
226  char *values[2];
227  char tid[16];
228  HeapTuple tuple;
229 
230  values[0] = tid;
231  sprintf(tid, "%d", st->list[st->cur].type);
232  values[1] = st->list[st->cur].lexeme;
233  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
234  result = HeapTupleGetDatum(tuple);
235 
236  pfree(values[1]);
237  st->cur++;
238  return result;
239  }
240  return (Datum) 0;
241 }
242 
243 Datum
245 {
246  FuncCallContext *funcctx;
247  Datum result;
248 
249  if (SRF_IS_FIRSTCALL())
250  {
251  text *txt = PG_GETARG_TEXT_PP(1);
252 
253  funcctx = SRF_FIRSTCALL_INIT();
254  prs_setup_firstcall(funcctx, fcinfo, PG_GETARG_OID(0), txt);
255  PG_FREE_IF_COPY(txt, 1);
256  }
257 
258  funcctx = SRF_PERCALL_SETUP();
259 
260  if ((result = prs_process_call(funcctx)) != (Datum) 0)
261  SRF_RETURN_NEXT(funcctx, result);
262  SRF_RETURN_DONE(funcctx);
263 }
264 
265 Datum
267 {
268  FuncCallContext *funcctx;
269  Datum result;
270 
271  if (SRF_IS_FIRSTCALL())
272  {
273  text *prsname = PG_GETARG_TEXT_PP(0);
274  text *txt = PG_GETARG_TEXT_PP(1);
275  Oid prsId;
276 
277  funcctx = SRF_FIRSTCALL_INIT();
278  prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
279  prs_setup_firstcall(funcctx, fcinfo, prsId, txt);
280  }
281 
282  funcctx = SRF_PERCALL_SETUP();
283 
284  if ((result = prs_process_call(funcctx)) != (Datum) 0)
285  SRF_RETURN_NEXT(funcctx, result);
286  SRF_RETURN_DONE(funcctx);
287 }
288 
289 Datum
291 {
292  Oid tsconfig = PG_GETARG_OID(0);
293  text *in = PG_GETARG_TEXT_PP(1);
294  TSQuery query = PG_GETARG_TSQUERY(2);
295  text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_PP(3) : NULL;
296  HeadlineParsedText prs;
297  List *prsoptions;
298  text *out;
299  TSConfigCacheEntry *cfg;
300  TSParserCacheEntry *prsobj;
301 
302  cfg = lookup_ts_config_cache(tsconfig);
303  prsobj = lookup_ts_parser_cache(cfg->prsId);
304 
305  if (!OidIsValid(prsobj->headlineOid))
306  ereport(ERROR,
307  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
308  errmsg("text search parser does not support headline creation")));
309 
310  memset(&prs, 0, sizeof(HeadlineParsedText));
311  prs.lenwords = 32;
312  prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
313 
314  hlparsetext(cfg->cfgId, &prs, query,
315  VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
316 
317  if (opt)
318  prsoptions = deserialize_deflist(PointerGetDatum(opt));
319  else
320  prsoptions = NIL;
321 
322  FunctionCall3(&(prsobj->prsheadline),
323  PointerGetDatum(&prs),
324  PointerGetDatum(prsoptions),
325  PointerGetDatum(query));
326 
327  out = generateHeadline(&prs);
328 
329  PG_FREE_IF_COPY(in, 1);
330  PG_FREE_IF_COPY(query, 2);
331  if (opt)
332  PG_FREE_IF_COPY(opt, 3);
333  pfree(prs.words);
334  pfree(prs.startsel);
335  pfree(prs.stopsel);
336 
337  PG_RETURN_POINTER(out);
338 }
339 
340 Datum
342 {
344  PG_GETARG_DATUM(0),
345  PG_GETARG_DATUM(1),
346  PG_GETARG_DATUM(2)));
347 }
348 
349 Datum
351 {
354  PG_GETARG_DATUM(0),
355  PG_GETARG_DATUM(1)));
356 }
357 
358 Datum
360 {
363  PG_GETARG_DATUM(0),
364  PG_GETARG_DATUM(1),
365  PG_GETARG_DATUM(2)));
366 }
367 
368 Datum
370 {
371  Oid tsconfig = PG_GETARG_OID(0);
372  Jsonb *jb = PG_GETARG_JSONB_P(1);
373  TSQuery query = PG_GETARG_TSQUERY(2);
374  text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
375  Jsonb *out;
377  HeadlineParsedText prs;
379 
380  memset(&prs, 0, sizeof(HeadlineParsedText));
381  prs.lenwords = 32;
382  prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
383 
384  state->prs = &prs;
385  state->cfg = lookup_ts_config_cache(tsconfig);
386  state->prsobj = lookup_ts_parser_cache(state->cfg->prsId);
387  state->query = query;
388  if (opt)
389  state->prsoptions = deserialize_deflist(PointerGetDatum(opt));
390  else
391  state->prsoptions = NIL;
392 
393  if (!OidIsValid(state->prsobj->headlineOid))
394  ereport(ERROR,
395  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
396  errmsg("text search parser does not support headline creation")));
397 
399 
400  PG_FREE_IF_COPY(jb, 1);
401  PG_FREE_IF_COPY(query, 2);
402  if (opt)
403  PG_FREE_IF_COPY(opt, 3);
404 
405  pfree(prs.words);
406 
407  if (state->transformed)
408  {
409  pfree(prs.startsel);
410  pfree(prs.stopsel);
411  }
412 
413  PG_RETURN_JSONB_P(out);
414 }
415 
416 Datum
418 {
421  PG_GETARG_DATUM(0),
422  PG_GETARG_DATUM(1)));
423 }
424 
425 Datum
427 {
429  PG_GETARG_DATUM(0),
430  PG_GETARG_DATUM(1),
431  PG_GETARG_DATUM(2)));
432 }
433 
434 Datum
436 {
439  PG_GETARG_DATUM(0),
440  PG_GETARG_DATUM(1),
441  PG_GETARG_DATUM(2)));
442 }
443 
444 Datum
446 {
447  Oid tsconfig = PG_GETARG_OID(0);
448  text *json = PG_GETARG_TEXT_P(1);
449  TSQuery query = PG_GETARG_TSQUERY(2);
450  text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
451  text *out;
453 
454  HeadlineParsedText prs;
456 
457  memset(&prs, 0, sizeof(HeadlineParsedText));
458  prs.lenwords = 32;
459  prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
460 
461  state->prs = &prs;
462  state->cfg = lookup_ts_config_cache(tsconfig);
463  state->prsobj = lookup_ts_parser_cache(state->cfg->prsId);
464  state->query = query;
465  if (opt)
466  state->prsoptions = deserialize_deflist(PointerGetDatum(opt));
467  else
468  state->prsoptions = NIL;
469 
470  if (!OidIsValid(state->prsobj->headlineOid))
471  ereport(ERROR,
472  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
473  errmsg("text search parser does not support headline creation")));
474 
476 
477  PG_FREE_IF_COPY(json, 1);
478  PG_FREE_IF_COPY(query, 2);
479  if (opt)
480  PG_FREE_IF_COPY(opt, 3);
481  pfree(prs.words);
482 
483  if (state->transformed)
484  {
485  pfree(prs.startsel);
486  pfree(prs.stopsel);
487  }
488 
489  PG_RETURN_TEXT_P(out);
490 }
491 
492 Datum
494 {
497  PG_GETARG_DATUM(0),
498  PG_GETARG_DATUM(1)));
499 }
500 
501 Datum
503 {
505  PG_GETARG_DATUM(0),
506  PG_GETARG_DATUM(1),
507  PG_GETARG_DATUM(2)));
508 }
509 
510 Datum
512 {
515  PG_GETARG_DATUM(0),
516  PG_GETARG_DATUM(1),
517  PG_GETARG_DATUM(2)));
518 }
519 
520 
521 /*
522  * Return headline in text from, generated from a json(b) element
523  */
524 static text *
525 headline_json_value(void *_state, char *elem_value, int elem_len)
526 {
528 
529  HeadlineParsedText *prs = state->prs;
530  TSConfigCacheEntry *cfg = state->cfg;
531  TSParserCacheEntry *prsobj = state->prsobj;
532  TSQuery query = state->query;
533  List *prsoptions = state->prsoptions;
534 
535  prs->curwords = 0;
536  hlparsetext(cfg->cfgId, prs, query, elem_value, elem_len);
537  FunctionCall3(&(prsobj->prsheadline),
538  PointerGetDatum(prs),
539  PointerGetDatum(prsoptions),
540  PointerGetDatum(query));
541 
542  state->transformed = true;
543  return generateHeadline(prs);
544 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define OidIsValid(objectId)
Definition: c.h:764
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
Definition: execTuples.c:2136
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
Definition: execTuples.c:2087
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:680
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define DirectFunctionCall4(func, arg1, arg2, arg3, arg4)
Definition: fmgr.h:648
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_NARGS()
Definition: fmgr.h:203
#define FunctionCall1(flinfo, arg1)
Definition: fmgr.h:660
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define FunctionCall2(flinfo, arg1, arg2)
Definition: fmgr.h:662
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:646
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define FunctionCall3(flinfo, arg1, arg2, arg3)
Definition: fmgr.h:664
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:336
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition: funcapi.h:230
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:393
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:391
text * transform_json_string_values(text *json, void *action_state, JsonTransformStringValuesAction transform_action)
Definition: jsonfuncs.c:5553
Jsonb * transform_jsonb_string_values(Jsonb *jsonb, void *action_state, JsonTransformStringValuesAction transform_action)
Definition: jsonfuncs.c:5506
text *(* JsonTransformStringValuesAction)(void *state, char *elem_value, int elem_len)
Definition: jsonfuncs.h:37
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc0(Size size)
Definition: mcxt.c:1257
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1476
void * palloc(Size size)
Definition: mcxt.c:1226
Oid get_ts_parser_oid(List *names, bool missing_ok)
Definition: namespace.c:2325
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
#define NIL
Definition: pg_list.h:68
#define sprintf
Definition: port.h:240
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
unsigned int Oid
Definition: postgres_ext.h:31
void * user_fctx
Definition: funcapi.h:82
AttInMetadata * attinmeta
Definition: funcapi.h:91
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
TupleDesc tuple_desc
Definition: funcapi.h:112
List * prsoptions
Definition: wparser.c:42
TSConfigCacheEntry * cfg
Definition: wparser.c:39
TSParserCacheEntry * prsobj
Definition: wparser.c:40
bool transformed
Definition: wparser.c:43
HeadlineParsedText * prs
Definition: wparser.c:38
TSQuery query
Definition: wparser.c:41
HeadlineWordEntry * words
Definition: ts_public.h:76
Definition: jsonb.h:213
char * alias
Definition: ts_public.h:28
int lexid
Definition: ts_public.h:27
char * descr
Definition: ts_public.h:29
int type
Definition: wparser.c:151
char * lexeme
Definition: wparser.c:152
Definition: pg_list.h:54
int len
Definition: wparser.c:158
int cur
Definition: wparser.c:157
LexemeEntry * list
Definition: wparser.c:159
FmgrInfo prstoken
Definition: ts_cache.h:46
FmgrInfo prsstart
Definition: ts_cache.h:45
FmgrInfo prsheadline
Definition: ts_cache.h:48
FmgrInfo prsend
Definition: ts_cache.h:47
LexDescr * list
Definition: wparser.c:32
Definition: regguts.h:323
Definition: c.h:676
Oid getTSCurrentConfig(bool emitError)
Definition: ts_cache.c:556
TSConfigCacheEntry * lookup_ts_config_cache(Oid cfgId)
Definition: ts_cache.c:385
TSParserCacheEntry * lookup_ts_parser_cache(Oid prsId)
Definition: ts_cache.c:113
void hlparsetext(Oid cfgId, HeadlineParsedText *prs, TSQuery query, char *buf, int buflen)
Definition: ts_parse.c:540
text * generateHeadline(HeadlineParsedText *prs)
Definition: ts_parse.c:607
#define PG_GETARG_TSQUERY(n)
Definition: ts_type.h:266
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1584
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3396
const char * type
static void prs_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo, Oid prsid, text *txt)
Definition: wparser.c:164
Datum ts_headline_opt(PG_FUNCTION_ARGS)
Definition: wparser.c:359
Datum ts_parse_byname(PG_FUNCTION_ARGS)
Definition: wparser.c:266
Datum ts_token_type_byid(PG_FUNCTION_ARGS)
Definition: wparser.c:108
Datum ts_headline(PG_FUNCTION_ARGS)
Definition: wparser.c:350
Datum ts_headline_byid_opt(PG_FUNCTION_ARGS)
Definition: wparser.c:290
static Datum prs_process_call(FuncCallContext *funcctx)
Definition: wparser.c:218
Datum ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
Definition: wparser.c:445
Datum ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
Definition: wparser.c:369
Datum ts_parse_byid(PG_FUNCTION_ARGS)
Definition: wparser.c:244
Datum ts_headline_byid(PG_FUNCTION_ARGS)
Definition: wparser.c:341
struct HeadlineJsonState HeadlineJsonState
Datum ts_headline_jsonb_byid(PG_FUNCTION_ARGS)
Definition: wparser.c:426
static void tt_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo, Oid prsid)
Definition: wparser.c:49
Datum ts_token_type_byname(PG_FUNCTION_ARGS)
Definition: wparser.c:127
Datum ts_headline_json_opt(PG_FUNCTION_ARGS)
Definition: wparser.c:511
Datum ts_headline_jsonb(PG_FUNCTION_ARGS)
Definition: wparser.c:417
Datum ts_headline_jsonb_opt(PG_FUNCTION_ARGS)
Definition: wparser.c:435
Datum ts_headline_json(PG_FUNCTION_ARGS)
Definition: wparser.c:493
static text * headline_json_value(void *_state, char *elem_value, int elem_len)
Definition: wparser.c:525
static Datum tt_process_call(FuncCallContext *funcctx)
Definition: wparser.c:79
Datum ts_headline_json_byid(PG_FUNCTION_ARGS)
Definition: wparser.c:502