LCOV - code coverage report
Current view: top level - src/backend/tsearch - wparser.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 95.6 % 226 216
Test Date: 2026-02-17 17:20:33 Functions: 90.5 % 21 19
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * wparser.c
       4              :  *      Standard interface to word parser
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, 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
      47          265 : tt_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
      48              :                    Oid prsid)
      49              : {
      50              :     TupleDesc   tupdesc;
      51              :     MemoryContext oldcontext;
      52              :     TSTokenTypeStorage *st;
      53          265 :     TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
      54              : 
      55          265 :     if (!OidIsValid(prs->lextypeOid))
      56            0 :         elog(ERROR, "method lextype isn't defined for text search parser %u",
      57              :              prsid);
      58              : 
      59          265 :     oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
      60              : 
      61          265 :     st = palloc_object(TSTokenTypeStorage);
      62          265 :     st->cur = 0;
      63              :     /* lextype takes one dummy argument */
      64          265 :     st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
      65              :                                                              (Datum) 0));
      66          265 :     funcctx->user_fctx = st;
      67              : 
      68          265 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
      69            0 :         elog(ERROR, "return type must be a row type");
      70          265 :     funcctx->tuple_desc = tupdesc;
      71          265 :     funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
      72              : 
      73          265 :     MemoryContextSwitchTo(oldcontext);
      74          265 : }
      75              : 
      76              : static Datum
      77         6360 : tt_process_call(FuncCallContext *funcctx)
      78              : {
      79              :     TSTokenTypeStorage *st;
      80              : 
      81         6360 :     st = (TSTokenTypeStorage *) funcctx->user_fctx;
      82         6360 :     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         6095 :         sprintf(txtid, "%d", st->list[st->cur].lexid);
      90         6095 :         values[0] = txtid;
      91         6095 :         values[1] = st->list[st->cur].alias;
      92         6095 :         values[2] = st->list[st->cur].descr;
      93              : 
      94         6095 :         tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
      95         6095 :         result = HeapTupleGetDatum(tuple);
      96              : 
      97         6095 :         pfree(values[1]);
      98         6095 :         pfree(values[2]);
      99         6095 :         st->cur++;
     100         6095 :         return result;
     101              :     }
     102          265 :     return (Datum) 0;
     103              : }
     104              : 
     105              : Datum
     106         6288 : ts_token_type_byid(PG_FUNCTION_ARGS)
     107              : {
     108              :     FuncCallContext *funcctx;
     109              :     Datum       result;
     110              : 
     111         6288 :     if (SRF_IS_FIRSTCALL())
     112              :     {
     113          262 :         funcctx = SRF_FIRSTCALL_INIT();
     114          262 :         tt_setup_firstcall(funcctx, fcinfo, PG_GETARG_OID(0));
     115              :     }
     116              : 
     117         6288 :     funcctx = SRF_PERCALL_SETUP();
     118              : 
     119         6288 :     if ((result = tt_process_call(funcctx)) != (Datum) 0)
     120         6026 :         SRF_RETURN_NEXT(funcctx, result);
     121          262 :     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              :     {
     132            3 :         text       *prsname = PG_GETARG_TEXT_PP(0);
     133              :         Oid         prsId;
     134              : 
     135            3 :         funcctx = SRF_FIRSTCALL_INIT();
     136            3 :         prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
     137            3 :         tt_setup_firstcall(funcctx, fcinfo, prsId);
     138              :     }
     139              : 
     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
     162           22 : prs_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
     163              :                     Oid prsid, text *txt)
     164              : {
     165              :     TupleDesc   tupdesc;
     166              :     MemoryContext oldcontext;
     167              :     PrsStorage *st;
     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 = palloc_object(PrsStorage);
     177           22 :     st->cur = 0;
     178           22 :     st->len = 16;
     179           22 :     st->list = palloc_array(LexemeEntry, st->len);
     180              : 
     181           22 :     prsdata = 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 = st;
     208           22 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
     209            0 :         elog(ERROR, "return type must be a row type");
     210           22 :     funcctx->tuple_desc = tupdesc;
     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              :     {
     249           18 :         text       *txt = PG_GETARG_TEXT_PP(1);
     250              : 
     251           18 :         funcctx = SRF_FIRSTCALL_INIT();
     252           18 :         prs_setup_firstcall(funcctx, fcinfo, PG_GETARG_OID(0), txt);
     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              :     {
     271            4 :         text       *prsname = PG_GETARG_TEXT_PP(0);
     272            4 :         text       *txt = PG_GETARG_TEXT_PP(1);
     273              :         Oid         prsId;
     274              : 
     275            4 :         funcctx = SRF_FIRSTCALL_INIT();
     276            4 :         prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
     277            4 :         prs_setup_firstcall(funcctx, fcinfo, prsId, txt);
     278              :     }
     279              : 
     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              : {
     290           73 :     Oid         tsconfig = PG_GETARG_OID(0);
     291           73 :     text       *in = PG_GETARG_TEXT_PP(1);
     292           73 :     TSQuery     query = PG_GETARG_TSQUERY(2);
     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              : 
     300           73 :     cfg = lookup_ts_config_cache(tsconfig);
     301           73 :     prsobj = lookup_ts_parser_cache(cfg->prsId);
     302              : 
     303           73 :     if (!OidIsValid(prsobj->headlineOid))
     304            0 :         ereport(ERROR,
     305              :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     306              :                  errmsg("text search parser does not support headline creation")));
     307              : 
     308           73 :     memset(&prs, 0, sizeof(HeadlineParsedText));
     309           73 :     prs.lenwords = 32;
     310           73 :     prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
     311              : 
     312           73 :     hlparsetext(cfg->cfgId, &prs, query,
     313           73 :                 VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
     314              : 
     315           73 :     if (opt)
     316           33 :         prsoptions = deserialize_deflist(PointerGetDatum(opt));
     317              :     else
     318           40 :         prsoptions = NIL;
     319              : 
     320           73 :     FunctionCall3(&(prsobj->prsheadline),
     321              :                   PointerGetDatum(&prs),
     322              :                   PointerGetDatum(prsoptions),
     323              :                   PointerGetDatum(query));
     324              : 
     325           73 :     out = generateHeadline(&prs);
     326              : 
     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
     348            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
     367           21 : ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
     368              : {
     369           21 :     Oid         tsconfig = PG_GETARG_OID(0);
     370           21 :     Jsonb      *jb = PG_GETARG_JSONB_P(1);
     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;
     374           21 :     JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
     375              :     HeadlineParsedText prs;
     376           21 :     HeadlineJsonState *state = palloc0_object(HeadlineJsonState);
     377              : 
     378           21 :     memset(&prs, 0, sizeof(HeadlineParsedText));
     379           21 :     prs.lenwords = 32;
     380           21 :     prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
     381              : 
     382           21 :     state->prs = &prs;
     383           21 :     state->cfg = lookup_ts_config_cache(tsconfig);
     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))
     392            0 :         ereport(ERROR,
     393              :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     394              :                  errmsg("text search parser does not support headline creation")));
     395              : 
     396           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              : 
     411           21 :     PG_RETURN_JSONB_P(out);
     412              : }
     413              : 
     414              : Datum
     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              : {
     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;
     450           21 :     JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
     451              : 
     452              :     HeadlineParsedText prs;
     453           21 :     HeadlineJsonState *state = palloc0_object(HeadlineJsonState);
     454              : 
     455           21 :     memset(&prs, 0, sizeof(HeadlineParsedText));
     456           21 :     prs.lenwords = 32;
     457           21 :     prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
     458              : 
     459           21 :     state->prs = &prs;
     460           21 :     state->cfg = lookup_ts_config_cache(tsconfig);
     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))
     469            0 :         ereport(ERROR,
     470              :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     471              :                  errmsg("text search parser does not support headline creation")));
     472              : 
     473           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;
     530          114 :     TSQuery     query = state->query;
     531          114 :     List       *prsoptions = state->prsoptions;
     532              : 
     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              : }
        

Generated by: LCOV version 2.0-1