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: 7a15cff1f11193467898da1c1fabf06fd2caee04 vs 84a3778c79c2d28b4dc281d03ef2ab019b16483b Lines: 85.3 % 136 116 1 19 5 111 1 5
Current Date: 2025-12-15 18:36:29 -0500 Functions: 80.0 % 10 8 2 4 4
Baseline: lcov-20251216-010103-baseline Branches: 70.3 % 74 52 22 2 50 27 9
Baseline Date: 2025-12-15 13:30:48 -0800 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] 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:
(7,30] 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                 :                : 
 6852 teodor@sigaev.ru           12                 :UBC           0 : PG_FUNCTION_INFO_V1(gin_extract_trgm);
 5433 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);
 6852 teodor@sigaev.ru           15                 :              4 : PG_FUNCTION_INFO_V1(gin_trgm_consistent);
 3802                            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
 6852 teodor@sigaev.ru           24                 :UBC           0 : gin_extract_trgm(PG_FUNCTION_ARGS)
                                 25                 :                : {
 5416 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
 5433 tgl@sss.pgh.pa.us          35                 :CBC        2404 : gin_extract_value_trgm(PG_FUNCTION_ARGS)
                                 36                 :                : {
 3201 noah@leadboat.com          37                 :           2404 :     text       *val = (text *) PG_GETARG_TEXT_PP(0);
 6606 bruce@momjian.us           38                 :           2404 :     int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
                                 39                 :           2404 :     Datum      *entries = NULL;
                                 40                 :                :     TRGM       *trg;
                                 41                 :                :     int32       trglen;
                                 42                 :                : 
 6852 teodor@sigaev.ru           43                 :           2404 :     *nentries = 0;
                                 44                 :                : 
 3201 noah@leadboat.com          45   [ -  +  -  -  :           2404 :     trg = generate_trgm(VARDATA_ANY(val), VARSIZE_ANY_EXHDR(val));
                                     -  -  -  -  +  
                                           -  +  - ]
 6852 teodor@sigaev.ru           46                 :           2404 :     trglen = ARRNELEM(trg);
                                 47                 :                : 
                                 48         [ +  - ]:           2404 :     if (trglen > 0)
                                 49                 :                :     {
                                 50                 :                :         trgm       *ptr;
                                 51                 :                :         int32       i;
                                 52                 :                : 
 5455 tgl@sss.pgh.pa.us          53                 :           2404 :         *nentries = trglen;
   11 michael@paquier.xyz        54                 :GNC        2404 :         entries = palloc_array(Datum, trglen);
                                 55                 :                : 
 6852 teodor@sigaev.ru           56                 :CBC        2404 :         ptr = GETARR(trg);
 5455 tgl@sss.pgh.pa.us          57         [ +  + ]:          35631 :         for (i = 0; i < trglen; i++)
                                 58                 :                :         {
 5364 bruce@momjian.us           59                 :          33227 :             int32       item = trgm2int(ptr);
                                 60                 :                : 
 5455 tgl@sss.pgh.pa.us          61                 :          33227 :             entries[i] = Int32GetDatum(item);
 6852 teodor@sigaev.ru           62                 :          33227 :             ptr++;
                                 63                 :                :         }
                                 64                 :                :     }
                                 65                 :                : 
                                 66                 :           2404 :     PG_RETURN_POINTER(entries);
                                 67                 :                : }
                                 68                 :                : 
                                 69                 :                : Datum
 5433 tgl@sss.pgh.pa.us          70                 :            188 : gin_extract_query_trgm(PG_FUNCTION_ARGS)
                                 71                 :                : {
 3201 noah@leadboat.com          72                 :            188 :     text       *val = (text *) PG_GETARG_TEXT_PP(0);
 5433 tgl@sss.pgh.pa.us          73                 :            188 :     int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
                                 74                 :            188 :     StrategyNumber strategy = PG_GETARG_UINT16(2);
                                 75                 :                : 
                                 76                 :                :     /* bool   **pmatch = (bool **) PG_GETARG_POINTER(3); */
 4634                            77                 :            188 :     Pointer   **extra_data = (Pointer **) PG_GETARG_POINTER(4);
                                 78                 :                : 
                                 79                 :                :     /* bool   **nullFlags = (bool **) PG_GETARG_POINTER(5); */
 5364 bruce@momjian.us           80                 :            188 :     int32      *searchMode = (int32 *) PG_GETARG_POINTER(6);
 5433 tgl@sss.pgh.pa.us          81                 :            188 :     Datum      *entries = NULL;
                                 82                 :                :     TRGM       *trg;
                                 83                 :                :     int32       trglen;
                                 84                 :                :     trgm       *ptr;
                                 85                 :                :     TrgmPackedGraph *graph;
                                 86                 :                :     int32       i;
                                 87                 :                : 
                                 88   [ +  +  +  - ]:            188 :     switch (strategy)
                                 89                 :                :     {
                                 90                 :             96 :         case SimilarityStrategyNumber:
                                 91                 :                :         case WordSimilarityStrategyNumber:
                                 92                 :                :         case StrictWordSimilarityStrategyNumber:
                                 93                 :                :         case EqualStrategyNumber:
 3201 noah@leadboat.com          94   [ -  +  -  -  :             96 :             trg = generate_trgm(VARDATA_ANY(val), VARSIZE_ANY_EXHDR(val));
                                     -  -  -  -  -  
                                           +  -  + ]
 5433 tgl@sss.pgh.pa.us          95                 :             96 :             break;
                                 96                 :             48 :         case ILikeStrategyNumber:
                                 97                 :                : #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                 :                :              */
 3201 noah@leadboat.com         107         [ -  + ]:             48 :             trg = generate_wildcard_trgm(VARDATA_ANY(val),
                                108   [ -  +  -  -  :             48 :                                          VARSIZE_ANY_EXHDR(val));
                                     -  -  -  -  -  
                                                 + ]
 5433 tgl@sss.pgh.pa.us         109                 :             48 :             break;
 4634                           110                 :             44 :         case RegExpICaseStrategyNumber:
                                111                 :                : #ifndef IGNORECASE
                                112                 :                :             elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
                                113                 :                : #endif
                                114                 :                :             /* FALL THRU */
                                115                 :                :         case RegExpStrategyNumber:
 4633                           116                 :             44 :             trg = createTrgmNFA(val, PG_GET_COLLATION(),
                                117                 :                :                                 &graph, CurrentMemoryContext);
 4634                           118   [ +  +  +  + ]:             44 :             if (trg && ARRNELEM(trg) > 0)
                                119                 :                :             {
                                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                 :             34 :                 trglen = ARRNELEM(trg);
   11 michael@paquier.xyz       126                 :GNC          34 :                 *extra_data = palloc_array(Pointer, trglen);
 4634 tgl@sss.pgh.pa.us         127         [ +  + ]:CBC         848 :                 for (i = 0; i < trglen; i++)
                                128                 :            814 :                     (*extra_data)[i] = (Pointer) graph;
                                129                 :                :             }
                                130                 :                :             else
                                131                 :                :             {
                                132                 :                :                 /* No result: have to do full index scan. */
                                133                 :             10 :                 *nentries = 0;
                                134                 :             10 :                 *searchMode = GIN_SEARCH_MODE_ALL;
                                135                 :             10 :                 PG_RETURN_POINTER(entries);
                                136                 :                :             }
                                137                 :             34 :             break;
 5433 tgl@sss.pgh.pa.us         138                 :UBC           0 :         default:
                                139         [ #  # ]:              0 :             elog(ERROR, "unrecognized strategy number: %d", strategy);
                                140                 :                :             trg = NULL;         /* keep compiler quiet */
                                141                 :                :             break;
                                142                 :                :     }
                                143                 :                : 
 5433 tgl@sss.pgh.pa.us         144                 :CBC         178 :     trglen = ARRNELEM(trg);
                                145                 :            178 :     *nentries = trglen;
                                146                 :                : 
                                147         [ +  + ]:            178 :     if (trglen > 0)
                                148                 :                :     {
   11 michael@paquier.xyz       149                 :GNC         146 :         entries = palloc_array(Datum, trglen);
 5433 tgl@sss.pgh.pa.us         150                 :CBC         146 :         ptr = GETARR(trg);
                                151         [ +  + ]:           1748 :         for (i = 0; i < trglen; i++)
                                152                 :                :         {
 5364 bruce@momjian.us          153                 :           1602 :             int32       item = trgm2int(ptr);
                                154                 :                : 
 5433 tgl@sss.pgh.pa.us         155                 :           1602 :             entries[i] = Int32GetDatum(item);
                                156                 :           1602 :             ptr++;
                                157                 :                :         }
                                158                 :                :     }
                                159                 :                : 
                                160                 :                :     /*
                                161                 :                :      * If no trigram was extracted then we have to scan all the index.
                                162                 :                :      */
                                163         [ +  + ]:            178 :     if (trglen == 0)
                                164                 :             32 :         *searchMode = GIN_SEARCH_MODE_ALL;
                                165                 :                : 
                                166                 :            178 :     PG_RETURN_POINTER(entries);
                                167                 :                : }
                                168                 :                : 
                                169                 :                : Datum
 6852 teodor@sigaev.ru          170                 :             12 : gin_trgm_consistent(PG_FUNCTION_ARGS)
                                171                 :                : {
 6606 bruce@momjian.us          172                 :             12 :     bool       *check = (bool *) PG_GETARG_POINTER(0);
 5433 tgl@sss.pgh.pa.us         173                 :             12 :     StrategyNumber strategy = PG_GETARG_UINT16(1);
                                174                 :                : 
                                175                 :                :     /* text    *query = PG_GETARG_TEXT_PP(2); */
 5455                           176                 :             12 :     int32       nkeys = PG_GETARG_INT32(3);
 4634                           177                 :             12 :     Pointer    *extra_data = (Pointer *) PG_GETARG_POINTER(4);
 6110                           178                 :             12 :     bool       *recheck = (bool *) PG_GETARG_POINTER(5);
                                179                 :                :     bool        res;
                                180                 :                :     int32       i,
                                181                 :                :                 ntrue;
                                182                 :                :     double      nlimit;
                                183                 :                : 
                                184                 :                :     /* All cases served by this function are inexact */
 6455                           185                 :             12 :     *recheck = true;
                                186                 :                : 
 5433                           187   [ +  +  -  - ]:             12 :     switch (strategy)
                                188                 :                :     {
                                189                 :              4 :         case SimilarityStrategyNumber:
                                190                 :                :         case WordSimilarityStrategyNumber:
                                191                 :                :         case StrictWordSimilarityStrategyNumber:
 2827 teodor@sigaev.ru          192                 :              4 :             nlimit = index_strategy_get_limit(strategy);
                                193                 :                : 
                                194                 :                :             /* Count the matches */
 5433 tgl@sss.pgh.pa.us         195                 :              4 :             ntrue = 0;
                                196         [ +  + ]:             18 :             for (i = 0; i < nkeys; i++)
                                197                 :                :             {
                                198         [ +  + ]:             14 :                 if (check[i])
                                199                 :             12 :                     ntrue++;
                                200                 :                :             }
                                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                 :                :              */
 3562 teodor@sigaev.ru          217         [ +  + ]:              6 :             res = (nkeys == 0) ? false :
                                218         [ +  - ]:              2 :                 (((((float4) ntrue) / ((float4) nkeys))) >= nlimit);
 5433 tgl@sss.pgh.pa.us         219                 :              4 :             break;
                                220                 :              8 :         case ILikeStrategyNumber:
                                221                 :                : #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                 :              8 :             res = true;
                                229         [ +  + ]:             16 :             for (i = 0; i < nkeys; i++)
                                230                 :                :             {
                                231         [ -  + ]:              8 :                 if (!check[i])
                                232                 :                :                 {
 5433 tgl@sss.pgh.pa.us         233                 :UBC           0 :                     res = false;
                                234                 :              0 :                     break;
                                235                 :                :                 }
                                236                 :                :             }
 5433 tgl@sss.pgh.pa.us         237                 :CBC           8 :             break;
 4634 tgl@sss.pgh.pa.us         238                 :UBC           0 :         case RegExpICaseStrategyNumber:
                                239                 :                : #ifndef IGNORECASE
                                240                 :                :             elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
                                241                 :                : #endif
                                242                 :                :             /* FALL THRU */
                                243                 :                :         case RegExpStrategyNumber:
                                244         [ #  # ]:              0 :             if (nkeys < 1)
                                245                 :                :             {
                                246                 :                :                 /* Regex processing gave no result: do full index scan */
                                247                 :              0 :                 res = true;
                                248                 :                :             }
                                249                 :                :             else
   12 peter@eisentraut.org      250                 :UNC           0 :                 res = trigramsMatchGraph(extra_data[0], check);
 4634 tgl@sss.pgh.pa.us         251                 :UBC           0 :             break;
 5433                           252                 :              0 :         default:
                                253         [ #  # ]:              0 :             elog(ERROR, "unrecognized strategy number: %d", strategy);
                                254                 :                :             res = false;        /* keep compiler quiet */
                                255                 :                :             break;
                                256                 :                :     }
                                257                 :                : 
 6852 teodor@sigaev.ru          258                 :CBC          12 :     PG_RETURN_BOOL(res);
                                259                 :                : }
                                260                 :                : 
                                261                 :                : /*
                                262                 :                :  * In all cases, GIN_TRUE is at least as favorable to inclusion as
                                263                 :                :  * GIN_MAYBE. If no better option is available, simply treat
                                264                 :                :  * GIN_MAYBE as if it were GIN_TRUE and apply the same test as the binary
                                265                 :                :  * consistent function.
                                266                 :                :  */
                                267                 :                : Datum
 3802                           268                 :          16357 : gin_trgm_triconsistent(PG_FUNCTION_ARGS)
                                269                 :                : {
 3477 rhaas@postgresql.org      270                 :          16357 :     GinTernaryValue *check = (GinTernaryValue *) PG_GETARG_POINTER(0);
 3802 teodor@sigaev.ru          271                 :          16357 :     StrategyNumber strategy = PG_GETARG_UINT16(1);
                                272                 :                : 
                                273                 :                :     /* text    *query = PG_GETARG_TEXT_PP(2); */
                                274                 :          16357 :     int32       nkeys = PG_GETARG_INT32(3);
                                275                 :          16357 :     Pointer    *extra_data = (Pointer *) PG_GETARG_POINTER(4);
 3477 rhaas@postgresql.org      276                 :          16357 :     GinTernaryValue res = GIN_MAYBE;
                                277                 :                :     int32       i,
                                278                 :                :                 ntrue;
                                279                 :                :     bool       *boolcheck;
                                280                 :                :     double      nlimit;
                                281                 :                : 
 3802 teodor@sigaev.ru          282   [ +  +  +  - ]:          16357 :     switch (strategy)
                                283                 :                :     {
                                284                 :          10197 :         case SimilarityStrategyNumber:
                                285                 :                :         case WordSimilarityStrategyNumber:
                                286                 :                :         case StrictWordSimilarityStrategyNumber:
 2827                           287                 :          10197 :             nlimit = index_strategy_get_limit(strategy);
                                288                 :                : 
                                289                 :                :             /* Count the matches */
 3802                           290                 :          10197 :             ntrue = 0;
                                291         [ +  + ]:          95957 :             for (i = 0; i < nkeys; i++)
                                292                 :                :             {
                                293         [ +  + ]:          85760 :                 if (check[i] != GIN_FALSE)
                                294                 :          39202 :                     ntrue++;
                                295                 :                :             }
                                296                 :                : 
                                297                 :                :             /*
                                298                 :                :              * See comment in gin_trgm_consistent() about * upper bound
                                299                 :                :              * formula
                                300                 :                :              */
 3562                           301         [ +  + ]:          19394 :             res = (nkeys == 0)
                                302         [ +  + ]:           9197 :                 ? GIN_FALSE : (((((float4) ntrue) / ((float4) nkeys)) >= nlimit)
                                303                 :                :                                ? GIN_MAYBE : GIN_FALSE);
 3802                           304                 :          10197 :             break;
                                305                 :           4039 :         case ILikeStrategyNumber:
                                306                 :                : #ifndef IGNORECASE
                                307                 :                :             elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
                                308                 :                : #endif
                                309                 :                :             /* FALL THRU */
                                310                 :                :         case LikeStrategyNumber:
                                311                 :                :         case EqualStrategyNumber:
                                312                 :                :             /* Check if all extracted trigrams are presented. */
                                313                 :           4039 :             res = GIN_MAYBE;
                                314         [ +  + ]:           8175 :             for (i = 0; i < nkeys; i++)
                                315                 :                :             {
                                316         [ +  + ]:           4156 :                 if (check[i] == GIN_FALSE)
                                317                 :                :                 {
                                318                 :             20 :                     res = GIN_FALSE;
                                319                 :             20 :                     break;
                                320                 :                :                 }
                                321                 :                :             }
                                322                 :           4039 :             break;
                                323                 :           2121 :         case RegExpICaseStrategyNumber:
                                324                 :                : #ifndef IGNORECASE
                                325                 :                :             elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
                                326                 :                : #endif
                                327                 :                :             /* FALL THRU */
                                328                 :                :         case RegExpStrategyNumber:
                                329         [ +  + ]:           2121 :             if (nkeys < 1)
                                330                 :                :             {
                                331                 :                :                 /* Regex processing gave no result: do full index scan */
                                332                 :            736 :                 res = GIN_MAYBE;
                                333                 :                :             }
                                334                 :                :             else
                                335                 :                :             {
                                336                 :                :                 /*
                                337                 :                :                  * As trigramsMatchGraph implements a monotonic boolean
                                338                 :                :                  * function, promoting all GIN_MAYBE keys to GIN_TRUE will
                                339                 :                :                  * give a conservative result.
                                340                 :                :                  */
   11 michael@paquier.xyz       341                 :GNC        1385 :                 boolcheck = palloc_array(bool, nkeys);
 3802 teodor@sigaev.ru          342         [ +  + ]:CBC      319289 :                 for (i = 0; i < nkeys; i++)
                                343                 :         317904 :                     boolcheck[i] = (check[i] != GIN_FALSE);
   12 peter@eisentraut.org      344         [ +  + ]:GNC        1385 :                 if (!trigramsMatchGraph(extra_data[0], boolcheck))
 3802 teodor@sigaev.ru          345                 :CBC           6 :                     res = GIN_FALSE;
                                346                 :           1385 :                 pfree(boolcheck);
                                347                 :                :             }
                                348                 :           2121 :             break;
 3802 teodor@sigaev.ru          349                 :UBC           0 :         default:
                                350         [ #  # ]:              0 :             elog(ERROR, "unrecognized strategy number: %d", strategy);
                                351                 :                :             res = GIN_FALSE;    /* keep compiler quiet */
                                352                 :                :             break;
                                353                 :                :     }
                                354                 :                : 
                                355                 :                :     /* All cases served by this function are inexact */
 3802 teodor@sigaev.ru          356         [ -  + ]:CBC       16357 :     Assert(res != GIN_TRUE);
                                357                 :          16357 :     PG_RETURN_GIN_TERNARY_VALUE(res);
                                358                 :                : }
        

Generated by: LCOV version 2.4-beta