LCOV - differential code coverage report
Current view: top level - contrib/pg_trgm - trgm_gin.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 78.7 % 136 107 29 107
Current Date: 2024-04-14 14:21:10 Functions: 80.0 % 10 8 2 8
Baseline: 16@8cea358b128 Branches: 47.3 % 110 52 58 52
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 78.7 % 136 107 29 107
Function coverage date bins:
(240..) days: 80.0 % 10 8 2 8
Branch coverage date bins:
(240..) days: 47.3 % 110 52 58 52

 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                 :                : 
 6241 teodor@sigaev.ru           12                 :UBC           0 : PG_FUNCTION_INFO_V1(gin_extract_trgm);
 4822 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);
 6241 teodor@sigaev.ru           15                 :              4 : PG_FUNCTION_INFO_V1(gin_trgm_consistent);
 3191                            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
 6241 teodor@sigaev.ru           24                 :UBC           0 : gin_extract_trgm(PG_FUNCTION_ARGS)
                                 25                 :                : {
 4805 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
 4822 tgl@sss.pgh.pa.us          35                 :CBC        2404 : gin_extract_value_trgm(PG_FUNCTION_ARGS)
                                 36                 :                : {
 2590 noah@leadboat.com          37                 :           2404 :     text       *val = (text *) PG_GETARG_TEXT_PP(0);
 5995 bruce@momjian.us           38                 :           2404 :     int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
                                 39                 :           2404 :     Datum      *entries = NULL;
                                 40                 :                :     TRGM       *trg;
                                 41                 :                :     int32       trglen;
                                 42                 :                : 
 6241 teodor@sigaev.ru           43                 :           2404 :     *nentries = 0;
                                 44                 :                : 
 2590 noah@leadboat.com          45   [ -  +  -  -  :           2404 :     trg = generate_trgm(VARDATA_ANY(val), VARSIZE_ANY_EXHDR(val));
                                     -  -  -  -  +  
                                           -  +  - ]
 6241 teodor@sigaev.ru           46                 :           2404 :     trglen = ARRNELEM(trg);
                                 47                 :                : 
                                 48         [ +  - ]:           2404 :     if (trglen > 0)
                                 49                 :                :     {
                                 50                 :                :         trgm       *ptr;
                                 51                 :                :         int32       i;
                                 52                 :                : 
 4844 tgl@sss.pgh.pa.us          53                 :           2404 :         *nentries = trglen;
 6241 teodor@sigaev.ru           54                 :           2404 :         entries = (Datum *) palloc(sizeof(Datum) * trglen);
                                 55                 :                : 
                                 56                 :           2404 :         ptr = GETARR(trg);
 4844 tgl@sss.pgh.pa.us          57         [ +  + ]:          35631 :         for (i = 0; i < trglen; i++)
                                 58                 :                :         {
 4753 bruce@momjian.us           59                 :          33227 :             int32       item = trgm2int(ptr);
                                 60                 :                : 
 4844 tgl@sss.pgh.pa.us          61                 :          33227 :             entries[i] = Int32GetDatum(item);
 6241 teodor@sigaev.ru           62                 :          33227 :             ptr++;
                                 63                 :                :         }
                                 64                 :                :     }
                                 65                 :                : 
                                 66                 :           2404 :     PG_RETURN_POINTER(entries);
                                 67                 :                : }
                                 68                 :                : 
                                 69                 :                : Datum
 4822 tgl@sss.pgh.pa.us          70                 :            172 : gin_extract_query_trgm(PG_FUNCTION_ARGS)
                                 71                 :                : {
 2590 noah@leadboat.com          72                 :            172 :     text       *val = (text *) PG_GETARG_TEXT_PP(0);
 4822 tgl@sss.pgh.pa.us          73                 :            172 :     int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
                                 74                 :            172 :     StrategyNumber strategy = PG_GETARG_UINT16(2);
                                 75                 :                : 
                                 76                 :                :     /* bool   **pmatch = (bool **) PG_GETARG_POINTER(3); */
 4023                            77                 :            172 :     Pointer   **extra_data = (Pointer **) PG_GETARG_POINTER(4);
                                 78                 :                : 
                                 79                 :                :     /* bool   **nullFlags = (bool **) PG_GETARG_POINTER(5); */
 4753 bruce@momjian.us           80                 :            172 :     int32      *searchMode = (int32 *) PG_GETARG_POINTER(6);
 4822 tgl@sss.pgh.pa.us          81                 :            172 :     Datum      *entries = NULL;
                                 82                 :                :     TRGM       *trg;
                                 83                 :                :     int32       trglen;
                                 84                 :                :     trgm       *ptr;
                                 85                 :                :     TrgmPackedGraph *graph;
                                 86                 :                :     int32       i;
                                 87                 :                : 
                                 88   [ +  +  +  - ]:            172 :     switch (strategy)
                                 89                 :                :     {
                                 90                 :             80 :         case SimilarityStrategyNumber:
                                 91                 :                :         case WordSimilarityStrategyNumber:
                                 92                 :                :         case StrictWordSimilarityStrategyNumber:
                                 93                 :                :         case EqualStrategyNumber:
 2590 noah@leadboat.com          94   [ -  +  -  -  :             80 :             trg = generate_trgm(VARDATA_ANY(val), VARSIZE_ANY_EXHDR(val));
                                     -  -  -  -  -  
                                           +  -  + ]
 4822 tgl@sss.pgh.pa.us          95                 :             80 :             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                 :                :              */
 2590 noah@leadboat.com         107         [ -  + ]:             48 :             trg = generate_wildcard_trgm(VARDATA_ANY(val),
                                108   [ -  +  -  -  :             48 :                                          VARSIZE_ANY_EXHDR(val));
                                     -  -  -  -  -  
                                                 + ]
 4822 tgl@sss.pgh.pa.us         109                 :             48 :             break;
 4023                           110                 :             44 :         case RegExpICaseStrategyNumber:
                                111                 :                : #ifndef IGNORECASE
                                112                 :                :             elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
                                113                 :                : #endif
                                114                 :                :             /* FALL THRU */
                                115                 :                :         case RegExpStrategyNumber:
 4022                           116                 :             44 :             trg = createTrgmNFA(val, PG_GET_COLLATION(),
                                117                 :                :                                 &graph, CurrentMemoryContext);
 4023                           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);
                                126                 :             34 :                 *extra_data = (Pointer *) palloc(sizeof(Pointer) * trglen);
                                127         [ +  + ]:            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;
 4822 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                 :                : 
 4822 tgl@sss.pgh.pa.us         144                 :CBC         162 :     trglen = ARRNELEM(trg);
                                145                 :            162 :     *nentries = trglen;
                                146                 :                : 
                                147         [ +  + ]:            162 :     if (trglen > 0)
                                148                 :                :     {
                                149                 :            138 :         entries = (Datum *) palloc(sizeof(Datum) * trglen);
                                150                 :            138 :         ptr = GETARR(trg);
                                151         [ +  + ]:           1684 :         for (i = 0; i < trglen; i++)
                                152                 :                :         {
 4753 bruce@momjian.us          153                 :           1546 :             int32       item = trgm2int(ptr);
                                154                 :                : 
 4822 tgl@sss.pgh.pa.us         155                 :           1546 :             entries[i] = Int32GetDatum(item);
                                156                 :           1546 :             ptr++;
                                157                 :                :         }
                                158                 :                :     }
                                159                 :                : 
                                160                 :                :     /*
                                161                 :                :      * If no trigram was extracted then we have to scan all the index.
                                162                 :                :      */
                                163         [ +  + ]:            162 :     if (trglen == 0)
                                164                 :             24 :         *searchMode = GIN_SEARCH_MODE_ALL;
                                165                 :                : 
                                166                 :            162 :     PG_RETURN_POINTER(entries);
                                167                 :                : }
                                168                 :                : 
                                169                 :                : Datum
 6241 teodor@sigaev.ru          170                 :              8 : gin_trgm_consistent(PG_FUNCTION_ARGS)
                                171                 :                : {
 5995 bruce@momjian.us          172                 :              8 :     bool       *check = (bool *) PG_GETARG_POINTER(0);
 4822 tgl@sss.pgh.pa.us         173                 :              8 :     StrategyNumber strategy = PG_GETARG_UINT16(1);
                                174                 :                : 
                                175                 :                :     /* text    *query = PG_GETARG_TEXT_PP(2); */
 4844                           176                 :              8 :     int32       nkeys = PG_GETARG_INT32(3);
 4023                           177                 :              8 :     Pointer    *extra_data = (Pointer *) PG_GETARG_POINTER(4);
 5499                           178                 :              8 :     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 */
 5844                           185                 :              8 :     *recheck = true;
                                186                 :                : 
 4822                           187   [ -  +  -  - ]:              8 :     switch (strategy)
                                188                 :                :     {
 4822 tgl@sss.pgh.pa.us         189                 :UBC           0 :         case SimilarityStrategyNumber:
                                190                 :                :         case WordSimilarityStrategyNumber:
                                191                 :                :         case StrictWordSimilarityStrategyNumber:
 2216 teodor@sigaev.ru          192                 :              0 :             nlimit = index_strategy_get_limit(strategy);
                                193                 :                : 
                                194                 :                :             /* Count the matches */
 4822 tgl@sss.pgh.pa.us         195                 :              0 :             ntrue = 0;
                                196         [ #  # ]:              0 :             for (i = 0; i < nkeys; i++)
                                197                 :                :             {
                                198         [ #  # ]:              0 :                 if (check[i])
                                199                 :              0 :                     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                 :                :              */
 2951 teodor@sigaev.ru          217         [ #  # ]:              0 :             res = (nkeys == 0) ? false :
                                218         [ #  # ]:              0 :                 (((((float4) ntrue) / ((float4) nkeys))) >= nlimit);
 4822 tgl@sss.pgh.pa.us         219                 :              0 :             break;
 4822 tgl@sss.pgh.pa.us         220                 :CBC           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                 :                :                 {
 4822 tgl@sss.pgh.pa.us         233                 :UBC           0 :                     res = false;
                                234                 :              0 :                     break;
                                235                 :                :                 }
                                236                 :                :             }
 4822 tgl@sss.pgh.pa.us         237                 :CBC           8 :             break;
 4023 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
                                250                 :              0 :                 res = trigramsMatchGraph((TrgmPackedGraph *) extra_data[0],
                                251                 :                :                                          check);
                                252                 :              0 :             break;
 4822                           253                 :              0 :         default:
                                254         [ #  # ]:              0 :             elog(ERROR, "unrecognized strategy number: %d", strategy);
                                255                 :                :             res = false;        /* keep compiler quiet */
                                256                 :                :             break;
                                257                 :                :     }
                                258                 :                : 
 6241 teodor@sigaev.ru          259                 :CBC           8 :     PG_RETURN_BOOL(res);
                                260                 :                : }
                                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
 3191                           269                 :          14358 : gin_trgm_triconsistent(PG_FUNCTION_ARGS)
                                270                 :                : {
 2866 rhaas@postgresql.org      271                 :          14358 :     GinTernaryValue *check = (GinTernaryValue *) PG_GETARG_POINTER(0);
 3191 teodor@sigaev.ru          272                 :          14358 :     StrategyNumber strategy = PG_GETARG_UINT16(1);
                                273                 :                : 
                                274                 :                :     /* text    *query = PG_GETARG_TEXT_PP(2); */
                                275                 :          14358 :     int32       nkeys = PG_GETARG_INT32(3);
                                276                 :          14358 :     Pointer    *extra_data = (Pointer *) PG_GETARG_POINTER(4);
 2866 rhaas@postgresql.org      277                 :          14358 :     GinTernaryValue res = GIN_MAYBE;
                                278                 :                :     int32       i,
                                279                 :                :                 ntrue;
                                280                 :                :     bool       *boolcheck;
                                281                 :                :     double      nlimit;
                                282                 :                : 
 3191 teodor@sigaev.ru          283   [ +  +  +  - ]:          14358 :     switch (strategy)
                                284                 :                :     {
                                285                 :           8191 :         case SimilarityStrategyNumber:
                                286                 :                :         case WordSimilarityStrategyNumber:
                                287                 :                :         case StrictWordSimilarityStrategyNumber:
 2216                           288                 :           8191 :             nlimit = index_strategy_get_limit(strategy);
                                289                 :                : 
                                290                 :                :             /* Count the matches */
 3191                           291                 :           8191 :             ntrue = 0;
                                292         [ +  + ]:          86909 :             for (i = 0; i < nkeys; i++)
                                293                 :                :             {
                                294         [ +  + ]:          78718 :                 if (check[i] != GIN_FALSE)
                                295                 :          33172 :                     ntrue++;
                                296                 :                :             }
                                297                 :                : 
                                298                 :                :             /*
                                299                 :                :              * See comment in gin_trgm_consistent() about * upper bound
                                300                 :                :              * formula
                                301                 :                :              */
 2951                           302         [ +  - ]:          16382 :             res = (nkeys == 0)
                                303         [ +  + ]:           8191 :                 ? GIN_FALSE : (((((float4) ntrue) / ((float4) nkeys)) >= nlimit)
                                304                 :                :                                ? GIN_MAYBE : GIN_FALSE);
 3191                           305                 :           8191 :             break;
                                306                 :           4046 :         case ILikeStrategyNumber:
                                307                 :                : #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                 :           4046 :             res = GIN_MAYBE;
                                315         [ +  + ]:           8182 :             for (i = 0; i < nkeys; i++)
                                316                 :                :             {
                                317         [ +  + ]:           4156 :                 if (check[i] == GIN_FALSE)
                                318                 :                :                 {
                                319                 :             20 :                     res = GIN_FALSE;
                                320                 :             20 :                     break;
                                321                 :                :                 }
                                322                 :                :             }
                                323                 :           4046 :             break;
                                324                 :           2121 :         case RegExpICaseStrategyNumber:
                                325                 :                : #ifndef IGNORECASE
                                326                 :                :             elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
                                327                 :                : #endif
                                328                 :                :             /* FALL THRU */
                                329                 :                :         case RegExpStrategyNumber:
                                330         [ +  + ]:           2121 :             if (nkeys < 1)
                                331                 :                :             {
                                332                 :                :                 /* Regex processing gave no result: do full index scan */
                                333                 :            736 :                 res = GIN_MAYBE;
                                334                 :                :             }
                                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                 :           1385 :                 boolcheck = (bool *) palloc(sizeof(bool) * nkeys);
                                343         [ +  + ]:         319289 :                 for (i = 0; i < nkeys; i++)
                                344                 :         317904 :                     boolcheck[i] = (check[i] != GIN_FALSE);
                                345         [ +  + ]:           1385 :                 if (!trigramsMatchGraph((TrgmPackedGraph *) extra_data[0],
                                346                 :                :                                         boolcheck))
                                347                 :              6 :                     res = GIN_FALSE;
                                348                 :           1385 :                 pfree(boolcheck);
                                349                 :                :             }
                                350                 :           2121 :             break;
 3191 teodor@sigaev.ru          351                 :UBC           0 :         default:
                                352         [ #  # ]:              0 :             elog(ERROR, "unrecognized strategy number: %d", strategy);
                                353                 :                :             res = GIN_FALSE;    /* keep compiler quiet */
                                354                 :                :             break;
                                355                 :                :     }
                                356                 :                : 
                                357                 :                :     /* All cases served by this function are inexact */
 3191 teodor@sigaev.ru          358         [ -  + ]:CBC       14358 :     Assert(res != GIN_TRUE);
                                359                 :          14358 :     PG_RETURN_GIN_TERNARY_VALUE(res);
                                360                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622