LCOV - differential code coverage report
Current view: top level - src/backend/tsearch - to_tsany.c (source / functions) Coverage Total Hit UIC UBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 96.8 % 282 273 3 6 26 1 246 3 25 2
Current Date: 2023-04-08 17:13:01 Functions: 92.3 % 26 24 1 1 6 2 16 1 6
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (240..) days: 96.8 % 281 272 3 6 26 246 3 24
Function coverage date bins:
(240..) days: 72.7 % 33 24 1 1 6 2 16 1 6

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * to_tsany.c
                                  4                 :  *      to_ts* function definitions
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :  *
                                  8                 :  *
                                  9                 :  * IDENTIFICATION
                                 10                 :  *    src/backend/tsearch/to_tsany.c
                                 11                 :  *
                                 12                 :  *-------------------------------------------------------------------------
                                 13                 :  */
                                 14                 : #include "postgres.h"
                                 15                 : 
                                 16                 : #include "common/jsonapi.h"
                                 17                 : #include "tsearch/ts_cache.h"
                                 18                 : #include "tsearch/ts_utils.h"
                                 19                 : #include "utils/builtins.h"
                                 20                 : #include "utils/jsonfuncs.h"
                                 21                 : 
                                 22                 : 
                                 23                 : /*
                                 24                 :  * Opaque data structure, which is passed by parse_tsquery() to pushval_morph().
                                 25                 :  */
                                 26                 : typedef struct MorphOpaque
                                 27                 : {
                                 28                 :     Oid         cfg_id;
                                 29                 : 
                                 30                 :     /*
                                 31                 :      * Single tsquery morph could be parsed into multiple words.  When these
                                 32                 :      * words reside in adjacent positions, they are connected using this
                                 33                 :      * operator.  Usually, that is OP_PHRASE, which requires word positions of
                                 34                 :      * a complex morph to exactly match the tsvector.
                                 35                 :      */
                                 36                 :     int         qoperator;
                                 37                 : } MorphOpaque;
                                 38                 : 
                                 39                 : typedef struct TSVectorBuildState
                                 40                 : {
                                 41                 :     ParsedText *prs;
                                 42                 :     Oid         cfgId;
                                 43                 : } TSVectorBuildState;
                                 44                 : 
                                 45                 : static void add_to_tsvector(void *_state, char *elem_value, int elem_len);
                                 46                 : 
                                 47                 : 
                                 48                 : Datum
 5710 tgl                        49 UBC           0 : get_current_ts_config(PG_FUNCTION_ARGS)
                                 50                 : {
                                 51               0 :     PG_RETURN_OID(getTSCurrentConfig(true));
                                 52                 : }
                                 53                 : 
                                 54                 : /*
                                 55                 :  * to_tsvector
                                 56                 :  */
                                 57                 : static int
 5710 tgl                        58 CBC        6229 : compareWORD(const void *a, const void *b)
                                 59                 : {
                                 60                 :     int         res;
                                 61                 : 
 1165 alvherre                   62            6229 :     res = tsCompareString(((const ParsedWord *) a)->word, ((const ParsedWord *) a)->len,
 2118 tgl                        63            6229 :                           ((const ParsedWord *) b)->word, ((const ParsedWord *) b)->len,
                                 64                 :                           false);
                                 65                 : 
 5441                            66            6229 :     if (res == 0)
                                 67                 :     {
 4228 peter_e                    68             525 :         if (((const ParsedWord *) a)->pos.pos == ((const ParsedWord *) b)->pos.pos)
 5441 tgl                        69              12 :             return 0;
                                 70                 : 
 4228 peter_e                    71             513 :         res = (((const ParsedWord *) a)->pos.pos > ((const ParsedWord *) b)->pos.pos) ? 1 : -1;
                                 72                 :     }
                                 73                 : 
 5441 tgl                        74            6217 :     return res;
                                 75                 : }
                                 76                 : 
                                 77                 : static int
 3940 peter_e                    78             338 : uniqueWORD(ParsedWord *a, int32 l)
                                 79                 : {
                                 80                 :     ParsedWord *ptr,
                                 81                 :                *res;
                                 82                 :     int         tmppos;
                                 83                 : 
 5710 tgl                        84             338 :     if (l == 1)
                                 85                 :     {
                                 86              13 :         tmppos = LIMITPOS(a->pos.pos);
                                 87              13 :         a->alen = 2;
                                 88              13 :         a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen);
                                 89              13 :         a->pos.apos[0] = 1;
                                 90              13 :         a->pos.apos[1] = tmppos;
                                 91              13 :         return l;
                                 92                 :     }
                                 93                 : 
                                 94             325 :     res = a;
                                 95             325 :     ptr = a + 1;
                                 96                 : 
                                 97                 :     /*
                                 98                 :      * Sort words with its positions
                                 99                 :      */
   61 peter                     100 GNC         325 :     qsort(a, l, sizeof(ParsedWord), compareWORD);
                                101                 : 
                                102                 :     /*
                                103                 :      * Initialize first word and its first position
                                104                 :      */
 5710 tgl                       105 CBC         325 :     tmppos = LIMITPOS(a->pos.pos);
                                106             325 :     a->alen = 2;
                                107             325 :     a->pos.apos = (uint16 *) palloc(sizeof(uint16) * a->alen);
                                108             325 :     a->pos.apos[0] = 1;
                                109             325 :     a->pos.apos[1] = tmppos;
                                110                 : 
                                111                 :     /*
                                112                 :      * Summarize position information for each word
                                113                 :      */
                                114            2096 :     while (ptr - a < l)
                                115                 :     {
                                116            1771 :         if (!(ptr->len == res->len &&
                                117            1015 :               strncmp(ptr->word, res->word, res->len) == 0))
                                118                 :         {
                                119                 :             /*
                                120                 :              * Got a new word, so put it in result
                                121                 :              */
                                122            1444 :             res++;
                                123            1444 :             res->len = ptr->len;
                                124            1444 :             res->word = ptr->word;
                                125            1444 :             tmppos = LIMITPOS(ptr->pos.pos);
                                126            1444 :             res->alen = 2;
                                127            1444 :             res->pos.apos = (uint16 *) palloc(sizeof(uint16) * res->alen);
                                128            1444 :             res->pos.apos[0] = 1;
                                129            1444 :             res->pos.apos[1] = tmppos;
                                130                 :         }
                                131                 :         else
                                132                 :         {
                                133                 :             /*
                                134                 :              * The word already exists, so adjust position information. But
                                135                 :              * before we should check size of position's array, max allowed
                                136                 :              * value for position and uniqueness of position
                                137                 :              */
                                138             327 :             pfree(ptr->word);
 5674 teodor                    139             327 :             if (res->pos.apos[0] < MAXNUMPOS - 1 && res->pos.apos[res->pos.apos[0]] != MAXENTRYPOS - 1 &&
 5624 bruce                     140             327 :                 res->pos.apos[res->pos.apos[0]] != LIMITPOS(ptr->pos.pos))
                                141                 :             {
 5710 tgl                       142             315 :                 if (res->pos.apos[0] + 1 >= res->alen)
                                143                 :                 {
                                144             252 :                     res->alen *= 2;
                                145             252 :                     res->pos.apos = (uint16 *) repalloc(res->pos.apos, sizeof(uint16) * res->alen);
                                146                 :                 }
                                147             315 :                 if (res->pos.apos[0] == 0 || res->pos.apos[res->pos.apos[0]] != LIMITPOS(ptr->pos.pos))
                                148                 :                 {
                                149             315 :                     res->pos.apos[res->pos.apos[0] + 1] = LIMITPOS(ptr->pos.pos);
                                150             315 :                     res->pos.apos[0]++;
                                151                 :                 }
                                152                 :             }
                                153                 :         }
                                154            1771 :         ptr++;
                                155                 :     }
                                156                 : 
                                157             325 :     return res + 1 - a;
                                158                 : }
                                159                 : 
                                160                 : /*
                                161                 :  * make value of tsvector, given parsed text
                                162                 :  *
                                163                 :  * Note: frees prs->words and subsidiary data.
                                164                 :  */
                                165                 : TSVector
 5624 bruce                     166             398 : make_tsvector(ParsedText *prs)
                                167                 : {
                                168                 :     int         i,
                                169                 :                 j,
 5710 tgl                       170             398 :                 lenstr = 0,
                                171                 :                 totallen;
                                172                 :     TSVector    in;
                                173                 :     WordEntry  *ptr;
                                174                 :     char       *str;
                                175                 :     int         stroff;
                                176                 : 
                                177                 :     /* Merge duplicate words */
 2091                           178             398 :     if (prs->curwords > 0)
                                179             338 :         prs->curwords = uniqueWORD(prs->words, prs->curwords);
                                180                 : 
                                181                 :     /* Determine space needed */
 5710                           182            2180 :     for (i = 0; i < prs->curwords; i++)
                                183                 :     {
 5647                           184            1782 :         lenstr += prs->words[i].len;
 5710                           185            1782 :         if (prs->words[i].alen)
                                186                 :         {
 5647                           187            1782 :             lenstr = SHORTALIGN(lenstr);
 5710                           188            1782 :             lenstr += sizeof(uint16) + prs->words[i].pos.apos[0] * sizeof(WordEntryPos);
                                189                 :         }
                                190                 :     }
                                191                 : 
 5647                           192             398 :     if (lenstr > MAXSTRPOS)
 5647 tgl                       193 UBC           0 :         ereport(ERROR,
                                194                 :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                195                 :                  errmsg("string is too long for tsvector (%d bytes, max %d bytes)", lenstr, MAXSTRPOS)));
                                196                 : 
 5710 tgl                       197 CBC         398 :     totallen = CALCDATASIZE(prs->curwords, lenstr);
                                198             398 :     in = (TSVector) palloc0(totallen);
                                199             398 :     SET_VARSIZE(in, totallen);
                                200             398 :     in->size = prs->curwords;
                                201                 : 
                                202             398 :     ptr = ARRPTR(in);
 5647                           203             398 :     str = STRPTR(in);
                                204             398 :     stroff = 0;
 5710                           205            2180 :     for (i = 0; i < prs->curwords; i++)
                                206                 :     {
                                207            1782 :         ptr->len = prs->words[i].len;
 5647                           208            1782 :         ptr->pos = stroff;
                                209            1782 :         memcpy(str + stroff, prs->words[i].word, prs->words[i].len);
                                210            1782 :         stroff += prs->words[i].len;
 5710                           211            1782 :         pfree(prs->words[i].word);
                                212            1782 :         if (prs->words[i].alen)
                                213                 :         {
 5624 bruce                     214            1782 :             int         k = prs->words[i].pos.apos[0];
                                215                 :             WordEntryPos *wptr;
                                216                 : 
 5647 tgl                       217            1782 :             if (k > 0xFFFF)
 5647 tgl                       218 UBC           0 :                 elog(ERROR, "positions array too long");
                                219                 : 
 5710 tgl                       220 CBC        1782 :             ptr->haspos = 1;
 5647                           221            1782 :             stroff = SHORTALIGN(stroff);
                                222            1782 :             *(uint16 *) (str + stroff) = (uint16) k;
 5710                           223            1782 :             wptr = POSDATAPTR(in, ptr);
 5647                           224            3879 :             for (j = 0; j < k; j++)
                                225                 :             {
 5710                           226            2097 :                 WEP_SETWEIGHT(wptr[j], 0);
                                227            2097 :                 WEP_SETPOS(wptr[j], prs->words[i].pos.apos[j + 1]);
                                228                 :             }
 5647                           229            1782 :             stroff += sizeof(uint16) + k * sizeof(WordEntryPos);
 5710                           230            1782 :             pfree(prs->words[i].pos.apos);
                                231                 :         }
                                232                 :         else
 5710 tgl                       233 UBC           0 :             ptr->haspos = 0;
 5710 tgl                       234 CBC        1782 :         ptr++;
                                235                 :     }
                                236                 : 
 2091                           237             398 :     if (prs->words)
                                238             356 :         pfree(prs->words);
                                239                 : 
 5710                           240             398 :     return in;
                                241                 : }
                                242                 : 
                                243                 : Datum
                                244             239 : to_tsvector_byid(PG_FUNCTION_ARGS)
                                245                 : {
                                246             239 :     Oid         cfgId = PG_GETARG_OID(0);
 2219 noah                      247             239 :     text       *in = PG_GETARG_TEXT_PP(1);
                                248                 :     ParsedText  prs;
                                249                 :     TSVector    out;
                                250                 : 
                                251             239 :     prs.lenwords = VARSIZE_ANY_EXHDR(in) / 6;   /* just estimation of word's
                                252                 :                                                  * number */
 2091 tgl                       253             239 :     if (prs.lenwords < 2)
 5710                           254             169 :         prs.lenwords = 2;
                                255             239 :     prs.curwords = 0;
                                256             239 :     prs.pos = 0;
                                257             239 :     prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);
                                258                 : 
 2219 noah                      259             239 :     parsetext(cfgId, &prs, VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in));
                                260                 : 
 5710 tgl                       261             239 :     PG_FREE_IF_COPY(in, 1);
                                262                 : 
 2091                           263             239 :     out = make_tsvector(&prs);
                                264                 : 
                                265             239 :     PG_RETURN_TSVECTOR(out);
                                266                 : }
                                267                 : 
                                268                 : Datum
 5710                           269              27 : to_tsvector(PG_FUNCTION_ARGS)
                                270                 : {
 2219 noah                      271              27 :     text       *in = PG_GETARG_TEXT_PP(0);
                                272                 :     Oid         cfgId;
                                273                 : 
 5710 tgl                       274              27 :     cfgId = getTSCurrentConfig(true);
                                275              27 :     PG_RETURN_DATUM(DirectFunctionCall2(to_tsvector_byid,
                                276                 :                                         ObjectIdGetDatum(cfgId),
                                277                 :                                         PointerGetDatum(in)));
                                278                 : }
                                279                 : 
                                280                 : /*
                                281                 :  * Worker function for jsonb(_string)_to_tsvector(_byid)
                                282                 :  */
                                283                 : static TSVector
 1828 teodor                    284              75 : jsonb_to_tsvector_worker(Oid cfgId, Jsonb *jb, uint32 flags)
                                285                 : {
                                286                 :     TSVectorBuildState state;
                                287                 :     ParsedText  prs;
                                288                 : 
 2091 tgl                       289              75 :     prs.words = NULL;
                                290              75 :     prs.curwords = 0;
                                291              75 :     state.prs = &prs;
 2200 andrew                    292              75 :     state.cfgId = cfgId;
                                293                 : 
 1828 teodor                    294              75 :     iterate_jsonb_values(jb, flags, &state, add_to_tsvector);
                                295                 : 
                                296              75 :     return make_tsvector(&prs);
                                297                 : }
                                298                 : 
                                299                 : Datum
                                300               9 : jsonb_string_to_tsvector_byid(PG_FUNCTION_ARGS)
                                301                 : {
                                302               9 :     Oid         cfgId = PG_GETARG_OID(0);
                                303               9 :     Jsonb      *jb = PG_GETARG_JSONB_P(1);
                                304                 :     TSVector    result;
                                305                 : 
                                306               9 :     result = jsonb_to_tsvector_worker(cfgId, jb, jtiString);
                                307               9 :     PG_FREE_IF_COPY(jb, 1);
                                308                 : 
 2091 tgl                       309               9 :     PG_RETURN_TSVECTOR(result);
                                310                 : }
                                311                 : 
                                312                 : Datum
 1828 teodor                    313              15 : jsonb_string_to_tsvector(PG_FUNCTION_ARGS)
                                314                 : {
 2029 tgl                       315              15 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
                                316                 :     Oid         cfgId;
                                317                 :     TSVector    result;
                                318                 : 
 2200 andrew                    319              15 :     cfgId = getTSCurrentConfig(true);
 1828 teodor                    320              15 :     result = jsonb_to_tsvector_worker(cfgId, jb, jtiString);
                                321              15 :     PG_FREE_IF_COPY(jb, 0);
                                322                 : 
                                323              15 :     PG_RETURN_TSVECTOR(result);
                                324                 : }
                                325                 : 
                                326                 : Datum
                                327              51 : jsonb_to_tsvector_byid(PG_FUNCTION_ARGS)
                                328                 : {
 2153 bruce                     329              51 :     Oid         cfgId = PG_GETARG_OID(0);
 1828 teodor                    330              51 :     Jsonb      *jb = PG_GETARG_JSONB_P(1);
                                331              51 :     Jsonb      *jbFlags = PG_GETARG_JSONB_P(2);
                                332                 :     TSVector    result;
                                333              51 :     uint32      flags = parse_jsonb_index_flags(jbFlags);
                                334                 : 
                                335              39 :     result = jsonb_to_tsvector_worker(cfgId, jb, flags);
                                336              39 :     PG_FREE_IF_COPY(jb, 1);
                                337              39 :     PG_FREE_IF_COPY(jbFlags, 2);
                                338                 : 
                                339              39 :     PG_RETURN_TSVECTOR(result);
                                340                 : }
                                341                 : 
                                342                 : Datum
                                343              12 : jsonb_to_tsvector(PG_FUNCTION_ARGS)
                                344                 : {
                                345              12 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
                                346              12 :     Jsonb      *jbFlags = PG_GETARG_JSONB_P(1);
                                347                 :     Oid         cfgId;
                                348                 :     TSVector    result;
                                349              12 :     uint32      flags = parse_jsonb_index_flags(jbFlags);
                                350                 : 
                                351              12 :     cfgId = getTSCurrentConfig(true);
                                352              12 :     result = jsonb_to_tsvector_worker(cfgId, jb, flags);
                                353              12 :     PG_FREE_IF_COPY(jb, 0);
                                354              12 :     PG_FREE_IF_COPY(jbFlags, 1);
                                355                 : 
                                356              12 :     PG_RETURN_TSVECTOR(result);
                                357                 : }
                                358                 : 
                                359                 : /*
                                360                 :  * Worker function for json(_string)_to_tsvector(_byid)
                                361                 :  */
                                362                 : static TSVector
                                363              75 : json_to_tsvector_worker(Oid cfgId, text *json, uint32 flags)
                                364                 : {
                                365                 :     TSVectorBuildState state;
                                366                 :     ParsedText  prs;
                                367                 : 
 2091 tgl                       368              75 :     prs.words = NULL;
                                369              75 :     prs.curwords = 0;
                                370              75 :     state.prs = &prs;
 2200 andrew                    371              75 :     state.cfgId = cfgId;
                                372                 : 
 1828 teodor                    373              75 :     iterate_json_values(json, flags, &state, add_to_tsvector);
                                374                 : 
                                375              75 :     return make_tsvector(&prs);
                                376                 : }
                                377                 : 
                                378                 : Datum
                                379               9 : json_string_to_tsvector_byid(PG_FUNCTION_ARGS)
                                380                 : {
                                381               9 :     Oid         cfgId = PG_GETARG_OID(0);
                                382               9 :     text       *json = PG_GETARG_TEXT_P(1);
                                383                 :     TSVector    result;
                                384                 : 
                                385               9 :     result = json_to_tsvector_worker(cfgId, json, jtiString);
 2091 tgl                       386               9 :     PG_FREE_IF_COPY(json, 1);
                                387                 : 
 1828 teodor                    388               9 :     PG_RETURN_TSVECTOR(result);
                                389                 : }
                                390                 : 
                                391                 : Datum
                                392              15 : json_string_to_tsvector(PG_FUNCTION_ARGS)
                                393                 : {
                                394              15 :     text       *json = PG_GETARG_TEXT_P(0);
                                395                 :     Oid         cfgId;
                                396                 :     TSVector    result;
                                397                 : 
                                398              15 :     cfgId = getTSCurrentConfig(true);
                                399              15 :     result = json_to_tsvector_worker(cfgId, json, jtiString);
                                400              15 :     PG_FREE_IF_COPY(json, 0);
                                401                 : 
                                402              15 :     PG_RETURN_TSVECTOR(result);
                                403                 : }
                                404                 : 
                                405                 : Datum
                                406              51 : json_to_tsvector_byid(PG_FUNCTION_ARGS)
                                407                 : {
                                408              51 :     Oid         cfgId = PG_GETARG_OID(0);
                                409              51 :     text       *json = PG_GETARG_TEXT_P(1);
                                410              51 :     Jsonb      *jbFlags = PG_GETARG_JSONB_P(2);
                                411                 :     TSVector    result;
                                412              51 :     uint32      flags = parse_jsonb_index_flags(jbFlags);
                                413                 : 
                                414              39 :     result = json_to_tsvector_worker(cfgId, json, flags);
                                415              39 :     PG_FREE_IF_COPY(json, 1);
                                416              39 :     PG_FREE_IF_COPY(jbFlags, 2);
                                417                 : 
 2091 tgl                       418              39 :     PG_RETURN_TSVECTOR(result);
                                419                 : }
                                420                 : 
                                421                 : Datum
 2200 andrew                    422              12 : json_to_tsvector(PG_FUNCTION_ARGS)
                                423                 : {
 2153 bruce                     424              12 :     text       *json = PG_GETARG_TEXT_P(0);
 1828 teodor                    425              12 :     Jsonb      *jbFlags = PG_GETARG_JSONB_P(1);
                                426                 :     Oid         cfgId;
                                427                 :     TSVector    result;
                                428              12 :     uint32      flags = parse_jsonb_index_flags(jbFlags);
                                429                 : 
 2200 andrew                    430              12 :     cfgId = getTSCurrentConfig(true);
 1828 teodor                    431              12 :     result = json_to_tsvector_worker(cfgId, json, flags);
                                432              12 :     PG_FREE_IF_COPY(json, 0);
                                433              12 :     PG_FREE_IF_COPY(jbFlags, 1);
                                434                 : 
                                435              12 :     PG_RETURN_TSVECTOR(result);
                                436                 : }
                                437                 : 
                                438                 : /*
                                439                 :  * Parse lexemes in an element of a json(b) value, add to TSVectorBuildState.
                                440                 :  */
                                441                 : static void
 2200 andrew                    442             372 : add_to_tsvector(void *_state, char *elem_value, int elem_len)
                                443                 : {
                                444             372 :     TSVectorBuildState *state = (TSVectorBuildState *) _state;
 2153 bruce                     445             372 :     ParsedText *prs = state->prs;
                                446                 :     int32       prevwords;
                                447                 : 
 2091 tgl                       448             372 :     if (prs->words == NULL)
                                449                 :     {
                                450                 :         /*
                                451                 :          * First time through: initialize words array to a reasonable size.
                                452                 :          * (parsetext() will realloc it bigger as needed.)
                                453                 :          */
 1828 teodor                    454             108 :         prs->lenwords = 16;
 2091 tgl                       455             108 :         prs->words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs->lenwords);
                                456             108 :         prs->curwords = 0;
                                457             108 :         prs->pos = 0;
                                458                 :     }
                                459                 : 
                                460             372 :     prevwords = prs->curwords;
                                461                 : 
 2200 andrew                    462             372 :     parsetext(state->cfgId, prs, elem_value, elem_len);
                                463                 : 
                                464                 :     /*
                                465                 :      * If we extracted any words from this JSON element, advance pos to create
                                466                 :      * an artificial break between elements.  This is because we don't want
                                467                 :      * phrase searches to think that the last word in this element is adjacent
                                468                 :      * to the first word in the next one.
                                469                 :      */
 2091 tgl                       470             372 :     if (prs->curwords > prevwords)
                                471             336 :         prs->pos += 1;
 2200 andrew                    472             372 : }
                                473                 : 
                                474                 : 
                                475                 : /*
                                476                 :  * to_tsquery
                                477                 :  */
                                478                 : 
                                479                 : 
                                480                 : /*
                                481                 :  * This function is used for morph parsing.
                                482                 :  *
                                483                 :  * The value is passed to parsetext which will call the right dictionary to
                                484                 :  * lexize the word. If it turns out to be a stopword, we push a QI_VALSTOP
                                485                 :  * to the stack.
                                486                 :  *
                                487                 :  * All words belonging to the same variant are pushed as an ANDed list,
                                488                 :  * and different variants are ORed together.
                                489                 :  */
                                490                 : static void
 3940 peter_e                   491            1544 : pushval_morph(Datum opaque, TSQueryParserState state, char *strval, int lenval, int16 weight, bool prefix)
                                492                 : {
 2495 rhaas                     493            1544 :     int32       count = 0;
                                494                 :     ParsedText  prs;
                                495                 :     uint32      variant,
                                496            1544 :                 pos = 0,
                                497            1544 :                 cntvar = 0,
                                498            1544 :                 cntpos = 0,
                                499            1544 :                 cnt = 0;
                                500            1544 :     MorphOpaque *data = (MorphOpaque *) DatumGetPointer(opaque);
                                501                 : 
 5710 tgl                       502            1544 :     prs.lenwords = 4;
                                503            1544 :     prs.curwords = 0;
                                504            1544 :     prs.pos = 0;
                                505            1544 :     prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords);
                                506                 : 
 2558 teodor                    507            1544 :     parsetext(data->cfg_id, &prs, strval, lenval);
                                508                 : 
 5710 tgl                       509            1544 :     if (prs.curwords > 0)
                                510                 :     {
                                511            2674 :         while (count < prs.curwords)
                                512                 :         {
                                513                 :             /*
                                514                 :              * Were any stop words removed? If so, fill empty positions with
                                515                 :              * placeholders linked by an appropriate operator.
                                516                 :              */
 2558 teodor                    517            1439 :             if (pos > 0 && pos + 1 < prs.words[count].pos.pos)
                                518                 :             {
                                519              39 :                 while (pos + 1 < prs.words[count].pos.pos)
                                520                 :                 {
                                521                 :                     /* put placeholders for each missing stop word */
                                522              24 :                     pushStop(state);
                                523              24 :                     if (cntpos)
                                524              24 :                         pushOperator(state, data->qoperator, 1);
                                525              24 :                     cntpos++;
                                526              24 :                     pos++;
                                527                 :                 }
                                528                 :             }
                                529                 : 
                                530                 :             /* save current word's position */
 2532 rhaas                     531            1439 :             pos = prs.words[count].pos.pos;
                                532                 : 
                                533                 :             /* Go through all variants obtained from this token */
 5710 tgl                       534            1439 :             cntvar = 0;
                                535            2914 :             while (count < prs.curwords && pos == prs.words[count].pos.pos)
                                536                 :             {
                                537            1475 :                 variant = prs.words[count].nvariant;
                                538                 : 
                                539                 :                 /* Push all words belonging to the same variant */
                                540            1475 :                 cnt = 0;
 2558 teodor                    541            1475 :                 while (count < prs.curwords &&
                                542            3022 :                        pos == prs.words[count].pos.pos &&
                                543            1583 :                        variant == prs.words[count].nvariant)
                                544                 :                 {
                                545            1547 :                     pushValue(state,
                                546            1547 :                               prs.words[count].word,
                                547            1547 :                               prs.words[count].len,
                                548                 :                               weight,
 2118 tgl                       549            1547 :                               ((prs.words[count].flags & TSL_PREFIX) || prefix));
 5710                           550            1547 :                     pfree(prs.words[count].word);
                                551            1547 :                     if (cnt)
 2558 teodor                    552              72 :                         pushOperator(state, OP_AND, 0);
 5710 tgl                       553            1547 :                     cnt++;
                                554            1547 :                     count++;
                                555                 :                 }
                                556                 : 
                                557            1475 :                 if (cntvar)
 2558 teodor                    558              36 :                     pushOperator(state, OP_OR, 0);
 5710 tgl                       559            1475 :                 cntvar++;
                                560                 :             }
                                561                 : 
                                562            1439 :             if (cntpos)
                                563                 :             {
                                564                 :                 /* distance may be useful */
 2532 rhaas                     565             204 :                 pushOperator(state, data->qoperator, 1);
                                566                 :             }
                                567                 : 
 5710 tgl                       568            1439 :             cntpos++;
                                569                 :         }
                                570                 : 
                                571            1235 :         pfree(prs.words);
                                572                 :     }
                                573                 :     else
 5693 teodor                    574             309 :         pushStop(state);
 5710 tgl                       575            1544 : }
                                576                 : 
                                577                 : Datum
                                578             377 : to_tsquery_byid(PG_FUNCTION_ARGS)
                                579                 : {
 2219 noah                      580             377 :     text       *in = PG_GETARG_TEXT_PP(1);
                                581                 :     TSQuery     query;
                                582                 :     MorphOpaque data;
                                583                 : 
 2558 teodor                    584             377 :     data.cfg_id = PG_GETARG_OID(0);
                                585                 : 
                                586                 :     /*
                                587                 :      * Passing OP_PHRASE as a qoperator makes tsquery require matching of word
                                588                 :      * positions of a complex morph exactly match the tsvector.  Also, when
                                589                 :      * the complex morphs are connected with OP_PHRASE operator, we connect
                                590                 :      * all their words into the OP_PHRASE sequence.
                                591                 :      */
  798 akorotkov                 592             377 :     data.qoperator = OP_PHRASE;
                                593                 : 
 2558 teodor                    594             377 :     query = parse_tsquery(text_to_cstring(in),
                                595                 :                           pushval_morph,
                                596                 :                           PointerGetDatum(&data),
                                597                 :                           0,
                                598                 :                           NULL);
                                599                 : 
 5710 tgl                       600 GIC         377 :     PG_RETURN_TSQUERY(query);
 5710 tgl                       601 ECB             : }
                                602                 : 
                                603                 : Datum
 5710 tgl                       604 GIC          66 : to_tsquery(PG_FUNCTION_ARGS)
 5710 tgl                       605 ECB             : {
 2219 noah                      606 GIC          66 :     text       *in = PG_GETARG_TEXT_PP(0);
 5710 tgl                       607 ECB             :     Oid         cfgId;
                                608                 : 
 5710 tgl                       609 GIC          66 :     cfgId = getTSCurrentConfig(true);
 5710 tgl                       610 CBC          66 :     PG_RETURN_DATUM(DirectFunctionCall2(to_tsquery_byid,
 5710 tgl                       611 ECB             :                                         ObjectIdGetDatum(cfgId),
                                612                 :                                         PointerGetDatum(in)));
                                613                 : }
                                614                 : 
                                615                 : Datum
 5710 tgl                       616 GIC          30 : plainto_tsquery_byid(PG_FUNCTION_ARGS)
 5710 tgl                       617 ECB             : {
 2219 noah                      618 GIC          30 :     text       *in = PG_GETARG_TEXT_PP(1);
 2495 rhaas                     619 ECB             :     TSQuery     query;
                                620                 :     MorphOpaque data;
                                621                 : 
 2558 teodor                    622 GIC          30 :     data.cfg_id = PG_GETARG_OID(0);
  798 akorotkov                 623 ECB             : 
                                624                 :     /*
                                625                 :      * parse_tsquery() with P_TSQ_PLAIN flag takes the whole input text as a
                                626                 :      * single morph.  Passing OP_PHRASE as a qoperator makes tsquery require
                                627                 :      * matching of all words independently on their positions.
                                628                 :      */
 2558 teodor                    629 GIC          30 :     data.qoperator = OP_AND;
 5710 tgl                       630 ECB             : 
 2558 teodor                    631 GIC          30 :     query = parse_tsquery(text_to_cstring(in),
 2558 teodor                    632 ECB             :                           pushval_morph,
                                633                 :                           PointerGetDatum(&data),
                                634                 :                           P_TSQ_PLAIN,
                                635                 :                           NULL);
                                636                 : 
 2558 teodor                    637 GIC          30 :     PG_RETURN_POINTER(query);
                                638                 : }
 5511 teodor                    639 ECB             : 
                                640                 : Datum
 2558 teodor                    641 GIC           6 : plainto_tsquery(PG_FUNCTION_ARGS)
                                642                 : {
 2219 noah                      643 CBC           6 :     text       *in = PG_GETARG_TEXT_PP(0);
                                644                 :     Oid         cfgId;
 2558 teodor                    645 ECB             : 
 2558 teodor                    646 GIC           6 :     cfgId = getTSCurrentConfig(true);
                                647               6 :     PG_RETURN_DATUM(DirectFunctionCall2(plainto_tsquery_byid,
 2558 teodor                    648 ECB             :                                         ObjectIdGetDatum(cfgId),
                                649                 :                                         PointerGetDatum(in)));
                                650                 : }
                                651                 : 
                                652                 : 
                                653                 : Datum
 2558 teodor                    654 GIC          24 : phraseto_tsquery_byid(PG_FUNCTION_ARGS)
                                655                 : {
 2219 noah                      656 CBC          24 :     text       *in = PG_GETARG_TEXT_PP(1);
                                657                 :     TSQuery     query;
 2495 rhaas                     658 ECB             :     MorphOpaque data;
                                659                 : 
 2558 teodor                    660 GIC          24 :     data.cfg_id = PG_GETARG_OID(0);
                                661                 : 
  798 akorotkov                 662 ECB             :     /*
                                663                 :      * parse_tsquery() with P_TSQ_PLAIN flag takes the whole input text as a
                                664                 :      * single morph.  Passing OP_PHRASE as a qoperator makes tsquery require
                                665                 :      * matching of word positions.
                                666                 :      */
 2558 teodor                    667 GIC          24 :     data.qoperator = OP_PHRASE;
                                668                 : 
 2558 teodor                    669 CBC          24 :     query = parse_tsquery(text_to_cstring(in),
                                670                 :                           pushval_morph,
 2558 teodor                    671 ECB             :                           PointerGetDatum(&data),
                                672                 :                           P_TSQ_PLAIN,
                                673                 :                           NULL);
                                674                 : 
 2558 teodor                    675 GIC          24 :     PG_RETURN_TSQUERY(query);
                                676                 : }
                                677                 : 
 5710 tgl                       678 ECB             : Datum
 2558 teodor                    679 UIC           0 : phraseto_tsquery(PG_FUNCTION_ARGS)
                                680                 : {
 2219 noah                      681               0 :     text       *in = PG_GETARG_TEXT_PP(0);
 5710 tgl                       682 EUB             :     Oid         cfgId;
                                683                 : 
 5710 tgl                       684 UBC           0 :     cfgId = getTSCurrentConfig(true);
 2558 teodor                    685 UIC           0 :     PG_RETURN_DATUM(DirectFunctionCall2(phraseto_tsquery_byid,
                                686                 :                                         ObjectIdGetDatum(cfgId),
 5710 tgl                       687 EUB             :                                         PointerGetDatum(in)));
                                688                 : }
                                689                 : 
                                690                 : Datum
 1830 teodor                    691 GIC         204 : websearch_to_tsquery_byid(PG_FUNCTION_ARGS)
                                692                 : {
                                693             204 :     text       *in = PG_GETARG_TEXT_PP(1);
 1809 tgl                       694 ECB             :     MorphOpaque data;
 1830 teodor                    695 GIC         204 :     TSQuery     query = NULL;
 1830 teodor                    696 ECB             : 
 1830 teodor                    697 GIC         204 :     data.cfg_id = PG_GETARG_OID(0);
 1830 teodor                    698 ECB             : 
                                699                 :     /*
  798 akorotkov                 700                 :      * Passing OP_PHRASE as a qoperator makes tsquery require matching of word
                                701                 :      * positions of a complex morph exactly match the tsvector.  Also, when
                                702                 :      * the complex morphs are given in quotes, we connect all their words into
                                703                 :      * the OP_PHRASE sequence.
                                704                 :      */
  798 akorotkov                 705 GIC         204 :     data.qoperator = OP_PHRASE;
                                706                 : 
 1830 teodor                    707             204 :     query = parse_tsquery(text_to_cstring(in),
 1830 teodor                    708 ECB             :                           pushval_morph,
                                709                 :                           PointerGetDatum(&data),
                                710                 :                           P_TSQ_WEB,
                                711                 :                           NULL);
                                712                 : 
 1830 teodor                    713 GIC         204 :     PG_RETURN_TSQUERY(query);
                                714                 : }
                                715                 : 
                                716                 : Datum
 1830 teodor                    717 CBC          12 : websearch_to_tsquery(PG_FUNCTION_ARGS)
                                718                 : {
 1830 teodor                    719 GIC          12 :     text       *in = PG_GETARG_TEXT_PP(0);
                                720                 :     Oid         cfgId;
 1830 teodor                    721 ECB             : 
 1830 teodor                    722 GIC          12 :     cfgId = getTSCurrentConfig(true);
 1830 teodor                    723 CBC          12 :     PG_RETURN_DATUM(DirectFunctionCall2(websearch_to_tsquery_byid,
                                724                 :                                         ObjectIdGetDatum(cfgId),
                                725                 :                                         PointerGetDatum(in)));
 1830 teodor                    726 ECB             : }
        

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