Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * wparser.c
4 : : * Standard interface to word parser
5 : : *
6 : : * Portions Copyright (c) 1996-2024, 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 "commands/defrem.h"
18 : : #include "funcapi.h"
19 : : #include "tsearch/ts_cache.h"
20 : : #include "tsearch/ts_utils.h"
21 : : #include "utils/fmgrprotos.h"
22 : : #include "utils/jsonfuncs.h"
23 : : #include "utils/varlena.h"
24 : :
25 : : /******sql-level interface******/
26 : :
27 : : typedef struct
28 : : {
29 : : int cur;
30 : : LexDescr *list;
31 : : } TSTokenTypeStorage;
32 : :
33 : : /* state for ts_headline_json_* */
34 : : typedef struct HeadlineJsonState
35 : : {
36 : : HeadlineParsedText *prs;
37 : : TSConfigCacheEntry *cfg;
38 : : TSParserCacheEntry *prsobj;
39 : : TSQuery query;
40 : : List *prsoptions;
41 : : bool transformed;
42 : : } HeadlineJsonState;
43 : :
44 : : static text *headline_json_value(void *_state, char *elem_value, int elem_len);
45 : :
46 : : static void
480 michael@paquier.xyz 47 :CBC 193 : tt_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
48 : : Oid prsid)
49 : : {
50 : : TupleDesc tupdesc;
51 : : MemoryContext oldcontext;
52 : : TSTokenTypeStorage *st;
6081 tgl@sss.pgh.pa.us 53 : 193 : TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
54 : :
55 [ - + ]: 193 : if (!OidIsValid(prs->lextypeOid))
6081 tgl@sss.pgh.pa.us 56 [ # # ]:UBC 0 : elog(ERROR, "method lextype isn't defined for text search parser %u",
57 : : prsid);
58 : :
6081 tgl@sss.pgh.pa.us 59 :CBC 193 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
60 : :
61 : 193 : st = (TSTokenTypeStorage *) palloc(sizeof(TSTokenTypeStorage));
62 : 193 : st->cur = 0;
63 : : /* lextype takes one dummy argument */
64 : 193 : st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
65 : : (Datum) 0));
66 : 193 : funcctx->user_fctx = (void *) st;
67 : :
480 michael@paquier.xyz 68 [ - + ]: 193 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
480 michael@paquier.xyz 69 [ # # ]:UBC 0 : elog(ERROR, "return type must be a row type");
480 michael@paquier.xyz 70 :CBC 193 : funcctx->tuple_desc = tupdesc;
6081 tgl@sss.pgh.pa.us 71 : 193 : funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
72 : :
73 : 193 : MemoryContextSwitchTo(oldcontext);
74 : 193 : }
75 : :
76 : : static Datum
77 : 4632 : tt_process_call(FuncCallContext *funcctx)
78 : : {
79 : : TSTokenTypeStorage *st;
80 : :
81 : 4632 : st = (TSTokenTypeStorage *) funcctx->user_fctx;
82 [ + - + + ]: 4632 : if (st->list && st->list[st->cur].lexid)
83 : : {
84 : : Datum result;
85 : : char *values[3];
86 : : char txtid[16];
87 : : HeapTuple tuple;
88 : :
89 : 4439 : sprintf(txtid, "%d", st->list[st->cur].lexid);
90 : 4439 : values[0] = txtid;
91 : 4439 : values[1] = st->list[st->cur].alias;
92 : 4439 : values[2] = st->list[st->cur].descr;
93 : :
94 : 4439 : tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
95 : 4439 : result = HeapTupleGetDatum(tuple);
96 : :
97 : 4439 : pfree(values[1]);
98 : 4439 : pfree(values[2]);
99 : 4439 : st->cur++;
100 : 4439 : return result;
101 : : }
102 : 193 : return (Datum) 0;
103 : : }
104 : :
105 : : Datum
106 : 4560 : ts_token_type_byid(PG_FUNCTION_ARGS)
107 : : {
108 : : FuncCallContext *funcctx;
109 : : Datum result;
110 : :
111 [ + + ]: 4560 : if (SRF_IS_FIRSTCALL())
112 : : {
113 : 190 : funcctx = SRF_FIRSTCALL_INIT();
480 michael@paquier.xyz 114 : 190 : tt_setup_firstcall(funcctx, fcinfo, PG_GETARG_OID(0));
115 : : }
116 : :
6081 tgl@sss.pgh.pa.us 117 : 4560 : funcctx = SRF_PERCALL_SETUP();
118 : :
119 [ + + ]: 4560 : if ((result = tt_process_call(funcctx)) != (Datum) 0)
120 : 4370 : SRF_RETURN_NEXT(funcctx, result);
121 : 190 : SRF_RETURN_DONE(funcctx);
122 : : }
123 : :
124 : : Datum
125 : 72 : ts_token_type_byname(PG_FUNCTION_ARGS)
126 : : {
127 : : FuncCallContext *funcctx;
128 : : Datum result;
129 : :
130 [ + + ]: 72 : if (SRF_IS_FIRSTCALL())
131 : : {
2590 noah@leadboat.com 132 : 3 : text *prsname = PG_GETARG_TEXT_PP(0);
133 : : Oid prsId;
134 : :
6081 tgl@sss.pgh.pa.us 135 : 3 : funcctx = SRF_FIRSTCALL_INIT();
5001 rhaas@postgresql.org 136 : 3 : prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
480 michael@paquier.xyz 137 : 3 : tt_setup_firstcall(funcctx, fcinfo, prsId);
138 : : }
139 : :
6081 tgl@sss.pgh.pa.us 140 : 72 : funcctx = SRF_PERCALL_SETUP();
141 : :
142 [ + + ]: 72 : if ((result = tt_process_call(funcctx)) != (Datum) 0)
143 : 69 : SRF_RETURN_NEXT(funcctx, result);
144 : 3 : SRF_RETURN_DONE(funcctx);
145 : : }
146 : :
147 : : typedef struct
148 : : {
149 : : int type;
150 : : char *lexeme;
151 : : } LexemeEntry;
152 : :
153 : : typedef struct
154 : : {
155 : : int cur;
156 : : int len;
157 : : LexemeEntry *list;
158 : : } PrsStorage;
159 : :
160 : :
161 : : static void
480 michael@paquier.xyz 162 : 22 : prs_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
163 : : Oid prsid, text *txt)
164 : : {
165 : : TupleDesc tupdesc;
166 : : MemoryContext oldcontext;
167 : : PrsStorage *st;
6081 tgl@sss.pgh.pa.us 168 : 22 : TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
169 : 22 : char *lex = NULL;
170 : 22 : int llen = 0,
171 : 22 : type = 0;
172 : : void *prsdata;
173 : :
174 : 22 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
175 : :
176 : 22 : st = (PrsStorage *) palloc(sizeof(PrsStorage));
177 : 22 : st->cur = 0;
178 : 22 : st->len = 16;
179 : 22 : st->list = (LexemeEntry *) palloc(sizeof(LexemeEntry) * st->len);
180 : :
181 [ - + - - : 22 : prsdata = (void *) DatumGetPointer(FunctionCall2(&prs->prsstart,
- - - - -
+ - + ]
182 : : PointerGetDatum(VARDATA_ANY(txt)),
183 : : Int32GetDatum(VARSIZE_ANY_EXHDR(txt))));
184 : :
185 : 541 : while ((type = DatumGetInt32(FunctionCall3(&prs->prstoken,
186 : : PointerGetDatum(prsdata),
187 : : PointerGetDatum(&lex),
188 [ + + ]: 541 : PointerGetDatum(&llen)))) != 0)
189 : : {
190 [ + + ]: 519 : if (st->cur >= st->len)
191 : : {
192 : 12 : st->len = 2 * st->len;
193 : 12 : st->list = (LexemeEntry *) repalloc(st->list, sizeof(LexemeEntry) * st->len);
194 : : }
195 : 519 : st->list[st->cur].lexeme = palloc(llen + 1);
196 : 519 : memcpy(st->list[st->cur].lexeme, lex, llen);
197 : 519 : st->list[st->cur].lexeme[llen] = '\0';
198 : 519 : st->list[st->cur].type = type;
199 : 519 : st->cur++;
200 : : }
201 : :
202 : 22 : FunctionCall1(&prs->prsend, PointerGetDatum(prsdata));
203 : :
204 : 22 : st->len = st->cur;
205 : 22 : st->cur = 0;
206 : :
207 : 22 : funcctx->user_fctx = (void *) st;
480 michael@paquier.xyz 208 [ - + ]: 22 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
480 michael@paquier.xyz 209 [ # # ]:UBC 0 : elog(ERROR, "return type must be a row type");
480 michael@paquier.xyz 210 :CBC 22 : funcctx->tuple_desc = tupdesc;
6081 tgl@sss.pgh.pa.us 211 : 22 : funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
212 : 22 : MemoryContextSwitchTo(oldcontext);
213 : 22 : }
214 : :
215 : : static Datum
216 : 541 : prs_process_call(FuncCallContext *funcctx)
217 : : {
218 : : PrsStorage *st;
219 : :
220 : 541 : st = (PrsStorage *) funcctx->user_fctx;
221 [ + + ]: 541 : if (st->cur < st->len)
222 : : {
223 : : Datum result;
224 : : char *values[2];
225 : : char tid[16];
226 : : HeapTuple tuple;
227 : :
228 : 519 : values[0] = tid;
229 : 519 : sprintf(tid, "%d", st->list[st->cur].type);
230 : 519 : values[1] = st->list[st->cur].lexeme;
231 : 519 : tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
232 : 519 : result = HeapTupleGetDatum(tuple);
233 : :
234 : 519 : pfree(values[1]);
235 : 519 : st->cur++;
236 : 519 : return result;
237 : : }
238 : 22 : return (Datum) 0;
239 : : }
240 : :
241 : : Datum
242 : 105 : ts_parse_byid(PG_FUNCTION_ARGS)
243 : : {
244 : : FuncCallContext *funcctx;
245 : : Datum result;
246 : :
247 [ + + ]: 105 : if (SRF_IS_FIRSTCALL())
248 : : {
2590 noah@leadboat.com 249 : 18 : text *txt = PG_GETARG_TEXT_PP(1);
250 : :
6081 tgl@sss.pgh.pa.us 251 : 18 : funcctx = SRF_FIRSTCALL_INIT();
480 michael@paquier.xyz 252 : 18 : prs_setup_firstcall(funcctx, fcinfo, PG_GETARG_OID(0), txt);
6081 tgl@sss.pgh.pa.us 253 [ - + ]: 18 : PG_FREE_IF_COPY(txt, 1);
254 : : }
255 : :
256 : 105 : funcctx = SRF_PERCALL_SETUP();
257 : :
258 [ + + ]: 105 : if ((result = prs_process_call(funcctx)) != (Datum) 0)
259 : 87 : SRF_RETURN_NEXT(funcctx, result);
260 : 18 : SRF_RETURN_DONE(funcctx);
261 : : }
262 : :
263 : : Datum
264 : 436 : ts_parse_byname(PG_FUNCTION_ARGS)
265 : : {
266 : : FuncCallContext *funcctx;
267 : : Datum result;
268 : :
269 [ + + ]: 436 : if (SRF_IS_FIRSTCALL())
270 : : {
2590 noah@leadboat.com 271 : 4 : text *prsname = PG_GETARG_TEXT_PP(0);
272 : 4 : text *txt = PG_GETARG_TEXT_PP(1);
273 : : Oid prsId;
274 : :
6081 tgl@sss.pgh.pa.us 275 : 4 : funcctx = SRF_FIRSTCALL_INIT();
5001 rhaas@postgresql.org 276 : 4 : prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
480 michael@paquier.xyz 277 : 4 : prs_setup_firstcall(funcctx, fcinfo, prsId, txt);
278 : : }
279 : :
6081 tgl@sss.pgh.pa.us 280 : 436 : funcctx = SRF_PERCALL_SETUP();
281 : :
282 [ + + ]: 436 : if ((result = prs_process_call(funcctx)) != (Datum) 0)
283 : 432 : SRF_RETURN_NEXT(funcctx, result);
284 : 4 : SRF_RETURN_DONE(funcctx);
285 : : }
286 : :
287 : : Datum
288 : 73 : ts_headline_byid_opt(PG_FUNCTION_ARGS)
289 : : {
2525 290 : 73 : Oid tsconfig = PG_GETARG_OID(0);
2590 noah@leadboat.com 291 : 73 : text *in = PG_GETARG_TEXT_PP(1);
6081 tgl@sss.pgh.pa.us 292 : 73 : TSQuery query = PG_GETARG_TSQUERY(2);
2590 noah@leadboat.com 293 [ + + + - ]: 73 : text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_PP(3) : NULL;
294 : : HeadlineParsedText prs;
295 : : List *prsoptions;
296 : : text *out;
297 : : TSConfigCacheEntry *cfg;
298 : : TSParserCacheEntry *prsobj;
299 : :
2525 tgl@sss.pgh.pa.us 300 : 73 : cfg = lookup_ts_config_cache(tsconfig);
6081 301 : 73 : prsobj = lookup_ts_parser_cache(cfg->prsId);
302 : :
5934 303 [ - + ]: 73 : if (!OidIsValid(prsobj->headlineOid))
5421 bruce@momjian.us 304 [ # # ]:UBC 0 : ereport(ERROR,
305 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
306 : : errmsg("text search parser does not support headline creation")));
307 : :
6077 tgl@sss.pgh.pa.us 308 :CBC 73 : memset(&prs, 0, sizeof(HeadlineParsedText));
6081 309 : 73 : prs.lenwords = 32;
6077 310 : 73 : prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
311 : :
2590 noah@leadboat.com 312 :UBC 0 : hlparsetext(cfg->cfgId, &prs, query,
2590 noah@leadboat.com 313 [ - + - - :CBC 146 : VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
- - - - -
+ - + ]
314 : :
6080 tgl@sss.pgh.pa.us 315 [ + + ]: 73 : if (opt)
316 : 33 : prsoptions = deserialize_deflist(PointerGetDatum(opt));
317 : : else
318 : 40 : prsoptions = NIL;
319 : :
6081 320 : 73 : FunctionCall3(&(prsobj->prsheadline),
321 : : PointerGetDatum(&prs),
322 : : PointerGetDatum(prsoptions),
323 : : PointerGetDatum(query));
324 : :
6077 325 : 73 : out = generateHeadline(&prs);
326 : :
6081 327 [ - + ]: 73 : PG_FREE_IF_COPY(in, 1);
328 [ - + ]: 73 : PG_FREE_IF_COPY(query, 2);
329 [ + + ]: 73 : if (opt)
330 [ - + ]: 33 : PG_FREE_IF_COPY(opt, 3);
331 : 73 : pfree(prs.words);
332 : 73 : pfree(prs.startsel);
333 : 73 : pfree(prs.stopsel);
334 : :
335 : 73 : PG_RETURN_POINTER(out);
336 : : }
337 : :
338 : : Datum
339 : 40 : ts_headline_byid(PG_FUNCTION_ARGS)
340 : : {
341 : 40 : PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_byid_opt,
342 : : PG_GETARG_DATUM(0),
343 : : PG_GETARG_DATUM(1),
344 : : PG_GETARG_DATUM(2)));
345 : : }
346 : :
347 : : Datum
6081 tgl@sss.pgh.pa.us 348 :UBC 0 : ts_headline(PG_FUNCTION_ARGS)
349 : : {
350 : 0 : PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_byid_opt,
351 : : ObjectIdGetDatum(getTSCurrentConfig(true)),
352 : : PG_GETARG_DATUM(0),
353 : : PG_GETARG_DATUM(1)));
354 : : }
355 : :
356 : : Datum
357 : 0 : ts_headline_opt(PG_FUNCTION_ARGS)
358 : : {
359 : 0 : PG_RETURN_DATUM(DirectFunctionCall4(ts_headline_byid_opt,
360 : : ObjectIdGetDatum(getTSCurrentConfig(true)),
361 : : PG_GETARG_DATUM(0),
362 : : PG_GETARG_DATUM(1),
363 : : PG_GETARG_DATUM(2)));
364 : : }
365 : :
366 : : Datum
2571 andrew@dunslane.net 367 :CBC 21 : ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
368 : : {
2524 bruce@momjian.us 369 : 21 : Oid tsconfig = PG_GETARG_OID(0);
2400 tgl@sss.pgh.pa.us 370 : 21 : Jsonb *jb = PG_GETARG_JSONB_P(1);
2524 bruce@momjian.us 371 : 21 : TSQuery query = PG_GETARG_TSQUERY(2);
372 [ + + + - ]: 21 : text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
373 : : Jsonb *out;
2571 andrew@dunslane.net 374 : 21 : JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
375 : : HeadlineParsedText prs;
376 : 21 : HeadlineJsonState *state = palloc0(sizeof(HeadlineJsonState));
377 : :
378 : 21 : memset(&prs, 0, sizeof(HeadlineParsedText));
379 : 21 : prs.lenwords = 32;
380 : 21 : prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
381 : :
382 : 21 : state->prs = &prs;
2525 tgl@sss.pgh.pa.us 383 : 21 : state->cfg = lookup_ts_config_cache(tsconfig);
2571 andrew@dunslane.net 384 : 21 : state->prsobj = lookup_ts_parser_cache(state->cfg->prsId);
385 : 21 : state->query = query;
386 [ + + ]: 21 : if (opt)
387 : 6 : state->prsoptions = deserialize_deflist(PointerGetDatum(opt));
388 : : else
389 : 15 : state->prsoptions = NIL;
390 : :
391 [ - + ]: 21 : if (!OidIsValid(state->prsobj->headlineOid))
2571 andrew@dunslane.net 392 [ # # ]:UBC 0 : ereport(ERROR,
393 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
394 : : errmsg("text search parser does not support headline creation")));
395 : :
2571 andrew@dunslane.net 396 :CBC 21 : out = transform_jsonb_string_values(jb, state, action);
397 : :
398 [ - + ]: 21 : PG_FREE_IF_COPY(jb, 1);
399 [ - + ]: 21 : PG_FREE_IF_COPY(query, 2);
400 [ + + ]: 21 : if (opt)
401 [ - + ]: 6 : PG_FREE_IF_COPY(opt, 3);
402 : :
403 : 21 : pfree(prs.words);
404 : :
405 [ + + ]: 21 : if (state->transformed)
406 : : {
407 : 12 : pfree(prs.startsel);
408 : 12 : pfree(prs.stopsel);
409 : : }
410 : :
2400 tgl@sss.pgh.pa.us 411 : 21 : PG_RETURN_JSONB_P(out);
412 : : }
413 : :
414 : : Datum
2571 andrew@dunslane.net 415 : 12 : ts_headline_jsonb(PG_FUNCTION_ARGS)
416 : : {
417 : 12 : PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_jsonb_byid_opt,
418 : : ObjectIdGetDatum(getTSCurrentConfig(true)),
419 : : PG_GETARG_DATUM(0),
420 : : PG_GETARG_DATUM(1)));
421 : : }
422 : :
423 : : Datum
424 : 3 : ts_headline_jsonb_byid(PG_FUNCTION_ARGS)
425 : : {
426 : 3 : PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_jsonb_byid_opt,
427 : : PG_GETARG_DATUM(0),
428 : : PG_GETARG_DATUM(1),
429 : : PG_GETARG_DATUM(2)));
430 : : }
431 : :
432 : : Datum
433 : 3 : ts_headline_jsonb_opt(PG_FUNCTION_ARGS)
434 : : {
435 : 3 : PG_RETURN_DATUM(DirectFunctionCall4(ts_headline_jsonb_byid_opt,
436 : : ObjectIdGetDatum(getTSCurrentConfig(true)),
437 : : PG_GETARG_DATUM(0),
438 : : PG_GETARG_DATUM(1),
439 : : PG_GETARG_DATUM(2)));
440 : : }
441 : :
442 : : Datum
443 : 21 : ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
444 : : {
2524 bruce@momjian.us 445 : 21 : Oid tsconfig = PG_GETARG_OID(0);
446 : 21 : text *json = PG_GETARG_TEXT_P(1);
447 : 21 : TSQuery query = PG_GETARG_TSQUERY(2);
448 [ + + + - ]: 21 : text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
449 : : text *out;
2571 andrew@dunslane.net 450 : 21 : JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
451 : :
452 : : HeadlineParsedText prs;
453 : 21 : HeadlineJsonState *state = palloc0(sizeof(HeadlineJsonState));
454 : :
455 : 21 : memset(&prs, 0, sizeof(HeadlineParsedText));
456 : 21 : prs.lenwords = 32;
457 : 21 : prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
458 : :
459 : 21 : state->prs = &prs;
2525 tgl@sss.pgh.pa.us 460 : 21 : state->cfg = lookup_ts_config_cache(tsconfig);
2571 andrew@dunslane.net 461 : 21 : state->prsobj = lookup_ts_parser_cache(state->cfg->prsId);
462 : 21 : state->query = query;
463 [ + + ]: 21 : if (opt)
464 : 6 : state->prsoptions = deserialize_deflist(PointerGetDatum(opt));
465 : : else
466 : 15 : state->prsoptions = NIL;
467 : :
468 [ - + ]: 21 : if (!OidIsValid(state->prsobj->headlineOid))
2571 andrew@dunslane.net 469 [ # # ]:UBC 0 : ereport(ERROR,
470 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
471 : : errmsg("text search parser does not support headline creation")));
472 : :
2571 andrew@dunslane.net 473 :CBC 21 : out = transform_json_string_values(json, state, action);
474 : :
475 [ - + ]: 21 : PG_FREE_IF_COPY(json, 1);
476 [ - + ]: 21 : PG_FREE_IF_COPY(query, 2);
477 [ + + ]: 21 : if (opt)
478 [ - + ]: 6 : PG_FREE_IF_COPY(opt, 3);
479 : 21 : pfree(prs.words);
480 : :
481 [ + + ]: 21 : if (state->transformed)
482 : : {
483 : 12 : pfree(prs.startsel);
484 : 12 : pfree(prs.stopsel);
485 : : }
486 : :
487 : 21 : PG_RETURN_TEXT_P(out);
488 : : }
489 : :
490 : : Datum
491 : 12 : ts_headline_json(PG_FUNCTION_ARGS)
492 : : {
493 : 12 : PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_json_byid_opt,
494 : : ObjectIdGetDatum(getTSCurrentConfig(true)),
495 : : PG_GETARG_DATUM(0),
496 : : PG_GETARG_DATUM(1)));
497 : : }
498 : :
499 : : Datum
500 : 3 : ts_headline_json_byid(PG_FUNCTION_ARGS)
501 : : {
502 : 3 : PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_json_byid_opt,
503 : : PG_GETARG_DATUM(0),
504 : : PG_GETARG_DATUM(1),
505 : : PG_GETARG_DATUM(2)));
506 : : }
507 : :
508 : : Datum
509 : 3 : ts_headline_json_opt(PG_FUNCTION_ARGS)
510 : : {
511 : 3 : PG_RETURN_DATUM(DirectFunctionCall4(ts_headline_json_byid_opt,
512 : : ObjectIdGetDatum(getTSCurrentConfig(true)),
513 : : PG_GETARG_DATUM(0),
514 : : PG_GETARG_DATUM(1),
515 : : PG_GETARG_DATUM(2)));
516 : : }
517 : :
518 : :
519 : : /*
520 : : * Return headline in text from, generated from a json(b) element
521 : : */
522 : : static text *
523 : 114 : headline_json_value(void *_state, char *elem_value, int elem_len)
524 : : {
525 : 114 : HeadlineJsonState *state = (HeadlineJsonState *) _state;
526 : :
527 : 114 : HeadlineParsedText *prs = state->prs;
528 : 114 : TSConfigCacheEntry *cfg = state->cfg;
529 : 114 : TSParserCacheEntry *prsobj = state->prsobj;
2524 bruce@momjian.us 530 : 114 : TSQuery query = state->query;
531 : 114 : List *prsoptions = state->prsoptions;
532 : :
2571 andrew@dunslane.net 533 : 114 : prs->curwords = 0;
534 : 114 : hlparsetext(cfg->cfgId, prs, query, elem_value, elem_len);
535 : 114 : FunctionCall3(&(prsobj->prsheadline),
536 : : PointerGetDatum(prs),
537 : : PointerGetDatum(prsoptions),
538 : : PointerGetDatum(query));
539 : :
540 : 114 : state->transformed = true;
541 : 114 : return generateHeadline(prs);
542 : : }
|