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-04-18 20:16:25 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          304 : tt_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
      48              :                    Oid prsid)
      49              : {
      50              :     TupleDesc   tupdesc;
      51              :     MemoryContext oldcontext;
      52              :     TSTokenTypeStorage *st;
      53          304 :     TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
      54              : 
      55          304 :     if (!OidIsValid(prs->lextypeOid))
      56            0 :         elog(ERROR, "method lextype isn't defined for text search parser %u",
      57              :              prsid);
      58              : 
      59          304 :     oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
      60              : 
      61          304 :     st = palloc_object(TSTokenTypeStorage);
      62          304 :     st->cur = 0;
      63              :     /* lextype takes one dummy argument */
      64          304 :     st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
      65              :                                                              (Datum) 0));
      66          304 :     funcctx->user_fctx = st;
      67              : 
      68          304 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
      69            0 :         elog(ERROR, "return type must be a row type");
      70          304 :     funcctx->tuple_desc = tupdesc;
      71          304 :     funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
      72              : 
      73          304 :     MemoryContextSwitchTo(oldcontext);
      74          304 : }
      75              : 
      76              : static Datum
      77         7296 : tt_process_call(FuncCallContext *funcctx)
      78              : {
      79              :     TSTokenTypeStorage *st;
      80              : 
      81         7296 :     st = (TSTokenTypeStorage *) funcctx->user_fctx;
      82         7296 :     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         6992 :         sprintf(txtid, "%d", st->list[st->cur].lexid);
      90         6992 :         values[0] = txtid;
      91         6992 :         values[1] = st->list[st->cur].alias;
      92         6992 :         values[2] = st->list[st->cur].descr;
      93              : 
      94         6992 :         tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
      95         6992 :         result = HeapTupleGetDatum(tuple);
      96              : 
      97         6992 :         pfree(values[1]);
      98         6992 :         pfree(values[2]);
      99         6992 :         st->cur++;
     100         6992 :         return result;
     101              :     }
     102          304 :     return (Datum) 0;
     103              : }
     104              : 
     105              : Datum
     106         7200 : ts_token_type_byid(PG_FUNCTION_ARGS)
     107              : {
     108              :     FuncCallContext *funcctx;
     109              :     Datum       result;
     110              : 
     111         7200 :     if (SRF_IS_FIRSTCALL())
     112              :     {
     113          300 :         funcctx = SRF_FIRSTCALL_INIT();
     114          300 :         tt_setup_firstcall(funcctx, fcinfo, PG_GETARG_OID(0));
     115              :     }
     116              : 
     117         7200 :     funcctx = SRF_PERCALL_SETUP();
     118              : 
     119         7200 :     if ((result = tt_process_call(funcctx)) != (Datum) 0)
     120         6900 :         SRF_RETURN_NEXT(funcctx, result);
     121          300 :     SRF_RETURN_DONE(funcctx);
     122              : }
     123              : 
     124              : Datum
     125           96 : ts_token_type_byname(PG_FUNCTION_ARGS)
     126              : {
     127              :     FuncCallContext *funcctx;
     128              :     Datum       result;
     129              : 
     130           96 :     if (SRF_IS_FIRSTCALL())
     131              :     {
     132            4 :         text       *prsname = PG_GETARG_TEXT_PP(0);
     133              :         Oid         prsId;
     134              : 
     135            4 :         funcctx = SRF_FIRSTCALL_INIT();
     136            4 :         prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
     137            4 :         tt_setup_firstcall(funcctx, fcinfo, prsId);
     138              :     }
     139              : 
     140           96 :     funcctx = SRF_PERCALL_SETUP();
     141              : 
     142           96 :     if ((result = tt_process_call(funcctx)) != (Datum) 0)
     143           92 :         SRF_RETURN_NEXT(funcctx, result);
     144            4 :     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           29 : prs_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
     163              :                     Oid prsid, text *txt)
     164              : {
     165              :     TupleDesc   tupdesc;
     166              :     MemoryContext oldcontext;
     167              :     PrsStorage *st;
     168           29 :     TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
     169           29 :     char       *lex = NULL;
     170           29 :     int         llen = 0,
     171           29 :                 type = 0;
     172              :     void       *prsdata;
     173              : 
     174           29 :     oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
     175              : 
     176           29 :     st = palloc_object(PrsStorage);
     177           29 :     st->cur = 0;
     178           29 :     st->len = 16;
     179           29 :     st->list = palloc_array(LexemeEntry, st->len);
     180              : 
     181           29 :     prsdata = DatumGetPointer(FunctionCall2(&prs->prsstart,
     182              :                                             PointerGetDatum(VARDATA_ANY(txt)),
     183              :                                             Int32GetDatum(VARSIZE_ANY_EXHDR(txt))));
     184              : 
     185          716 :     while ((type = DatumGetInt32(FunctionCall3(&prs->prstoken,
     186              :                                                PointerGetDatum(prsdata),
     187              :                                                PointerGetDatum(&lex),
     188          716 :                                                PointerGetDatum(&llen)))) != 0)
     189              :     {
     190          687 :         if (st->cur >= st->len)
     191              :         {
     192           16 :             st->len = 2 * st->len;
     193           16 :             st->list = (LexemeEntry *) repalloc(st->list, sizeof(LexemeEntry) * st->len);
     194              :         }
     195          687 :         st->list[st->cur].lexeme = palloc(llen + 1);
     196          687 :         memcpy(st->list[st->cur].lexeme, lex, llen);
     197          687 :         st->list[st->cur].lexeme[llen] = '\0';
     198          687 :         st->list[st->cur].type = type;
     199          687 :         st->cur++;
     200              :     }
     201              : 
     202           29 :     FunctionCall1(&prs->prsend, PointerGetDatum(prsdata));
     203              : 
     204           29 :     st->len = st->cur;
     205           29 :     st->cur = 0;
     206              : 
     207           29 :     funcctx->user_fctx = st;
     208           29 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
     209            0 :         elog(ERROR, "return type must be a row type");
     210           29 :     funcctx->tuple_desc = tupdesc;
     211           29 :     funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
     212           29 :     MemoryContextSwitchTo(oldcontext);
     213           29 : }
     214              : 
     215              : static Datum
     216          716 : prs_process_call(FuncCallContext *funcctx)
     217              : {
     218              :     PrsStorage *st;
     219              : 
     220          716 :     st = (PrsStorage *) funcctx->user_fctx;
     221          716 :     if (st->cur < st->len)
     222              :     {
     223              :         Datum       result;
     224              :         char       *values[2];
     225              :         char        tid[16];
     226              :         HeapTuple   tuple;
     227              : 
     228          687 :         values[0] = tid;
     229          687 :         sprintf(tid, "%d", st->list[st->cur].type);
     230          687 :         values[1] = st->list[st->cur].lexeme;
     231          687 :         tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
     232          687 :         result = HeapTupleGetDatum(tuple);
     233              : 
     234          687 :         pfree(values[1]);
     235          687 :         st->cur++;
     236          687 :         return result;
     237              :     }
     238           29 :     return (Datum) 0;
     239              : }
     240              : 
     241              : Datum
     242          140 : ts_parse_byid(PG_FUNCTION_ARGS)
     243              : {
     244              :     FuncCallContext *funcctx;
     245              :     Datum       result;
     246              : 
     247          140 :     if (SRF_IS_FIRSTCALL())
     248              :     {
     249           24 :         text       *txt = PG_GETARG_TEXT_PP(1);
     250              : 
     251           24 :         funcctx = SRF_FIRSTCALL_INIT();
     252           24 :         prs_setup_firstcall(funcctx, fcinfo, PG_GETARG_OID(0), txt);
     253           24 :         PG_FREE_IF_COPY(txt, 1);
     254              :     }
     255              : 
     256          140 :     funcctx = SRF_PERCALL_SETUP();
     257              : 
     258          140 :     if ((result = prs_process_call(funcctx)) != (Datum) 0)
     259          116 :         SRF_RETURN_NEXT(funcctx, result);
     260           24 :     SRF_RETURN_DONE(funcctx);
     261              : }
     262              : 
     263              : Datum
     264          576 : ts_parse_byname(PG_FUNCTION_ARGS)
     265              : {
     266              :     FuncCallContext *funcctx;
     267              :     Datum       result;
     268              : 
     269          576 :     if (SRF_IS_FIRSTCALL())
     270              :     {
     271            5 :         text       *prsname = PG_GETARG_TEXT_PP(0);
     272            5 :         text       *txt = PG_GETARG_TEXT_PP(1);
     273              :         Oid         prsId;
     274              : 
     275            5 :         funcctx = SRF_FIRSTCALL_INIT();
     276            5 :         prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
     277            5 :         prs_setup_firstcall(funcctx, fcinfo, prsId, txt);
     278              :     }
     279              : 
     280          576 :     funcctx = SRF_PERCALL_SETUP();
     281              : 
     282          576 :     if ((result = prs_process_call(funcctx)) != (Datum) 0)
     283          571 :         SRF_RETURN_NEXT(funcctx, result);
     284            5 :     SRF_RETURN_DONE(funcctx);
     285              : }
     286              : 
     287              : Datum
     288          121 : ts_headline_byid_opt(PG_FUNCTION_ARGS)
     289              : {
     290          121 :     Oid         tsconfig = PG_GETARG_OID(0);
     291          121 :     text       *in = PG_GETARG_TEXT_PP(1);
     292          121 :     TSQuery     query = PG_GETARG_TSQUERY(2);
     293          121 :     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          121 :     cfg = lookup_ts_config_cache(tsconfig);
     301          121 :     prsobj = lookup_ts_parser_cache(cfg->prsId);
     302              : 
     303          121 :     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          121 :     memset(&prs, 0, sizeof(HeadlineParsedText));
     309          121 :     prs.lenwords = 32;
     310          121 :     prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
     311              : 
     312          121 :     hlparsetext(cfg->cfgId, &prs, query,
     313          121 :                 VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
     314              : 
     315          121 :     if (opt)
     316           55 :         prsoptions = deserialize_deflist(PointerGetDatum(opt));
     317              :     else
     318           66 :         prsoptions = NIL;
     319              : 
     320          121 :     FunctionCall3(&(prsobj->prsheadline),
     321              :                   PointerGetDatum(&prs),
     322              :                   PointerGetDatum(prsoptions),
     323              :                   PointerGetDatum(query));
     324              : 
     325          121 :     out = generateHeadline(&prs);
     326              : 
     327          121 :     PG_FREE_IF_COPY(in, 1);
     328          121 :     PG_FREE_IF_COPY(query, 2);
     329          121 :     if (opt)
     330           55 :         PG_FREE_IF_COPY(opt, 3);
     331          121 :     pfree(prs.words);
     332          121 :     pfree(prs.startsel);
     333          121 :     pfree(prs.stopsel);
     334              : 
     335          121 :     PG_RETURN_POINTER(out);
     336              : }
     337              : 
     338              : Datum
     339           66 : ts_headline_byid(PG_FUNCTION_ARGS)
     340              : {
     341           66 :     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           30 : ts_headline_jsonb_byid_opt(PG_FUNCTION_ARGS)
     368              : {
     369           30 :     Oid         tsconfig = PG_GETARG_OID(0);
     370           30 :     Jsonb      *jb = PG_GETARG_JSONB_P(1);
     371           30 :     TSQuery     query = PG_GETARG_TSQUERY(2);
     372           30 :     text       *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
     373              :     Jsonb      *out;
     374           30 :     JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
     375              :     HeadlineParsedText prs;
     376           30 :     HeadlineJsonState *state = palloc0_object(HeadlineJsonState);
     377              : 
     378           30 :     memset(&prs, 0, sizeof(HeadlineParsedText));
     379           30 :     prs.lenwords = 32;
     380           30 :     prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
     381              : 
     382           30 :     state->prs = &prs;
     383           30 :     state->cfg = lookup_ts_config_cache(tsconfig);
     384           30 :     state->prsobj = lookup_ts_parser_cache(state->cfg->prsId);
     385           30 :     state->query = query;
     386           30 :     if (opt)
     387            9 :         state->prsoptions = deserialize_deflist(PointerGetDatum(opt));
     388              :     else
     389           21 :         state->prsoptions = NIL;
     390              : 
     391           30 :     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           30 :     out = transform_jsonb_string_values(jb, state, action);
     397              : 
     398           30 :     PG_FREE_IF_COPY(jb, 1);
     399           30 :     PG_FREE_IF_COPY(query, 2);
     400           30 :     if (opt)
     401            9 :         PG_FREE_IF_COPY(opt, 3);
     402              : 
     403           30 :     pfree(prs.words);
     404              : 
     405           30 :     if (state->transformed)
     406              :     {
     407           18 :         pfree(prs.startsel);
     408           18 :         pfree(prs.stopsel);
     409              :     }
     410              : 
     411           30 :     PG_RETURN_JSONB_P(out);
     412              : }
     413              : 
     414              : Datum
     415           16 : ts_headline_jsonb(PG_FUNCTION_ARGS)
     416              : {
     417           16 :     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            5 : ts_headline_jsonb_byid(PG_FUNCTION_ARGS)
     425              : {
     426            5 :     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            4 : ts_headline_jsonb_opt(PG_FUNCTION_ARGS)
     434              : {
     435            4 :     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           30 : ts_headline_json_byid_opt(PG_FUNCTION_ARGS)
     444              : {
     445           30 :     Oid         tsconfig = PG_GETARG_OID(0);
     446           30 :     text       *json = PG_GETARG_TEXT_P(1);
     447           30 :     TSQuery     query = PG_GETARG_TSQUERY(2);
     448           30 :     text       *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
     449              :     text       *out;
     450           30 :     JsonTransformStringValuesAction action = (JsonTransformStringValuesAction) headline_json_value;
     451              : 
     452              :     HeadlineParsedText prs;
     453           30 :     HeadlineJsonState *state = palloc0_object(HeadlineJsonState);
     454              : 
     455           30 :     memset(&prs, 0, sizeof(HeadlineParsedText));
     456           30 :     prs.lenwords = 32;
     457           30 :     prs.words = palloc_array(HeadlineWordEntry, prs.lenwords);
     458              : 
     459           30 :     state->prs = &prs;
     460           30 :     state->cfg = lookup_ts_config_cache(tsconfig);
     461           30 :     state->prsobj = lookup_ts_parser_cache(state->cfg->prsId);
     462           30 :     state->query = query;
     463           30 :     if (opt)
     464            9 :         state->prsoptions = deserialize_deflist(PointerGetDatum(opt));
     465              :     else
     466           21 :         state->prsoptions = NIL;
     467              : 
     468           30 :     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           30 :     out = transform_json_string_values(json, state, action);
     474              : 
     475           30 :     PG_FREE_IF_COPY(json, 1);
     476           30 :     PG_FREE_IF_COPY(query, 2);
     477           30 :     if (opt)
     478            9 :         PG_FREE_IF_COPY(opt, 3);
     479           30 :     pfree(prs.words);
     480              : 
     481           30 :     if (state->transformed)
     482              :     {
     483           18 :         pfree(prs.startsel);
     484           18 :         pfree(prs.stopsel);
     485              :     }
     486              : 
     487           30 :     PG_RETURN_TEXT_P(out);
     488              : }
     489              : 
     490              : Datum
     491           16 : ts_headline_json(PG_FUNCTION_ARGS)
     492              : {
     493           16 :     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            5 : ts_headline_json_byid(PG_FUNCTION_ARGS)
     501              : {
     502            5 :     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            4 : ts_headline_json_opt(PG_FUNCTION_ARGS)
     510              : {
     511            4 :     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          170 : headline_json_value(void *_state, char *elem_value, int elem_len)
     524              : {
     525          170 :     HeadlineJsonState *state = (HeadlineJsonState *) _state;
     526              : 
     527          170 :     HeadlineParsedText *prs = state->prs;
     528          170 :     TSConfigCacheEntry *cfg = state->cfg;
     529          170 :     TSParserCacheEntry *prsobj = state->prsobj;
     530          170 :     TSQuery     query = state->query;
     531          170 :     List       *prsoptions = state->prsoptions;
     532              : 
     533          170 :     prs->curwords = 0;
     534          170 :     hlparsetext(cfg->cfgId, prs, query, elem_value, elem_len);
     535          170 :     FunctionCall3(&(prsobj->prsheadline),
     536              :                   PointerGetDatum(prs),
     537              :                   PointerGetDatum(prsoptions),
     538              :                   PointerGetDatum(query));
     539              : 
     540          170 :     state->transformed = true;
     541          170 :     return generateHeadline(prs);
     542              : }
        

Generated by: LCOV version 2.0-1