LCOV - differential code coverage report
Current view: top level - src/backend/tsearch - ts_parse.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 92.8 % 276 256 2 10 8 2 146 5 103 10 148 3
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 15 15 15 15
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 100.0 % 3 3 3
Legend: Lines: hit not hit (180,240] days: 100.0 % 2 2 2
(240..) days: 92.6 % 271 251 2 10 8 2 146 103 10 148
Function coverage date bins:
(240..) days: 50.0 % 30 15 15 15

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * ts_parse.c
                                  4                 :  *      main parse functions for tsearch
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :  *
                                  8                 :  *
                                  9                 :  * IDENTIFICATION
                                 10                 :  *    src/backend/tsearch/ts_parse.c
                                 11                 :  *
                                 12                 :  *-------------------------------------------------------------------------
                                 13                 :  */
                                 14                 : 
                                 15                 : #include "postgres.h"
                                 16                 : 
                                 17                 : #include "tsearch/ts_cache.h"
                                 18                 : #include "tsearch/ts_utils.h"
                                 19                 : #include "varatt.h"
                                 20                 : 
                                 21                 : #define IGNORE_LONGLEXEME   1
                                 22                 : 
                                 23                 : /*
                                 24                 :  * Lexize subsystem
                                 25                 :  */
                                 26                 : 
                                 27                 : typedef struct ParsedLex
                                 28                 : {
                                 29                 :     int         type;
                                 30                 :     char       *lemm;
                                 31                 :     int         lenlemm;
                                 32                 :     struct ParsedLex *next;
                                 33                 : } ParsedLex;
                                 34                 : 
                                 35                 : typedef struct ListParsedLex
                                 36                 : {
                                 37                 :     ParsedLex  *head;
                                 38                 :     ParsedLex  *tail;
                                 39                 : } ListParsedLex;
                                 40                 : 
                                 41                 : typedef struct
                                 42                 : {
                                 43                 :     TSConfigCacheEntry *cfg;
                                 44                 :     Oid         curDictId;
                                 45                 :     int         posDict;
                                 46                 :     DictSubState dictState;
                                 47                 :     ParsedLex  *curSub;
                                 48                 :     ListParsedLex towork;       /* current list to work */
                                 49                 :     ListParsedLex waste;        /* list of lexemes that already lexized */
                                 50                 : 
                                 51                 :     /*
                                 52                 :      * fields to store last variant to lexize (basically, thesaurus or similar
                                 53                 :      * to, which wants  several lexemes
                                 54                 :      */
                                 55                 : 
                                 56                 :     ParsedLex  *lastRes;
                                 57                 :     TSLexeme   *tmpRes;
                                 58                 : } LexizeData;
                                 59                 : 
                                 60                 : static void
 5624 bruce                      61 GIC        2348 : LexizeInit(LexizeData *ld, TSConfigCacheEntry *cfg)
 5710 tgl                        62 ECB             : {
 5710 tgl                        63 GIC        2348 :     ld->cfg = cfg;
 5710 tgl                        64 CBC        2348 :     ld->curDictId = InvalidOid;
                                 65            2348 :     ld->posDict = 0;
                                 66            2348 :     ld->towork.head = ld->towork.tail = ld->curSub = NULL;
                                 67            2348 :     ld->waste.head = ld->waste.tail = NULL;
                                 68            2348 :     ld->lastRes = NULL;
                                 69            2348 :     ld->tmpRes = NULL;
                                 70            2348 : }
 5710 tgl                        71 ECB             : 
                                 72                 : static void
 5624 bruce                      73 GIC       27646 : LPLAddTail(ListParsedLex *list, ParsedLex *newpl)
 5710 tgl                        74 ECB             : {
 5710 tgl                        75 GIC       27646 :     if (list->tail)
 5710 tgl                        76 ECB             :     {
 5710 tgl                        77 GIC         111 :         list->tail->next = newpl;
 5710 tgl                        78 CBC         111 :         list->tail = newpl;
 5710 tgl                        79 ECB             :     }
                                 80                 :     else
 5710 tgl                        81 GIC       27535 :         list->head = list->tail = newpl;
 5710 tgl                        82 CBC       27646 :     newpl->next = NULL;
                                 83           27646 : }
 5710 tgl                        84 ECB             : 
                                 85                 : static ParsedLex *
 5624 bruce                      86 GIC       13823 : LPLRemoveHead(ListParsedLex *list)
 5710 tgl                        87 ECB             : {
 5710 tgl                        88 GIC       13823 :     ParsedLex  *res = list->head;
 5710 tgl                        89 ECB             : 
 5710 tgl                        90 GIC       13823 :     if (list->head)
 5710 tgl                        91 CBC       13823 :         list->head = list->head->next;
 5710 tgl                        92 ECB             : 
 5710 tgl                        93 GIC       13823 :     if (list->head == NULL)
 5710 tgl                        94 CBC       13760 :         list->tail = NULL;
 5710 tgl                        95 ECB             : 
 5710 tgl                        96 GIC       13823 :     return res;
 5710 tgl                        97 ECB             : }
                                 98                 : 
                                 99                 : static void
 5624 bruce                     100 GIC       13823 : LexizeAddLemm(LexizeData *ld, int type, char *lemm, int lenlemm)
 5710 tgl                       101 ECB             : {
 5710 tgl                       102 GIC       13823 :     ParsedLex  *newpl = (ParsedLex *) palloc(sizeof(ParsedLex));
 5710 tgl                       103 ECB             : 
 5710 tgl                       104 GIC       13823 :     newpl->type = type;
 5710 tgl                       105 CBC       13823 :     newpl->lemm = lemm;
                                106           13823 :     newpl->lenlemm = lenlemm;
                                107           13823 :     LPLAddTail(&ld->towork, newpl);
                                108           13823 :     ld->curSub = ld->towork.tail;
                                109           13823 : }
 5710 tgl                       110 ECB             : 
                                111                 : static void
 5624 bruce                     112 GIC       13823 : RemoveHead(LexizeData *ld)
 5710 tgl                       113 ECB             : {
 5710 tgl                       114 GIC       13823 :     LPLAddTail(&ld->waste, LPLRemoveHead(&ld->towork));
 5710 tgl                       115 ECB             : 
 5710 tgl                       116 GIC       13823 :     ld->posDict = 0;
 5710 tgl                       117 CBC       13823 : }
 5710 tgl                       118 ECB             : 
                                119                 : static void
 5624 bruce                     120 GIC       20556 : setCorrLex(LexizeData *ld, ParsedLex **correspondLexem)
 5710 tgl                       121 ECB             : {
 5710 tgl                       122 GIC       20556 :     if (correspondLexem)
 5710 tgl                       123 ECB             :     {
 5710 tgl                       124 GIC        7545 :         *correspondLexem = ld->waste.head;
 5710 tgl                       125 ECB             :     }
                                126                 :     else
                                127                 :     {
                                128                 :         ParsedLex  *tmp,
 5710 tgl                       129 GIC       13011 :                    *ptr = ld->waste.head;
 5710 tgl                       130 ECB             : 
 5710 tgl                       131 GIC       21763 :         while (ptr)
 5710 tgl                       132 ECB             :         {
 5710 tgl                       133 GIC        8752 :             tmp = ptr->next;
 5710 tgl                       134 CBC        8752 :             pfree(ptr);
                                135            8752 :             ptr = tmp;
 5710 tgl                       136 ECB             :         }
                                137                 :     }
 5710 tgl                       138 GIC       20556 :     ld->waste.head = ld->waste.tail = NULL;
 5710 tgl                       139 CBC       20556 : }
 5710 tgl                       140 ECB             : 
                                141                 : static void
 5624 bruce                     142 GIC          24 : moveToWaste(LexizeData *ld, ParsedLex *stop)
 5710 tgl                       143 ECB             : {
 5710 tgl                       144 GIC          24 :     bool        go = true;
 5710 tgl                       145 ECB             : 
 5710 tgl                       146 GIC          90 :     while (ld->towork.head && go)
 5710 tgl                       147 ECB             :     {
 5710 tgl                       148 GIC          66 :         if (ld->towork.head == stop)
 5710 tgl                       149 ECB             :         {
 5710 tgl                       150 GIC          24 :             ld->curSub = stop->next;
 5710 tgl                       151 CBC          24 :             go = false;
 5710 tgl                       152 ECB             :         }
 5710 tgl                       153 GIC          66 :         RemoveHead(ld);
 5710 tgl                       154 ECB             :     }
 5710 tgl                       155 GIC          24 : }
 5710 tgl                       156 ECB             : 
                                157                 : static void
 5624 bruce                     158 GIC          24 : setNewTmpRes(LexizeData *ld, ParsedLex *lex, TSLexeme *res)
 5710 tgl                       159 ECB             : {
 5710 tgl                       160 GIC          24 :     if (ld->tmpRes)
 5710 tgl                       161 ECB             :     {
                                162                 :         TSLexeme   *ptr;
                                163                 : 
 5710 tgl                       164 GIC          12 :         for (ptr = ld->tmpRes; ptr->lexeme; ptr++)
 5710 tgl                       165 CBC           6 :             pfree(ptr->lexeme);
                                166               6 :         pfree(ld->tmpRes);
 5710 tgl                       167 ECB             :     }
 5710 tgl                       168 GIC          24 :     ld->tmpRes = res;
 5710 tgl                       169 CBC          24 :     ld->lastRes = lex;
                                170              24 : }
 5710 tgl                       171 ECB             : 
                                172                 : static TSLexeme *
 5624 bruce                     173 GIC       20580 : LexizeExec(LexizeData *ld, ParsedLex **correspondLexem)
 5710 tgl                       174 ECB             : {
                                175                 :     int         i;
                                176                 :     ListDictionary *map;
                                177                 :     TSDictionaryCacheEntry *dict;
                                178                 :     TSLexeme   *res;
                                179                 : 
 5710 tgl                       180 GIC       20580 :     if (ld->curDictId == InvalidOid)
 5710 tgl                       181 ECB             :     {
                                182                 :         /*
                                183                 :          * usual mode: dictionary wants only one word, but we should keep in
                                184                 :          * mind that we should go through all stack
                                185                 :          */
                                186                 : 
 5710 tgl                       187 GIC       27541 :         while (ld->towork.head)
 5710 tgl                       188 ECB             :         {
 5710 tgl                       189 GIC       13781 :             ParsedLex  *curVal = ld->towork.head;
 4982 teodor                    190 CBC       13781 :             char       *curValLemm = curVal->lemm;
 4790 bruce                     191           13781 :             int         curValLenLemm = curVal->lenlemm;
 5710 tgl                       192 ECB             : 
 5710 tgl                       193 GIC       13781 :             map = ld->cfg->map + curVal->type;
 5710 tgl                       194 ECB             : 
 5710 tgl                       195 GIC       13781 :             if (curVal->type == 0 || curVal->type >= ld->cfg->lenmap || map->len == 0)
 5710 tgl                       196 ECB             :             {
                                197                 :                 /* skip this type of lexeme */
 5710 tgl                       198 GIC        7048 :                 RemoveHead(ld);
 5710 tgl                       199 CBC        7048 :                 continue;
 5710 tgl                       200 ECB             :             }
                                201                 : 
 5710 tgl                       202 GIC        6979 :             for (i = ld->posDict; i < map->len; i++)
 5710 tgl                       203 ECB             :             {
 5710 tgl                       204 GIC        6979 :                 dict = lookup_ts_dictionary_cache(map->dictIds[i]);
 5710 tgl                       205 ECB             : 
 5710 tgl                       206 GIC        6979 :                 ld->dictState.isend = ld->dictState.getnext = false;
 5015 peter_e                   207 CBC        6979 :                 ld->dictState.private_state = NULL;
 1165 alvherre                  208            6979 :                 res = (TSLexeme *) DatumGetPointer(FunctionCall4(&(dict->lexize),
 2118 tgl                       209 ECB             :                                                                  PointerGetDatum(dict->dictData),
                                210                 :                                                                  PointerGetDatum(curValLemm),
                                211                 :                                                                  Int32GetDatum(curValLenLemm),
                                212                 :                                                                  PointerGetDatum(&ld->dictState)));
                                213                 : 
 5710 tgl                       214 GIC        6979 :                 if (ld->dictState.getnext)
 5710 tgl                       215 ECB             :                 {
                                216                 :                     /*
                                217                 :                      * dictionary wants next word, so setup and store current
                                218                 :                      * position and go to multiword mode
                                219                 :                      */
                                220                 : 
 5710 tgl                       221 GIC          24 :                     ld->curDictId = DatumGetObjectId(map->dictIds[i]);
 5710 tgl                       222 CBC          24 :                     ld->posDict = i + 1;
                                223              24 :                     ld->curSub = curVal->next;
                                224              24 :                     if (res)
                                225              18 :                         setNewTmpRes(ld, curVal, res);
                                226              24 :                     return LexizeExec(ld, correspondLexem);
 5710 tgl                       227 ECB             :                 }
                                228                 : 
 5710 tgl                       229 GIC        6955 :                 if (!res)       /* dictionary doesn't know this lexeme */
 5710 tgl                       230 CBC         246 :                     continue;
 5710 tgl                       231 ECB             : 
 4790 bruce                     232 GIC        6709 :                 if (res->flags & TSL_FILTER)
 4982 teodor                    233 ECB             :                 {
 4982 teodor                    234 UIC           0 :                     curValLemm = res->lexeme;
 4982 teodor                    235 UBC           0 :                     curValLenLemm = strlen(res->lexeme);
                                236               0 :                     continue;
 4982 teodor                    237 EUB             :                 }
                                238                 : 
 5710 tgl                       239 GIC        6709 :                 RemoveHead(ld);
 5710 tgl                       240 CBC        6709 :                 setCorrLex(ld, correspondLexem);
                                241            6709 :                 return res;
 5710 tgl                       242 ECB             :             }
                                243                 : 
 5710 tgl                       244 UIC           0 :             RemoveHead(ld);
 5710 tgl                       245 EUB             :         }
                                246                 :     }
                                247                 :     else
                                248                 :     {                           /* curDictId is valid */
 5710 tgl                       249 GIC          87 :         dict = lookup_ts_dictionary_cache(ld->curDictId);
 5710 tgl                       250 ECB             : 
                                251                 :         /*
                                252                 :          * Dictionary ld->curDictId asks us about following words
                                253                 :          */
                                254                 : 
 5710 tgl                       255 GIC         126 :         while (ld->curSub)
 5710 tgl                       256 ECB             :         {
 5710 tgl                       257 GIC          63 :             ParsedLex  *curVal = ld->curSub;
 5710 tgl                       258 ECB             : 
 5710 tgl                       259 GIC          63 :             map = ld->cfg->map + curVal->type;
 5710 tgl                       260 ECB             : 
 5710 tgl                       261 GIC          63 :             if (curVal->type != 0)
 5710 tgl                       262 ECB             :             {
 5710 tgl                       263 GIC          60 :                 bool        dictExists = false;
 5710 tgl                       264 ECB             : 
 5710 tgl                       265 GIC          60 :                 if (curVal->type >= ld->cfg->lenmap || map->len == 0)
 5710 tgl                       266 ECB             :                 {
                                267                 :                     /* skip this type of lexeme */
 5710 tgl                       268 GIC          30 :                     ld->curSub = curVal->next;
 5710 tgl                       269 CBC          30 :                     continue;
 5710 tgl                       270 ECB             :                 }
                                271                 : 
                                272                 :                 /*
                                273                 :                  * We should be sure that current type of lexeme is recognized
                                274                 :                  * by our dictionary: we just check is it exist in list of
                                275                 :                  * dictionaries ?
                                276                 :                  */
 5710 tgl                       277 GIC          90 :                 for (i = 0; i < map->len && !dictExists; i++)
 5710 tgl                       278 CBC          60 :                     if (ld->curDictId == DatumGetObjectId(map->dictIds[i]))
                                279              30 :                         dictExists = true;
 5710 tgl                       280 ECB             : 
 5710 tgl                       281 GIC          30 :                 if (!dictExists)
 5710 tgl                       282 ECB             :                 {
                                283                 :                     /*
                                284                 :                      * Dictionary can't work with current type of lexeme,
                                285                 :                      * return to basic mode and redo all stored lexemes
                                286                 :                      */
 5710 tgl                       287 UIC           0 :                     ld->curDictId = InvalidOid;
 5710 tgl                       288 UBC           0 :                     return LexizeExec(ld, correspondLexem);
 5710 tgl                       289 EUB             :                 }
                                290                 :             }
                                291                 : 
  578 michael                   292 GIC          33 :             ld->dictState.isend = (curVal->type == 0);
 5710 tgl                       293 CBC          33 :             ld->dictState.getnext = false;
 5710 tgl                       294 ECB             : 
 1165 alvherre                  295 GIC          33 :             res = (TSLexeme *) DatumGetPointer(FunctionCall4(&(dict->lexize),
 2118 tgl                       296 ECB             :                                                              PointerGetDatum(dict->dictData),
                                297                 :                                                              PointerGetDatum(curVal->lemm),
                                298                 :                                                              Int32GetDatum(curVal->lenlemm),
                                299                 :                                                              PointerGetDatum(&ld->dictState)));
                                300                 : 
 5710 tgl                       301 GIC          33 :             if (ld->dictState.getnext)
 5710 tgl                       302 ECB             :             {
                                303                 :                 /* Dictionary wants one more */
 5710 tgl                       304 GIC           9 :                 ld->curSub = curVal->next;
 5710 tgl                       305 CBC           9 :                 if (res)
                                306               6 :                     setNewTmpRes(ld, curVal, res);
                                307               9 :                 continue;
 5710 tgl                       308 ECB             :             }
                                309                 : 
 5710 tgl                       310 GIC          24 :             if (res || ld->tmpRes)
 5710 tgl                       311 ECB             :             {
                                312                 :                 /*
                                313                 :                  * Dictionary normalizes lexemes, so we remove from stack all
                                314                 :                  * used lexemes, return to basic mode and redo end of stack
                                315                 :                  * (if it exists)
                                316                 :                  */
 5710 tgl                       317 GIC          24 :                 if (res)
 5710 tgl                       318 ECB             :                 {
 5710 tgl                       319 GIC          12 :                     moveToWaste(ld, ld->curSub);
 5710 tgl                       320 ECB             :                 }
                                321                 :                 else
                                322                 :                 {
 5710 tgl                       323 GIC          12 :                     res = ld->tmpRes;
 5710 tgl                       324 CBC          12 :                     moveToWaste(ld, ld->lastRes);
 5710 tgl                       325 ECB             :                 }
                                326                 : 
                                327                 :                 /* reset to initial state */
 5710 tgl                       328 GIC          24 :                 ld->curDictId = InvalidOid;
 5710 tgl                       329 CBC          24 :                 ld->posDict = 0;
                                330              24 :                 ld->lastRes = NULL;
                                331              24 :                 ld->tmpRes = NULL;
                                332              24 :                 setCorrLex(ld, correspondLexem);
                                333              24 :                 return res;
 5710 tgl                       334 ECB             :             }
                                335                 : 
                                336                 :             /*
                                337                 :              * Dict don't want next lexem and didn't recognize anything, redo
                                338                 :              * from ld->towork.head
                                339                 :              */
 5710 tgl                       340 UIC           0 :             ld->curDictId = InvalidOid;
 5710 tgl                       341 UBC           0 :             return LexizeExec(ld, correspondLexem);
 5710 tgl                       342 EUB             :         }
                                343                 :     }
                                344                 : 
 5710 tgl                       345 GIC       13823 :     setCorrLex(ld, correspondLexem);
 5710 tgl                       346 CBC       13823 :     return NULL;
 5710 tgl                       347 ECB             : }
                                348                 : 
                                349                 : /*
                                350                 :  * Parse string and lexize words.
                                351                 :  *
                                352                 :  * prs will be filled in.
                                353                 :  */
                                354                 : void
 5624 bruce                     355 GIC        2161 : parsetext(Oid cfgId, ParsedText *prs, char *buf, int buflen)
 5710 tgl                       356 ECB             : {
                                357                 :     int         type,
  194 peter                     358 GNC        2161 :                 lenlemm = 0;    /* silence compiler warning */
 5710 tgl                       359 CBC        2161 :     char       *lemm = NULL;
 5710 tgl                       360 ECB             :     LexizeData  ldata;
                                361                 :     TSLexeme   *norms;
                                362                 :     TSConfigCacheEntry *cfg;
                                363                 :     TSParserCacheEntry *prsobj;
                                364                 :     void       *prsdata;
                                365                 : 
 5710 tgl                       366 GIC        2161 :     cfg = lookup_ts_config_cache(cfgId);
 5710 tgl                       367 CBC        2161 :     prsobj = lookup_ts_parser_cache(cfg->prsId);
 5710 tgl                       368 ECB             : 
 5710 tgl                       369 GIC        2161 :     prsdata = (void *) DatumGetPointer(FunctionCall2(&prsobj->prsstart,
 5710 tgl                       370 ECB             :                                                      PointerGetDatum(buf),
                                371                 :                                                      Int32GetDatum(buflen)));
                                372                 : 
 5710 tgl                       373 GIC        2161 :     LexizeInit(&ldata, cfg);
 5710 tgl                       374 ECB             : 
                                375                 :     do
                                376                 :     {
 5710 tgl                       377 GIC        8752 :         type = DatumGetInt32(FunctionCall3(&(prsobj->prstoken),
 5710 tgl                       378 ECB             :                                            PointerGetDatum(prsdata),
                                379                 :                                            PointerGetDatum(&lemm),
                                380                 :                                            PointerGetDatum(&lenlemm)));
                                381                 : 
 5710 tgl                       382 GIC        8752 :         if (type > 0 && lenlemm >= MAXSTRLEN)
 5710 tgl                       383 ECB             :         {
                                384                 : #ifdef IGNORE_LONGLEXEME
 5710 tgl                       385 UIC           0 :             ereport(NOTICE,
 5611 tgl                       386 EUB             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                387                 :                      errmsg("word is too long to be indexed"),
                                388                 :                      errdetail("Words longer than %d characters are ignored.",
                                389                 :                                MAXSTRLEN)));
 5710 tgl                       390 UIC           0 :             continue;
 5710 tgl                       391 EUB             : #else
                                392                 :             ereport(ERROR,
                                393                 :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                394                 :                      errmsg("word is too long to be indexed"),
                                395                 :                      errdetail("Words longer than %d characters are ignored.",
                                396                 :                                MAXSTRLEN)));
                                397                 : #endif
                                398                 :         }
                                399                 : 
 5710 tgl                       400 GIC        8752 :         LexizeAddLemm(&ldata, type, lemm, lenlemm);
 5710 tgl                       401 ECB             : 
 5710 tgl                       402 GIC       13011 :         while ((norms = LexizeExec(&ldata, NULL)) != NULL)
 5710 tgl                       403 ECB             :         {
 5710 tgl                       404 GIC        4259 :             TSLexeme   *ptr = norms;
 5710 tgl                       405 ECB             : 
 5710 tgl                       406 GIC        4259 :             prs->pos++;          /* set pos */
 5710 tgl                       407 ECB             : 
 5710 tgl                       408 GIC        7915 :             while (ptr->lexeme)
 5710 tgl                       409 ECB             :             {
 5710 tgl                       410 GIC        3656 :                 if (prs->curwords == prs->lenwords)
 5710 tgl                       411 ECB             :                 {
 5710 tgl                       412 GIC         166 :                     prs->lenwords *= 2;
   61 peter                     413 GNC         166 :                     prs->words = (ParsedWord *) repalloc(prs->words, prs->lenwords * sizeof(ParsedWord));
 5710 tgl                       414 ECB             :                 }
                                415                 : 
 5710 tgl                       416 GIC        3656 :                 if (ptr->flags & TSL_ADDPOS)
 5710 tgl                       417 CBC          12 :                     prs->pos++;
                                418            3656 :                 prs->words[prs->curwords].len = strlen(ptr->lexeme);
                                419            3656 :                 prs->words[prs->curwords].word = ptr->lexeme;
                                420            3656 :                 prs->words[prs->curwords].nvariant = ptr->nvariant;
 5441                           421            3656 :                 prs->words[prs->curwords].flags = ptr->flags & TSL_PREFIX;
 5710                           422            3656 :                 prs->words[prs->curwords].alen = 0;
                                423            3656 :                 prs->words[prs->curwords].pos.pos = LIMITPOS(prs->pos);
                                424            3656 :                 ptr++;
                                425            3656 :                 prs->curwords++;
 5710 tgl                       426 ECB             :             }
 5710 tgl                       427 GIC        4259 :             pfree(norms);
 5710 tgl                       428 ECB             :         }
 5710 tgl                       429 GIC        8752 :     } while (type > 0);
 5710 tgl                       430 ECB             : 
 5710 tgl                       431 GIC        2161 :     FunctionCall1(&(prsobj->prsend), PointerGetDatum(prsdata));
 5710 tgl                       432 CBC        2161 : }
 5710 tgl                       433 ECB             : 
                                434                 : /*
                                435                 :  * Headline framework
                                436                 :  */
                                437                 : 
                                438                 : /* Add a word to prs->words[] */
                                439                 : static void
 5624 bruce                     440 GIC        4884 : hladdword(HeadlineParsedText *prs, char *buf, int buflen, int type)
 5710 tgl                       441 ECB             : {
  647 drowley                   442 GIC        4884 :     if (prs->curwords >= prs->lenwords)
 5710 tgl                       443 ECB             :     {
 5710 tgl                       444 GIC          27 :         prs->lenwords *= 2;
   61 peter                     445 GNC          27 :         prs->words = (HeadlineWordEntry *) repalloc(prs->words, prs->lenwords * sizeof(HeadlineWordEntry));
 5710 tgl                       446 ECB             :     }
 5706 tgl                       447 GIC        4884 :     memset(&(prs->words[prs->curwords]), 0, sizeof(HeadlineWordEntry));
 5710 tgl                       448 CBC        4884 :     prs->words[prs->curwords].type = (uint8) type;
                                449            4884 :     prs->words[prs->curwords].len = buflen;
                                450            4884 :     prs->words[prs->curwords].word = palloc(buflen);
                                451            4884 :     memcpy(prs->words[prs->curwords].word, buf, buflen);
                                452            4884 :     prs->curwords++;
                                453            4884 : }
 5710 tgl                       454 ECB             : 
                                455                 : /*
                                456                 :  * Add pos and matching-query-item data to the just-added word.
                                457                 :  * Here, buf/buflen represent a processed lexeme, not raw token text.
                                458                 :  *
                                459                 :  * If the query contains more than one matching item, we replicate
                                460                 :  * the last-added word so that each item can be pointed to.  The
                                461                 :  * duplicate entries are marked with repeated = 1.
                                462                 :  */
                                463                 : static void
 2558 teodor                    464 GIC        1574 : hlfinditem(HeadlineParsedText *prs, TSQuery query, int32 pos, char *buf, int buflen)
 5710 tgl                       465 ECB             : {
                                466                 :     int         i;
 5710 tgl                       467 GIC        1574 :     QueryItem  *item = GETQUERY(query);
 5706 tgl                       468 ECB             :     HeadlineWordEntry *word;
                                469                 : 
 5710 tgl                       470 GIC        1640 :     while (prs->curwords + query->size >= prs->lenwords)
 5710 tgl                       471 ECB             :     {
 5710 tgl                       472 GIC          66 :         prs->lenwords *= 2;
   61 peter                     473 GNC          66 :         prs->words = (HeadlineWordEntry *) repalloc(prs->words, prs->lenwords * sizeof(HeadlineWordEntry));
 5710 tgl                       474 ECB             :     }
                                475                 : 
 5710 tgl                       476 GIC        1574 :     word = &(prs->words[prs->curwords - 1]);
 2558 teodor                    477 CBC        1574 :     word->pos = LIMITPOS(pos);
 5710 tgl                       478            7474 :     for (i = 0; i < query->size; i++)
 5710 tgl                       479 ECB             :     {
 5693 teodor                    480 GIC        9556 :         if (item->type == QI_VAL &&
 5015 peter_e                   481 CBC        3656 :             tsCompareString(GETOPERAND(query) + item->qoperand.distance, item->qoperand.length,
                                482            3656 :                             buf, buflen, item->qoperand.prefix) == 0)
 5710 tgl                       483 ECB             :         {
 5710 tgl                       484 GIC         307 :             if (word->item)
 5710 tgl                       485 ECB             :             {
 5706 tgl                       486 UIC           0 :                 memcpy(&(prs->words[prs->curwords]), word, sizeof(HeadlineWordEntry));
 5015 peter_e                   487 UBC           0 :                 prs->words[prs->curwords].item = &item->qoperand;
 5710 tgl                       488               0 :                 prs->words[prs->curwords].repeated = 1;
                                489               0 :                 prs->curwords++;
 5710 tgl                       490 EUB             :             }
                                491                 :             else
 5015 peter_e                   492 GIC         307 :                 word->item = &item->qoperand;
 5710 tgl                       493 ECB             :         }
 5710 tgl                       494 GIC        5900 :         item++;
 5710 tgl                       495 ECB             :     }
 5710 tgl                       496 GIC        1574 : }
 5710 tgl                       497 ECB             : 
                                498                 : static void
 5624 bruce                     499 GIC        7545 : addHLParsedLex(HeadlineParsedText *prs, TSQuery query, ParsedLex *lexs, TSLexeme *norms)
 5710 tgl                       500 ECB             : {
                                501                 :     ParsedLex  *tmplexs;
                                502                 :     TSLexeme   *ptr;
                                503                 :     int32       savedpos;
                                504                 : 
 5710 tgl                       505 GIC       12616 :     while (lexs)
 5710 tgl                       506 ECB             :     {
 5710 tgl                       507 GIC        5071 :         if (lexs->type > 0)
 5710 tgl                       508 CBC        4884 :             hladdword(prs, lexs->lemm, lexs->lenlemm, lexs->type);
 5710 tgl                       509 ECB             : 
 5710 tgl                       510 GIC        5071 :         ptr = norms;
 2558 teodor                    511 CBC        5071 :         savedpos = prs->vectorpos;
 5710 tgl                       512            6645 :         while (ptr && ptr->lexeme)
 5710 tgl                       513 ECB             :         {
 2558 teodor                    514 GIC        1574 :             if (ptr->flags & TSL_ADDPOS)
 2558 teodor                    515 LBC           0 :                 savedpos++;
 2558 teodor                    516 GBC        1574 :             hlfinditem(prs, query, savedpos, ptr->lexeme, strlen(ptr->lexeme));
 5710 tgl                       517 CBC        1574 :             ptr++;
 5710 tgl                       518 ECB             :         }
                                519                 : 
 5710 tgl                       520 GIC        5071 :         tmplexs = lexs->next;
 5710 tgl                       521 CBC        5071 :         pfree(lexs);
                                522            5071 :         lexs = tmplexs;
 5710 tgl                       523 ECB             :     }
                                524                 : 
 5710 tgl                       525 GIC        7545 :     if (norms)
 5710 tgl                       526 ECB             :     {
 5710 tgl                       527 GIC        2474 :         ptr = norms;
 5710 tgl                       528 CBC        4048 :         while (ptr->lexeme)
 5710 tgl                       529 ECB             :         {
 2558 teodor                    530 GIC        1574 :             if (ptr->flags & TSL_ADDPOS)
 2558 teodor                    531 LBC           0 :                 prs->vectorpos++;
 5710 tgl                       532 GBC        1574 :             pfree(ptr->lexeme);
 5710 tgl                       533 CBC        1574 :             ptr++;
 5710 tgl                       534 ECB             :         }
 5710 tgl                       535 GIC        2474 :         pfree(norms);
 5710 tgl                       536 ECB             :     }
 5710 tgl                       537 GIC        7545 : }
 5710 tgl                       538 ECB             : 
                                539                 : void
 5624 bruce                     540 GIC         187 : hlparsetext(Oid cfgId, HeadlineParsedText *prs, TSQuery query, char *buf, int buflen)
 5710 tgl                       541 ECB             : {
                                542                 :     int         type,
  194 peter                     543 GNC         187 :                 lenlemm = 0;    /* silence compiler warning */
 5710 tgl                       544 CBC         187 :     char       *lemm = NULL;
 5710 tgl                       545 ECB             :     LexizeData  ldata;
                                546                 :     TSLexeme   *norms;
                                547                 :     ParsedLex  *lexs;
                                548                 :     TSConfigCacheEntry *cfg;
                                549                 :     TSParserCacheEntry *prsobj;
                                550                 :     void       *prsdata;
                                551                 : 
 5710 tgl                       552 GIC         187 :     cfg = lookup_ts_config_cache(cfgId);
 5710 tgl                       553 CBC         187 :     prsobj = lookup_ts_parser_cache(cfg->prsId);
 5710 tgl                       554 ECB             : 
 5710 tgl                       555 GIC         187 :     prsdata = (void *) DatumGetPointer(FunctionCall2(&(prsobj->prsstart),
 5710 tgl                       556 ECB             :                                                      PointerGetDatum(buf),
                                557                 :                                                      Int32GetDatum(buflen)));
                                558                 : 
 5710 tgl                       559 GIC         187 :     LexizeInit(&ldata, cfg);
 5710 tgl                       560 ECB             : 
                                561                 :     do
                                562                 :     {
 5710 tgl                       563 GIC        5071 :         type = DatumGetInt32(FunctionCall3(&(prsobj->prstoken),
 5710 tgl                       564 ECB             :                                            PointerGetDatum(prsdata),
                                565                 :                                            PointerGetDatum(&lemm),
                                566                 :                                            PointerGetDatum(&lenlemm)));
                                567                 : 
 5710 tgl                       568 GIC        5071 :         if (type > 0 && lenlemm >= MAXSTRLEN)
 5710 tgl                       569 ECB             :         {
                                570                 : #ifdef IGNORE_LONGLEXEME
 5710 tgl                       571 UIC           0 :             ereport(NOTICE,
 5611 tgl                       572 EUB             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                573                 :                      errmsg("word is too long to be indexed"),
                                574                 :                      errdetail("Words longer than %d characters are ignored.",
                                575                 :                                MAXSTRLEN)));
 5710 tgl                       576 UIC           0 :             continue;
 5710 tgl                       577 EUB             : #else
                                578                 :             ereport(ERROR,
                                579                 :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                580                 :                      errmsg("word is too long to be indexed"),
                                581                 :                      errdetail("Words longer than %d characters are ignored.",
                                582                 :                                MAXSTRLEN)));
                                583                 : #endif
                                584                 :         }
                                585                 : 
 5710 tgl                       586 GIC        5071 :         LexizeAddLemm(&ldata, type, lemm, lenlemm);
 5710 tgl                       587 ECB             : 
                                588                 :         do
                                589                 :         {
 5710 tgl                       590 GIC        7545 :             if ((norms = LexizeExec(&ldata, &lexs)) != NULL)
 2558 teodor                    591 ECB             :             {
 2558 teodor                    592 GIC        2474 :                 prs->vectorpos++;
 5710 tgl                       593 CBC        2474 :                 addHLParsedLex(prs, query, lexs, norms);
 2558 teodor                    594 ECB             :             }
                                595                 :             else
 5710 tgl                       596 GIC        5071 :                 addHLParsedLex(prs, query, lexs, NULL);
 5710 tgl                       597 CBC        7545 :         } while (norms);
                                598            5071 :     } while (type > 0);
 5710 tgl                       599 ECB             : 
 5710 tgl                       600 GIC         187 :     FunctionCall1(&(prsobj->prsend), PointerGetDatum(prsdata));
 5710 tgl                       601 CBC         187 : }
 5710 tgl                       602 ECB             : 
                                603                 : /*
                                604                 :  * Generate the headline, as a text object, from HeadlineParsedText.
                                605                 :  */
                                606                 : text *
 5624 bruce                     607 GIC         187 : generateHeadline(HeadlineParsedText *prs)
 5710 tgl                       608 ECB             : {
                                609                 :     text       *out;
                                610                 :     char       *ptr;
 5050 bruce                     611 GIC         187 :     int         len = 128;
 5050 bruce                     612 CBC         187 :     int         numfragments = 0;
 3940 peter_e                   613             187 :     int16       infrag = 0;
 5287 teodor                    614 ECB             : 
 5706 tgl                       615 GIC         187 :     HeadlineWordEntry *wrd = prs->words;
 5710 tgl                       616 ECB             : 
 5710 tgl                       617 GIC         187 :     out = (text *) palloc(len);
 5710 tgl                       618 CBC         187 :     ptr = ((char *) out) + VARHDRSZ;
 5710 tgl                       619 ECB             : 
 5710 tgl                       620 GIC        5071 :     while (wrd - prs->words < prs->curwords)
 5710 tgl                       621 ECB             :     {
 5287 teodor                    622 GIC        4932 :         while (wrd->len + prs->stopsellen + prs->startsellen + prs->fragdelimlen + (ptr - ((char *) out)) >= len)
 5710 tgl                       623 ECB             :         {
 5710 tgl                       624 GIC          48 :             int         dist = ptr - ((char *) out);
 5710 tgl                       625 ECB             : 
 5710 tgl                       626 GIC          48 :             len *= 2;
 5710 tgl                       627 CBC          48 :             out = (text *) repalloc(out, len);
                                628              48 :             ptr = ((char *) out) + dist;
 5710 tgl                       629 ECB             :         }
                                630                 : 
 5710 tgl                       631 GIC        4884 :         if (wrd->in && !wrd->repeated)
 5710 tgl                       632 ECB             :         {
 5287 teodor                    633 GIC        2634 :             if (!infrag)
 5287 teodor                    634 ECB             :             {
                                635                 : 
                                636                 :                 /* start of a new fragment */
 5287 teodor                    637 GIC         190 :                 infrag = 1;
 5050 bruce                     638 CBC         190 :                 numfragments++;
 2253 heikki.linnakangas        639 ECB             :                 /* add a fragment delimiter if this is after the first one */
 5287 teodor                    640 GIC         190 :                 if (numfragments > 1)
 5287 teodor                    641 ECB             :                 {
 5287 teodor                    642 GIC           6 :                     memcpy(ptr, prs->fragdelim, prs->fragdelimlen);
 5287 teodor                    643 CBC           6 :                     ptr += prs->fragdelimlen;
 5050 bruce                     644 ECB             :                 }
                                645                 :             }
 5710 tgl                       646 GIC        2634 :             if (wrd->replace)
 5710 tgl                       647 ECB             :             {
 5710 tgl                       648 UIC           0 :                 *ptr = ' ';
 5710 tgl                       649 UBC           0 :                 ptr++;
 5710 tgl                       650 EUB             :             }
 5197 teodor                    651 GIC        2634 :             else if (!wrd->skip)
 5710 tgl                       652 ECB             :             {
 5710 tgl                       653 GIC        2631 :                 if (wrd->selected)
 5710 tgl                       654 ECB             :                 {
 5710 tgl                       655 GIC         250 :                     memcpy(ptr, prs->startsel, prs->startsellen);
 5710 tgl                       656 CBC         250 :                     ptr += prs->startsellen;
 5710 tgl                       657 ECB             :                 }
 5710 tgl                       658 GIC        2631 :                 memcpy(ptr, wrd->word, wrd->len);
 5710 tgl                       659 CBC        2631 :                 ptr += wrd->len;
                                660            2631 :                 if (wrd->selected)
 5710 tgl                       661 ECB             :                 {
 5710 tgl                       662 GIC         250 :                     memcpy(ptr, prs->stopsel, prs->stopsellen);
 5710 tgl                       663 CBC         250 :                     ptr += prs->stopsellen;
 5710 tgl                       664 ECB             :                 }
                                665                 :             }
                                666                 :         }
 5710 tgl                       667 GIC        2250 :         else if (!wrd->repeated)
 5287 teodor                    668 ECB             :         {
 5287 teodor                    669 GIC        2250 :             if (infrag)
 5287 teodor                    670 CBC          60 :                 infrag = 0;
 5710 tgl                       671            2250 :             pfree(wrd->word);
 5050 bruce                     672 ECB             :         }
                                673                 : 
 5710 tgl                       674 GIC        4884 :         wrd++;
 5710 tgl                       675 ECB             :     }
                                676                 : 
 5710 tgl                       677 GIC         187 :     SET_VARSIZE(out, ptr - ((char *) out));
 5710 tgl                       678 CBC         187 :     return out;
 5710 tgl                       679 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a