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

Generated by: LCOV version 1.14