LCOV - code coverage report
Current view: top level - contrib/hstore - hstore_gin.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 94.1 % 85 80
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 7 7
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 75.0 % 56 42

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * contrib/hstore/hstore_gin.c
       3                 :             :  */
       4                 :             : #include "postgres.h"
       5                 :             : 
       6                 :             : #include "access/gin.h"
       7                 :             : #include "access/stratnum.h"
       8                 :             : #include "catalog/pg_type.h"
       9                 :             : 
      10                 :             : #include "hstore.h"
      11                 :             : 
      12                 :             : 
      13                 :             : /*
      14                 :             :  * When using a GIN index for hstore, we choose to index both keys and values.
      15                 :             :  * The storage format is "text" values, with K, V, or N prepended to the string
      16                 :             :  * to indicate key, value, or null values.  (As of 9.1 it might be better to
      17                 :             :  * store null values as nulls, but we'll keep it this way for on-disk
      18                 :             :  * compatibility.)
      19                 :             :  */
      20                 :             : #define KEYFLAG     'K'
      21                 :             : #define VALFLAG     'V'
      22                 :             : #define NULLFLAG    'N'
      23                 :             : 
      24                 :           8 : PG_FUNCTION_INFO_V1(gin_extract_hstore);
      25                 :             : 
      26                 :             : /* Build an indexable text value */
      27                 :             : static text *
      28                 :        9588 : makeitem(char *str, int len, char flag)
      29                 :             : {
      30                 :             :     text       *item;
      31                 :             : 
      32                 :        9588 :     item = (text *) palloc(VARHDRSZ + len + 1);
      33                 :        9588 :     SET_VARSIZE(item, VARHDRSZ + len + 1);
      34                 :             : 
      35                 :        9588 :     *VARDATA(item) = flag;
      36                 :             : 
      37   [ +  +  +  - ]:        9588 :     if (str && len > 0)
      38                 :        9585 :         memcpy(VARDATA(item) + 1, str, len);
      39                 :             : 
      40                 :        9588 :     return item;
      41                 :             : }
      42                 :             : 
      43                 :             : Datum
      44                 :        1007 : gin_extract_hstore(PG_FUNCTION_ARGS)
      45                 :             : {
      46                 :        1007 :     HStore     *hs = PG_GETARG_HSTORE_P(0);
      47                 :        1007 :     int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
      48                 :        1007 :     Datum      *entries = NULL;
      49                 :        1007 :     HEntry     *hsent = ARRPTR(hs);
      50                 :        1007 :     char       *ptr = STRPTR(hs);
      51                 :        1007 :     int         count = HS_COUNT(hs);
      52                 :             :     int         i;
      53                 :             : 
      54                 :        1007 :     *nentries = 2 * count;
      55         [ +  + ]:        1007 :     if (count)
      56                 :         890 :         entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
      57                 :             : 
      58         [ +  + ]:        5796 :     for (i = 0; i < count; ++i)
      59                 :             :     {
      60                 :             :         text       *item;
      61                 :             : 
      62         [ +  + ]:        4789 :         item = makeitem(HSTORE_KEY(hsent, ptr, i),
      63         [ +  + ]:        4789 :                         HSTORE_KEYLEN(hsent, i),
      64                 :             :                         KEYFLAG);
      65                 :        4789 :         entries[2 * i] = PointerGetDatum(item);
      66                 :             : 
      67         [ +  + ]:        4789 :         if (HSTORE_VALISNULL(hsent, i))
      68                 :           3 :             item = makeitem(NULL, 0, NULLFLAG);
      69                 :             :         else
      70         [ +  - ]:        4786 :             item = makeitem(HSTORE_VAL(hsent, ptr, i),
      71         [ -  + ]:        4786 :                             HSTORE_VALLEN(hsent, i),
      72                 :             :                             VALFLAG);
      73                 :        4789 :         entries[2 * i + 1] = PointerGetDatum(item);
      74                 :             :     }
      75                 :             : 
      76                 :        1007 :     PG_RETURN_POINTER(entries);
      77                 :             : }
      78                 :             : 
      79                 :           8 : PG_FUNCTION_INFO_V1(gin_extract_hstore_query);
      80                 :             : 
      81                 :             : Datum
      82                 :          12 : gin_extract_hstore_query(PG_FUNCTION_ARGS)
      83                 :             : {
      84                 :          12 :     int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
      85                 :          12 :     StrategyNumber strategy = PG_GETARG_UINT16(2);
      86                 :          12 :     int32      *searchMode = (int32 *) PG_GETARG_POINTER(6);
      87                 :             :     Datum      *entries;
      88                 :             : 
      89         [ +  + ]:          12 :     if (strategy == HStoreContainsStrategyNumber)
      90                 :             :     {
      91                 :             :         /* Query is an hstore, so just apply gin_extract_hstore... */
      92                 :             :         entries = (Datum *)
      93                 :           6 :             DatumGetPointer(DirectFunctionCall2(gin_extract_hstore,
      94                 :             :                                                 PG_GETARG_DATUM(0),
      95                 :             :                                                 PointerGetDatum(nentries)));
      96                 :             :         /* ... except that "contains {}" requires a full index scan */
      97         [ -  + ]:           6 :         if (entries == NULL)
      98                 :           0 :             *searchMode = GIN_SEARCH_MODE_ALL;
      99                 :             :     }
     100         [ +  + ]:           6 :     else if (strategy == HStoreExistsStrategyNumber)
     101                 :             :     {
     102                 :           2 :         text       *query = PG_GETARG_TEXT_PP(0);
     103                 :             :         text       *item;
     104                 :             : 
     105                 :           2 :         *nentries = 1;
     106                 :           2 :         entries = (Datum *) palloc(sizeof(Datum));
     107                 :           2 :         item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query), KEYFLAG);
     108                 :           2 :         entries[0] = PointerGetDatum(item);
     109                 :             :     }
     110   [ +  +  +  - ]:           4 :     else if (strategy == HStoreExistsAnyStrategyNumber ||
     111                 :             :              strategy == HStoreExistsAllStrategyNumber)
     112                 :           4 :     {
     113                 :           4 :         ArrayType  *query = PG_GETARG_ARRAYTYPE_P(0);
     114                 :             :         Datum      *key_datums;
     115                 :             :         bool       *key_nulls;
     116                 :             :         int         key_count;
     117                 :             :         int         i,
     118                 :             :                     j;
     119                 :             :         text       *item;
     120                 :             : 
     121                 :           4 :         deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
     122                 :             : 
     123                 :           4 :         entries = (Datum *) palloc(sizeof(Datum) * key_count);
     124                 :             : 
     125         [ +  + ]:          12 :         for (i = 0, j = 0; i < key_count; ++i)
     126                 :             :         {
     127                 :             :             /* Nulls in the array are ignored, cf hstoreArrayToPairs */
     128         [ -  + ]:           8 :             if (key_nulls[i])
     129                 :           0 :                 continue;
     130                 :           8 :             item = makeitem(VARDATA(DatumGetPointer(key_datums[i])), VARSIZE(DatumGetPointer(key_datums[i])) - VARHDRSZ, KEYFLAG);
     131                 :           8 :             entries[j++] = PointerGetDatum(item);
     132                 :             :         }
     133                 :             : 
     134                 :           4 :         *nentries = j;
     135                 :             :         /* ExistsAll with no keys should match everything */
     136   [ -  +  -  - ]:           4 :         if (j == 0 && strategy == HStoreExistsAllStrategyNumber)
     137                 :           0 :             *searchMode = GIN_SEARCH_MODE_ALL;
     138                 :             :     }
     139                 :             :     else
     140                 :             :     {
     141         [ #  # ]:           0 :         elog(ERROR, "unrecognized strategy number: %d", strategy);
     142                 :             :         entries = NULL;         /* keep compiler quiet */
     143                 :             :     }
     144                 :             : 
     145                 :          12 :     PG_RETURN_POINTER(entries);
     146                 :             : }
     147                 :             : 
     148                 :           8 : PG_FUNCTION_INFO_V1(gin_consistent_hstore);
     149                 :             : 
     150                 :             : Datum
     151                 :         955 : gin_consistent_hstore(PG_FUNCTION_ARGS)
     152                 :             : {
     153                 :         955 :     bool       *check = (bool *) PG_GETARG_POINTER(0);
     154                 :         955 :     StrategyNumber strategy = PG_GETARG_UINT16(1);
     155                 :             : #ifdef NOT_USED
     156                 :             :     HStore     *query = PG_GETARG_HSTORE_P(2);
     157                 :             : #endif
     158                 :         955 :     int32       nkeys = PG_GETARG_INT32(3);
     159                 :             : #ifdef NOT_USED
     160                 :             :     Pointer    *extra_data = (Pointer *) PG_GETARG_POINTER(4);
     161                 :             : #endif
     162                 :         955 :     bool       *recheck = (bool *) PG_GETARG_POINTER(5);
     163                 :         955 :     bool        res = true;
     164                 :             :     int32       i;
     165                 :             : 
     166         [ +  + ]:         955 :     if (strategy == HStoreContainsStrategyNumber)
     167                 :             :     {
     168                 :             :         /*
     169                 :             :          * Index doesn't have information about correspondence of keys and
     170                 :             :          * values, so we need recheck.  However, if not all the keys are
     171                 :             :          * present, we can fail at once.
     172                 :             :          */
     173                 :         235 :         *recheck = true;
     174         [ +  + ]:         375 :         for (i = 0; i < nkeys; i++)
     175                 :             :         {
     176         [ +  + ]:         339 :             if (!check[i])
     177                 :             :             {
     178                 :         199 :                 res = false;
     179                 :         199 :                 break;
     180                 :             :             }
     181                 :             :         }
     182                 :             :     }
     183         [ +  + ]:         720 :     else if (strategy == HStoreExistsStrategyNumber)
     184                 :             :     {
     185                 :             :         /* Existence of key is guaranteed in default search mode */
     186                 :         194 :         *recheck = false;
     187                 :         194 :         res = true;
     188                 :             :     }
     189         [ +  + ]:         526 :     else if (strategy == HStoreExistsAnyStrategyNumber)
     190                 :             :     {
     191                 :             :         /* Existence of key is guaranteed in default search mode */
     192                 :         339 :         *recheck = false;
     193                 :         339 :         res = true;
     194                 :             :     }
     195         [ +  - ]:         187 :     else if (strategy == HStoreExistsAllStrategyNumber)
     196                 :             :     {
     197                 :             :         /* Testing for all the keys being present gives an exact result */
     198                 :         187 :         *recheck = false;
     199         [ +  + ]:         272 :         for (i = 0; i < nkeys; i++)
     200                 :             :         {
     201         [ +  + ]:         230 :             if (!check[i])
     202                 :             :             {
     203                 :         145 :                 res = false;
     204                 :         145 :                 break;
     205                 :             :             }
     206                 :             :         }
     207                 :             :     }
     208                 :             :     else
     209         [ #  # ]:           0 :         elog(ERROR, "unrecognized strategy number: %d", strategy);
     210                 :             : 
     211                 :         955 :     PG_RETURN_BOOL(res);
     212                 :             : }
        

Generated by: LCOV version 2.0-1