LCOV - differential code coverage report
Current view: top level - contrib/pg_trgm - trgm_gin.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 78.7 % 136 107 3 13 13 2 59 46 14 58
Current Date: 2023-04-08 15:15:32 Functions: 80.0 % 10 8 2 8 2 8
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*
       2                 :  * contrib/pg_trgm/trgm_gin.c
       3                 :  */
       4                 : #include "postgres.h"
       5                 : 
       6                 : #include "access/gin.h"
       7                 : #include "access/stratnum.h"
       8                 : #include "fmgr.h"
       9                 : #include "trgm.h"
      10                 : #include "varatt.h"
      11                 : 
      12 UIC           0 : PG_FUNCTION_INFO_V1(gin_extract_trgm);
      13 GBC           4 : PG_FUNCTION_INFO_V1(gin_extract_value_trgm);
      14 CBC           4 : PG_FUNCTION_INFO_V1(gin_extract_query_trgm);
      15               4 : PG_FUNCTION_INFO_V1(gin_trgm_consistent);
      16               4 : PG_FUNCTION_INFO_V1(gin_trgm_triconsistent);
      17 ECB             : 
      18                 : /*
      19                 :  * This function can only be called if a pre-9.1 version of the GIN operator
      20                 :  * class definition is present in the catalogs (probably as a consequence
      21                 :  * of upgrade-in-place).  Cope.
      22                 :  */
      23                 : Datum
      24 UIC           0 : gin_extract_trgm(PG_FUNCTION_ARGS)
      25 EUB             : {
      26 UIC           0 :     if (PG_NARGS() == 3)
      27 UBC           0 :         return gin_extract_value_trgm(fcinfo);
      28               0 :     if (PG_NARGS() == 7)
      29               0 :         return gin_extract_query_trgm(fcinfo);
      30               0 :     elog(ERROR, "unexpected number of arguments to gin_extract_trgm");
      31 EUB             :     PG_RETURN_NULL();
      32                 : }
      33                 : 
      34                 : Datum
      35 GIC        2404 : gin_extract_value_trgm(PG_FUNCTION_ARGS)
      36 ECB             : {
      37 GIC        2404 :     text       *val = (text *) PG_GETARG_TEXT_PP(0);
      38 CBC        2404 :     int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
      39            2404 :     Datum      *entries = NULL;
      40 ECB             :     TRGM       *trg;
      41                 :     int32       trglen;
      42                 : 
      43 GIC        2404 :     *nentries = 0;
      44 ECB             : 
      45 GIC        2404 :     trg = generate_trgm(VARDATA_ANY(val), VARSIZE_ANY_EXHDR(val));
      46 CBC        2404 :     trglen = ARRNELEM(trg);
      47 ECB             : 
      48 GIC        2404 :     if (trglen > 0)
      49 ECB             :     {
      50                 :         trgm       *ptr;
      51                 :         int32       i;
      52                 : 
      53 GIC        2404 :         *nentries = trglen;
      54 CBC        2404 :         entries = (Datum *) palloc(sizeof(Datum) * trglen);
      55 ECB             : 
      56 GIC        2404 :         ptr = GETARR(trg);
      57 CBC       35631 :         for (i = 0; i < trglen; i++)
      58 ECB             :         {
      59 GIC       33227 :             int32       item = trgm2int(ptr);
      60 ECB             : 
      61 GIC       33227 :             entries[i] = Int32GetDatum(item);
      62 CBC       33227 :             ptr++;
      63 ECB             :         }
      64                 :     }
      65                 : 
      66 GIC        2404 :     PG_RETURN_POINTER(entries);
      67 ECB             : }
      68                 : 
      69                 : Datum
      70 GIC         172 : gin_extract_query_trgm(PG_FUNCTION_ARGS)
      71 ECB             : {
      72 GIC         172 :     text       *val = (text *) PG_GETARG_TEXT_PP(0);
      73 CBC         172 :     int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
      74             172 :     StrategyNumber strategy = PG_GETARG_UINT16(2);
      75 ECB             : 
      76                 :     /* bool   **pmatch = (bool **) PG_GETARG_POINTER(3); */
      77 GIC         172 :     Pointer   **extra_data = (Pointer **) PG_GETARG_POINTER(4);
      78 ECB             : 
      79                 :     /* bool   **nullFlags = (bool **) PG_GETARG_POINTER(5); */
      80 GIC         172 :     int32      *searchMode = (int32 *) PG_GETARG_POINTER(6);
      81 CBC         172 :     Datum      *entries = NULL;
      82 ECB             :     TRGM       *trg;
      83                 :     int32       trglen;
      84                 :     trgm       *ptr;
      85                 :     TrgmPackedGraph *graph;
      86                 :     int32       i;
      87                 : 
      88 GIC         172 :     switch (strategy)
      89 ECB             :     {
      90 GIC          80 :         case SimilarityStrategyNumber:
      91 ECB             :         case WordSimilarityStrategyNumber:
      92                 :         case StrictWordSimilarityStrategyNumber:
      93                 :         case EqualStrategyNumber:
      94 GIC          80 :             trg = generate_trgm(VARDATA_ANY(val), VARSIZE_ANY_EXHDR(val));
      95 CBC          80 :             break;
      96              48 :         case ILikeStrategyNumber:
      97 ECB             : #ifndef IGNORECASE
      98                 :             elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
      99                 : #endif
     100                 :             /* FALL THRU */
     101                 :         case LikeStrategyNumber:
     102                 : 
     103                 :             /*
     104                 :              * For wildcard search we extract all the trigrams that every
     105                 :              * potentially-matching string must include.
     106                 :              */
     107 GIC          48 :             trg = generate_wildcard_trgm(VARDATA_ANY(val),
     108 CBC          48 :                                          VARSIZE_ANY_EXHDR(val));
     109              48 :             break;
     110              44 :         case RegExpICaseStrategyNumber:
     111 ECB             : #ifndef IGNORECASE
     112                 :             elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
     113                 : #endif
     114                 :             /* FALL THRU */
     115                 :         case RegExpStrategyNumber:
     116 GIC          44 :             trg = createTrgmNFA(val, PG_GET_COLLATION(),
     117 ECB             :                                 &graph, CurrentMemoryContext);
     118 GIC          44 :             if (trg && ARRNELEM(trg) > 0)
     119 ECB             :             {
     120                 :                 /*
     121                 :                  * Successful regex processing: store NFA-like graph as
     122                 :                  * extra_data.  GIN API requires an array of nentries
     123                 :                  * Pointers, but we just put the same value in each element.
     124                 :                  */
     125 GIC          34 :                 trglen = ARRNELEM(trg);
     126 CBC          34 :                 *extra_data = (Pointer *) palloc(sizeof(Pointer) * trglen);
     127             848 :                 for (i = 0; i < trglen; i++)
     128             814 :                     (*extra_data)[i] = (Pointer) graph;
     129 ECB             :             }
     130                 :             else
     131                 :             {
     132                 :                 /* No result: have to do full index scan. */
     133 GIC          10 :                 *nentries = 0;
     134 CBC          10 :                 *searchMode = GIN_SEARCH_MODE_ALL;
     135              10 :                 PG_RETURN_POINTER(entries);
     136 ECB             :             }
     137 GIC          34 :             break;
     138 LBC           0 :         default:
     139 UBC           0 :             elog(ERROR, "unrecognized strategy number: %d", strategy);
     140 EUB             :             trg = NULL;         /* keep compiler quiet */
     141                 :             break;
     142                 :     }
     143                 : 
     144 GIC         162 :     trglen = ARRNELEM(trg);
     145 CBC         162 :     *nentries = trglen;
     146 ECB             : 
     147 GIC         162 :     if (trglen > 0)
     148 ECB             :     {
     149 GIC         138 :         entries = (Datum *) palloc(sizeof(Datum) * trglen);
     150 CBC         138 :         ptr = GETARR(trg);
     151            1684 :         for (i = 0; i < trglen; i++)
     152 ECB             :         {
     153 GIC        1546 :             int32       item = trgm2int(ptr);
     154 ECB             : 
     155 GIC        1546 :             entries[i] = Int32GetDatum(item);
     156 CBC        1546 :             ptr++;
     157 ECB             :         }
     158                 :     }
     159                 : 
     160                 :     /*
     161                 :      * If no trigram was extracted then we have to scan all the index.
     162                 :      */
     163 GIC         162 :     if (trglen == 0)
     164 CBC          24 :         *searchMode = GIN_SEARCH_MODE_ALL;
     165 ECB             : 
     166 GIC         162 :     PG_RETURN_POINTER(entries);
     167 ECB             : }
     168                 : 
     169                 : Datum
     170 GIC           8 : gin_trgm_consistent(PG_FUNCTION_ARGS)
     171 ECB             : {
     172 GIC           8 :     bool       *check = (bool *) PG_GETARG_POINTER(0);
     173 CBC           8 :     StrategyNumber strategy = PG_GETARG_UINT16(1);
     174 ECB             : 
     175                 :     /* text    *query = PG_GETARG_TEXT_PP(2); */
     176 GIC           8 :     int32       nkeys = PG_GETARG_INT32(3);
     177 CBC           8 :     Pointer    *extra_data = (Pointer *) PG_GETARG_POINTER(4);
     178               8 :     bool       *recheck = (bool *) PG_GETARG_POINTER(5);
     179 ECB             :     bool        res;
     180                 :     int32       i,
     181                 :                 ntrue;
     182                 :     double      nlimit;
     183                 : 
     184                 :     /* All cases served by this function are inexact */
     185 GIC           8 :     *recheck = true;
     186 ECB             : 
     187 GIC           8 :     switch (strategy)
     188 ECB             :     {
     189 UIC           0 :         case SimilarityStrategyNumber:
     190 EUB             :         case WordSimilarityStrategyNumber:
     191                 :         case StrictWordSimilarityStrategyNumber:
     192 UIC           0 :             nlimit = index_strategy_get_limit(strategy);
     193 EUB             : 
     194                 :             /* Count the matches */
     195 UIC           0 :             ntrue = 0;
     196 UBC           0 :             for (i = 0; i < nkeys; i++)
     197 EUB             :             {
     198 UIC           0 :                 if (check[i])
     199 UBC           0 :                     ntrue++;
     200 EUB             :             }
     201                 : 
     202                 :             /*--------------------
     203                 :              * If DIVUNION is defined then similarity formula is:
     204                 :              * c / (len1 + len2 - c)
     205                 :              * where c is number of common trigrams and it stands as ntrue in
     206                 :              * this code.  Here we don't know value of len2 but we can assume
     207                 :              * that c (ntrue) is a lower bound of len2, so upper bound of
     208                 :              * similarity is:
     209                 :              * c / (len1 + c - c)  => c / len1
     210                 :              * If DIVUNION is not defined then similarity formula is:
     211                 :              * c / max(len1, len2)
     212                 :              * And again, c (ntrue) is a lower bound of len2, but c <= len1
     213                 :              * just by definition and, consequently, upper bound of
     214                 :              * similarity is just c / len1.
     215                 :              * So, independently on DIVUNION the upper bound formula is the same.
     216                 :              */
     217 UIC           0 :             res = (nkeys == 0) ? false :
     218 UBC           0 :                 (((((float4) ntrue) / ((float4) nkeys))) >= nlimit);
     219               0 :             break;
     220 GBC           8 :         case ILikeStrategyNumber:
     221 ECB             : #ifndef IGNORECASE
     222                 :             elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
     223                 : #endif
     224                 :             /* FALL THRU */
     225                 :         case LikeStrategyNumber:
     226                 :         case EqualStrategyNumber:
     227                 :             /* Check if all extracted trigrams are presented. */
     228 GIC           8 :             res = true;
     229 CBC          16 :             for (i = 0; i < nkeys; i++)
     230 ECB             :             {
     231 GIC           8 :                 if (!check[i])
     232 ECB             :                 {
     233 UIC           0 :                     res = false;
     234 UBC           0 :                     break;
     235 EUB             :                 }
     236                 :             }
     237 GIC           8 :             break;
     238 LBC           0 :         case RegExpICaseStrategyNumber:
     239 EUB             : #ifndef IGNORECASE
     240                 :             elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
     241                 : #endif
     242                 :             /* FALL THRU */
     243                 :         case RegExpStrategyNumber:
     244 UIC           0 :             if (nkeys < 1)
     245 EUB             :             {
     246                 :                 /* Regex processing gave no result: do full index scan */
     247 UIC           0 :                 res = true;
     248 EUB             :             }
     249                 :             else
     250 UIC           0 :                 res = trigramsMatchGraph((TrgmPackedGraph *) extra_data[0],
     251 EUB             :                                          check);
     252 UIC           0 :             break;
     253 UBC           0 :         default:
     254               0 :             elog(ERROR, "unrecognized strategy number: %d", strategy);
     255 EUB             :             res = false;        /* keep compiler quiet */
     256                 :             break;
     257                 :     }
     258                 : 
     259 GIC           8 :     PG_RETURN_BOOL(res);
     260 ECB             : }
     261                 : 
     262                 : /*
     263                 :  * In all cases, GIN_TRUE is at least as favorable to inclusion as
     264                 :  * GIN_MAYBE. If no better option is available, simply treat
     265                 :  * GIN_MAYBE as if it were GIN_TRUE and apply the same test as the binary
     266                 :  * consistent function.
     267                 :  */
     268                 : Datum
     269 GIC       14358 : gin_trgm_triconsistent(PG_FUNCTION_ARGS)
     270 ECB             : {
     271 GIC       14358 :     GinTernaryValue *check = (GinTernaryValue *) PG_GETARG_POINTER(0);
     272 CBC       14358 :     StrategyNumber strategy = PG_GETARG_UINT16(1);
     273 ECB             : 
     274                 :     /* text    *query = PG_GETARG_TEXT_PP(2); */
     275 GIC       14358 :     int32       nkeys = PG_GETARG_INT32(3);
     276 CBC       14358 :     Pointer    *extra_data = (Pointer *) PG_GETARG_POINTER(4);
     277           14358 :     GinTernaryValue res = GIN_MAYBE;
     278 ECB             :     int32       i,
     279                 :                 ntrue;
     280                 :     bool       *boolcheck;
     281                 :     double      nlimit;
     282                 : 
     283 GIC       14358 :     switch (strategy)
     284 ECB             :     {
     285 GIC        8191 :         case SimilarityStrategyNumber:
     286 ECB             :         case WordSimilarityStrategyNumber:
     287                 :         case StrictWordSimilarityStrategyNumber:
     288 GIC        8191 :             nlimit = index_strategy_get_limit(strategy);
     289 ECB             : 
     290                 :             /* Count the matches */
     291 GIC        8191 :             ntrue = 0;
     292 CBC       86909 :             for (i = 0; i < nkeys; i++)
     293 ECB             :             {
     294 GIC       78718 :                 if (check[i] != GIN_FALSE)
     295 CBC       33172 :                     ntrue++;
     296 ECB             :             }
     297                 : 
     298                 :             /*
     299                 :              * See comment in gin_trgm_consistent() about * upper bound
     300                 :              * formula
     301                 :              */
     302 GIC       16382 :             res = (nkeys == 0)
     303 CBC        8191 :                 ? GIN_FALSE : (((((float4) ntrue) / ((float4) nkeys)) >= nlimit)
     304 ECB             :                                ? GIN_MAYBE : GIN_FALSE);
     305 GIC        8191 :             break;
     306 CBC        4046 :         case ILikeStrategyNumber:
     307 ECB             : #ifndef IGNORECASE
     308                 :             elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
     309                 : #endif
     310                 :             /* FALL THRU */
     311                 :         case LikeStrategyNumber:
     312                 :         case EqualStrategyNumber:
     313                 :             /* Check if all extracted trigrams are presented. */
     314 GIC        4046 :             res = GIN_MAYBE;
     315 CBC        8182 :             for (i = 0; i < nkeys; i++)
     316 ECB             :             {
     317 GIC        4156 :                 if (check[i] == GIN_FALSE)
     318 ECB             :                 {
     319 GIC          20 :                     res = GIN_FALSE;
     320 CBC          20 :                     break;
     321 ECB             :                 }
     322                 :             }
     323 GIC        4046 :             break;
     324 CBC        2121 :         case RegExpICaseStrategyNumber:
     325 ECB             : #ifndef IGNORECASE
     326                 :             elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
     327                 : #endif
     328                 :             /* FALL THRU */
     329                 :         case RegExpStrategyNumber:
     330 GIC        2121 :             if (nkeys < 1)
     331 ECB             :             {
     332                 :                 /* Regex processing gave no result: do full index scan */
     333 GIC         736 :                 res = GIN_MAYBE;
     334 ECB             :             }
     335                 :             else
     336                 :             {
     337                 :                 /*
     338                 :                  * As trigramsMatchGraph implements a monotonic boolean
     339                 :                  * function, promoting all GIN_MAYBE keys to GIN_TRUE will
     340                 :                  * give a conservative result.
     341                 :                  */
     342 GIC        1385 :                 boolcheck = (bool *) palloc(sizeof(bool) * nkeys);
     343 CBC      319289 :                 for (i = 0; i < nkeys; i++)
     344          317904 :                     boolcheck[i] = (check[i] != GIN_FALSE);
     345            1385 :                 if (!trigramsMatchGraph((TrgmPackedGraph *) extra_data[0],
     346 ECB             :                                         boolcheck))
     347 GIC           6 :                     res = GIN_FALSE;
     348 CBC        1385 :                 pfree(boolcheck);
     349 ECB             :             }
     350 GIC        2121 :             break;
     351 LBC           0 :         default:
     352 UBC           0 :             elog(ERROR, "unrecognized strategy number: %d", strategy);
     353 EUB             :             res = GIN_FALSE;    /* keep compiler quiet */
     354                 :             break;
     355                 :     }
     356                 : 
     357                 :     /* All cases served by this function are inexact */
     358 GIC       14358 :     Assert(res != GIN_TRUE);
     359 CBC       14358 :     PG_RETURN_GIN_TERNARY_VALUE(res);
     360 ECB             : }
        

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