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