LCOV - code coverage report
Current view: top level - contrib/hstore - hstore_gin.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 81 86 94.2 %
Date: 2019-06-18 07:06:57 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          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          16 : PG_FUNCTION_INFO_V1(gin_extract_hstore);
      25             : 
      26             : /* Build an indexable text value */
      27             : static text *
      28       19176 : makeitem(char *str, int len, char flag)
      29             : {
      30             :     text       *item;
      31             : 
      32       19176 :     item = (text *) palloc(VARHDRSZ + len + 1);
      33       19176 :     SET_VARSIZE(item, VARHDRSZ + len + 1);
      34             : 
      35       19176 :     *VARDATA(item) = flag;
      36             : 
      37       19176 :     if (str && len > 0)
      38       19170 :         memcpy(VARDATA(item) + 1, str, len);
      39             : 
      40       19176 :     return item;
      41             : }
      42             : 
      43             : Datum
      44        2014 : gin_extract_hstore(PG_FUNCTION_ARGS)
      45             : {
      46        2014 :     HStore     *hs = PG_GETARG_HSTORE_P(0);
      47        2014 :     int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
      48        2014 :     Datum      *entries = NULL;
      49        2014 :     HEntry     *hsent = ARRPTR(hs);
      50        2014 :     char       *ptr = STRPTR(hs);
      51        2014 :     int         count = HS_COUNT(hs);
      52             :     int         i;
      53             : 
      54        2014 :     *nentries = 2 * count;
      55        2014 :     if (count)
      56        1780 :         entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
      57             : 
      58       11592 :     for (i = 0; i < count; ++i)
      59             :     {
      60             :         text       *item;
      61             : 
      62       19156 :         item = makeitem(HSTORE_KEY(hsent, ptr, i),
      63       19156 :                         HSTORE_KEYLEN(hsent, i),
      64             :                         KEYFLAG);
      65        9578 :         entries[2 * i] = PointerGetDatum(item);
      66             : 
      67        9578 :         if (HSTORE_VALISNULL(hsent, i))
      68           6 :             item = makeitem(NULL, 0, NULLFLAG);
      69             :         else
      70       19144 :             item = makeitem(HSTORE_VAL(hsent, ptr, i),
      71       19144 :                             HSTORE_VALLEN(hsent, i),
      72             :                             VALFLAG);
      73        9578 :         entries[2 * i + 1] = PointerGetDatum(item);
      74             :     }
      75             : 
      76        2014 :     PG_RETURN_POINTER(entries);
      77             : }
      78             : 
      79          16 : PG_FUNCTION_INFO_V1(gin_extract_hstore_query);
      80             : 
      81             : Datum
      82          24 : gin_extract_hstore_query(PG_FUNCTION_ARGS)
      83             : {
      84          24 :     int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
      85          24 :     StrategyNumber strategy = PG_GETARG_UINT16(2);
      86          24 :     int32      *searchMode = (int32 *) PG_GETARG_POINTER(6);
      87             :     Datum      *entries;
      88             : 
      89          24 :     if (strategy == HStoreContainsStrategyNumber)
      90             :     {
      91             :         /* Query is an hstore, so just apply gin_extract_hstore... */
      92          12 :         entries = (Datum *)
      93          12 :             DatumGetPointer(DirectFunctionCall2(gin_extract_hstore,
      94             :                                                 PG_GETARG_DATUM(0),
      95             :                                                 PointerGetDatum(nentries)));
      96             :         /* ... except that "contains {}" requires a full index scan */
      97          12 :         if (entries == NULL)
      98           0 :             *searchMode = GIN_SEARCH_MODE_ALL;
      99             :     }
     100          12 :     else if (strategy == HStoreExistsStrategyNumber)
     101             :     {
     102           4 :         text       *query = PG_GETARG_TEXT_PP(0);
     103             :         text       *item;
     104             : 
     105           4 :         *nentries = 1;
     106           4 :         entries = (Datum *) palloc(sizeof(Datum));
     107           4 :         item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query), KEYFLAG);
     108           4 :         entries[0] = PointerGetDatum(item);
     109             :     }
     110           8 :     else if (strategy == HStoreExistsAnyStrategyNumber ||
     111             :              strategy == HStoreExistsAllStrategyNumber)
     112           8 :     {
     113           8 :         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           8 :         deconstruct_array(query,
     122             :                           TEXTOID, -1, false, 'i',
     123             :                           &key_datums, &key_nulls, &key_count);
     124             : 
     125           8 :         entries = (Datum *) palloc(sizeof(Datum) * key_count);
     126             : 
     127          24 :         for (i = 0, j = 0; i < key_count; ++i)
     128             :         {
     129             :             /* Nulls in the array are ignored, cf hstoreArrayToPairs */
     130          16 :             if (key_nulls[i])
     131           0 :                 continue;
     132          16 :             item = makeitem(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ, KEYFLAG);
     133          16 :             entries[j++] = PointerGetDatum(item);
     134             :         }
     135             : 
     136           8 :         *nentries = j;
     137             :         /* ExistsAll with no keys should match everything */
     138           8 :         if (j == 0 && strategy == HStoreExistsAllStrategyNumber)
     139           0 :             *searchMode = GIN_SEARCH_MODE_ALL;
     140             :     }
     141             :     else
     142             :     {
     143           0 :         elog(ERROR, "unrecognized strategy number: %d", strategy);
     144             :         entries = NULL;         /* keep compiler quiet */
     145             :     }
     146             : 
     147          24 :     PG_RETURN_POINTER(entries);
     148             : }
     149             : 
     150          16 : PG_FUNCTION_INFO_V1(gin_consistent_hstore);
     151             : 
     152             : Datum
     153        1910 : gin_consistent_hstore(PG_FUNCTION_ARGS)
     154             : {
     155        1910 :     bool       *check = (bool *) PG_GETARG_POINTER(0);
     156        1910 :     StrategyNumber strategy = PG_GETARG_UINT16(1);
     157             : 
     158             :     /* HStore      *query = PG_GETARG_HSTORE_P(2); */
     159        1910 :     int32       nkeys = PG_GETARG_INT32(3);
     160             : 
     161             :     /* Pointer     *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
     162        1910 :     bool       *recheck = (bool *) PG_GETARG_POINTER(5);
     163        1910 :     bool        res = true;
     164             :     int32       i;
     165             : 
     166        1910 :     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         470 :         *recheck = true;
     174         750 :         for (i = 0; i < nkeys; i++)
     175             :         {
     176         678 :             if (!check[i])
     177             :             {
     178         398 :                 res = false;
     179         398 :                 break;
     180             :             }
     181             :         }
     182             :     }
     183        1440 :     else if (strategy == HStoreExistsStrategyNumber)
     184             :     {
     185             :         /* Existence of key is guaranteed in default search mode */
     186         388 :         *recheck = false;
     187         388 :         res = true;
     188             :     }
     189        1052 :     else if (strategy == HStoreExistsAnyStrategyNumber)
     190             :     {
     191             :         /* Existence of key is guaranteed in default search mode */
     192         678 :         *recheck = false;
     193         678 :         res = true;
     194             :     }
     195         374 :     else if (strategy == HStoreExistsAllStrategyNumber)
     196             :     {
     197             :         /* Testing for all the keys being present gives an exact result */
     198         374 :         *recheck = false;
     199         544 :         for (i = 0; i < nkeys; i++)
     200             :         {
     201         460 :             if (!check[i])
     202             :             {
     203         290 :                 res = false;
     204         290 :                 break;
     205             :             }
     206             :         }
     207             :     }
     208             :     else
     209           0 :         elog(ERROR, "unrecognized strategy number: %d", strategy);
     210             : 
     211        1910 :     PG_RETURN_BOOL(res);
     212             : }

Generated by: LCOV version 1.13