LCOV - differential code coverage report
Current view: top level - contrib/pg_trgm - trgm_gin.c (source / functions) Coverage Total Hit UNC UBC GNC CBC EUB ECB DUB DCB
Current: 0e5ff9b9b45a657aea12440478dc002e9b01f138 vs 0123ce131fca454009439dfa3b2266d1d40737d7 Lines: 85.3 % 136 116 1 19 5 111 1 5
Current Date: 2026-03-14 14:10:32 -0400 Functions: 80.0 % 10 8 2 4 4
Baseline: lcov-20260315-024220-baseline Branches: 70.3 % 74 52 22 2 50 27 9 2
Baseline Date: 2026-03-14 15:27:56 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 83.3 % 6 5 1 5
(360..) days: 85.4 % 130 111 19 111
Function coverage date bins:
(360..) days: 80.0 % 10 8 2 4 4
Branch coverage date bins:
(30,360] days: 100.0 % 2 2 2
(360..) days: 46.3 % 108 50 22 50 27 9

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

Generated by: LCOV version 2.4-beta