LCOV - code coverage report
Current view: top level - contrib/ltree - _ltree_gist.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 88.6 % 271 240
Test Date: 2026-07-03 19:57:34 Functions: 96.0 % 25 24
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 63.4 % 145 92

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * contrib/ltree/_ltree_gist.c
       3                 :             :  *
       4                 :             :  *
       5                 :             :  * GiST support for ltree[]
       6                 :             :  * Teodor Sigaev <teodor@stack.net>
       7                 :             :  */
       8                 :             : #include "postgres.h"
       9                 :             : 
      10                 :             : #include "access/gist.h"
      11                 :             : #include "access/reloptions.h"
      12                 :             : #include "access/stratnum.h"
      13                 :             : #include "crc32.h"
      14                 :             : #include "ltree.h"
      15                 :             : #include "port/pg_bitutils.h"
      16                 :             : #include "utils/array.h"
      17                 :             : 
      18                 :           3 : PG_FUNCTION_INFO_V1(_ltree_compress);
      19                 :           3 : PG_FUNCTION_INFO_V1(_ltree_same);
      20                 :           3 : PG_FUNCTION_INFO_V1(_ltree_union);
      21                 :           3 : PG_FUNCTION_INFO_V1(_ltree_penalty);
      22                 :           3 : PG_FUNCTION_INFO_V1(_ltree_picksplit);
      23                 :           3 : PG_FUNCTION_INFO_V1(_ltree_consistent);
      24                 :           3 : PG_FUNCTION_INFO_V1(_ltree_gist_options);
      25                 :             : 
      26                 :             : #define GETENTRY(vec,pos) ((ltree_gist *) DatumGetPointer((vec)->vector[(pos)].key))
      27                 :             : #define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
      28                 :             : 
      29                 :             : #define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
      30                 :             : 
      31                 :             : 
      32                 :             : static void
      33                 :        7058 : hashing(BITVECP sign, ltree *t, int siglen)
      34                 :             : {
      35                 :        7058 :     int         tlen = t->numlevel;
      36                 :        7058 :     ltree_level *cur = LTREE_FIRST(t);
      37                 :             :     int         hash;
      38                 :             : 
      39         [ +  + ]:       53466 :     while (tlen > 0)
      40                 :             :     {
      41                 :       46408 :         hash = ltree_crc32_sz(cur->name, cur->len);
      42                 :       46408 :         AHASH(sign, hash, siglen);
      43                 :       46408 :         cur = LEVEL_NEXT(cur);
      44                 :       46408 :         tlen--;
      45                 :             :     }
      46                 :        7058 : }
      47                 :             : 
      48                 :             : Datum
      49                 :        6079 : _ltree_compress(PG_FUNCTION_ARGS)
      50                 :             : {
      51                 :        6079 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
      52                 :        6079 :     GISTENTRY  *retval = entry;
      53         [ +  - ]:        6079 :     int         siglen = LTREE_GET_ASIGLEN();
      54                 :             : 
      55         [ +  + ]:        6079 :     if (entry->leafkey)
      56                 :             :     {                           /* ltree */
      57                 :             :         ltree_gist *key;
      58                 :        2000 :         ArrayType  *val = DatumGetArrayTypeP(entry->key);
      59                 :        2000 :         int         num = ArrayGetNItems(ARR_NDIM(val), ARR_DIMS(val));
      60         [ -  + ]:        2000 :         ltree      *item = (ltree *) ARR_DATA_PTR(val);
      61                 :             : 
      62         [ -  + ]:        2000 :         if (ARR_NDIM(val) > 1)
      63         [ #  # ]:           0 :             ereport(ERROR,
      64                 :             :                     (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
      65                 :             :                      errmsg("array must be one-dimensional")));
      66         [ -  + ]:        2000 :         if (array_contains_nulls(val))
      67         [ #  # ]:           0 :             ereport(ERROR,
      68                 :             :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
      69                 :             :                      errmsg("array must not contain nulls")));
      70                 :             : 
      71                 :        2000 :         key = ltree_gist_alloc(false, NULL, siglen, NULL, NULL);
      72                 :             : 
      73         [ +  + ]:        9058 :         while (num > 0)
      74                 :             :         {
      75                 :        7058 :             hashing(LTG_SIGN(key), item, siglen);
      76                 :        7058 :             num--;
      77                 :        7058 :             item = NEXTVAL(item);
      78                 :             :         }
      79                 :             : 
      80                 :        2000 :         retval = palloc_object(GISTENTRY);
      81                 :        2000 :         gistentryinit(*retval, PointerGetDatum(key),
      82                 :             :                       entry->rel, entry->page,
      83                 :             :                       entry->offset, false);
      84                 :             :     }
      85         [ +  - ]:        4079 :     else if (!LTG_ISALLTRUE(DatumGetPointer(entry->key)))
      86                 :             :     {
      87                 :             :         int32       i;
      88                 :             :         ltree_gist *key;
      89                 :        4079 :         BITVECP     sign = LTG_SIGN(DatumGetPointer(entry->key));
      90                 :             : 
      91         [ +  - ]:        4079 :         ALOOPBYTE(siglen)
      92                 :             :         {
      93         [ +  - ]:        4079 :             if ((sign[i] & 0xff) != 0xff)
      94                 :        4079 :                 PG_RETURN_POINTER(retval);
      95                 :             :         }
      96                 :             : 
      97                 :           0 :         key = ltree_gist_alloc(true, sign, siglen, NULL, NULL);
      98                 :           0 :         retval = palloc_object(GISTENTRY);
      99                 :           0 :         gistentryinit(*retval, PointerGetDatum(key),
     100                 :             :                       entry->rel, entry->page,
     101                 :             :                       entry->offset, false);
     102                 :             :     }
     103                 :        2000 :     PG_RETURN_POINTER(retval);
     104                 :             : }
     105                 :             : 
     106                 :             : Datum
     107                 :        8152 : _ltree_same(PG_FUNCTION_ARGS)
     108                 :             : {
     109                 :        8152 :     ltree_gist *a = (ltree_gist *) PG_GETARG_POINTER(0);
     110                 :        8152 :     ltree_gist *b = (ltree_gist *) PG_GETARG_POINTER(1);
     111                 :        8152 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     112         [ +  - ]:        8152 :     int         siglen = LTREE_GET_ASIGLEN();
     113                 :             : 
     114   [ -  +  -  - ]:        8152 :     if (LTG_ISALLTRUE(a) && LTG_ISALLTRUE(b))
     115                 :           0 :         *result = true;
     116         [ -  + ]:        8152 :     else if (LTG_ISALLTRUE(a))
     117                 :           0 :         *result = false;
     118         [ -  + ]:        8152 :     else if (LTG_ISALLTRUE(b))
     119                 :           0 :         *result = false;
     120                 :             :     else
     121                 :             :     {
     122                 :             :         int32       i;
     123                 :        8152 :         BITVECP     sa = LTG_SIGN(a),
     124                 :        8152 :                     sb = LTG_SIGN(b);
     125                 :             : 
     126                 :        8152 :         *result = true;
     127         [ +  + ]:    11674569 :         ALOOPBYTE(siglen)
     128                 :             :         {
     129         [ +  + ]:    11668660 :             if (sa[i] != sb[i])
     130                 :             :             {
     131                 :        2243 :                 *result = false;
     132                 :        2243 :                 break;
     133                 :             :             }
     134                 :             :         }
     135                 :             :     }
     136                 :        8152 :     PG_RETURN_POINTER(result);
     137                 :             : }
     138                 :             : 
     139                 :             : static int32
     140                 :       16304 : unionkey(BITVECP sbase, ltree_gist *add, int siglen)
     141                 :             : {
     142                 :             :     int32       i;
     143                 :       16304 :     BITVECP     sadd = LTG_SIGN(add);
     144                 :             : 
     145         [ -  + ]:       16304 :     if (LTG_ISALLTRUE(add))
     146                 :           0 :         return 1;
     147                 :             : 
     148         [ +  + ]:    29586472 :     ALOOPBYTE(siglen)
     149                 :    29570168 :         sbase[i] |= sadd[i];
     150                 :       16304 :     return 0;
     151                 :             : }
     152                 :             : 
     153                 :             : Datum
     154                 :        8152 : _ltree_union(PG_FUNCTION_ARGS)
     155                 :             : {
     156                 :        8152 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     157                 :        8152 :     int        *size = (int *) PG_GETARG_POINTER(1);
     158         [ +  - ]:        8152 :     int         siglen = LTREE_GET_ASIGLEN();
     159                 :             :     int32       i;
     160                 :        8152 :     ltree_gist *result = ltree_gist_alloc(false, NULL, siglen, NULL, NULL);
     161                 :        8152 :     BITVECP     base = LTG_SIGN(result);
     162                 :             : 
     163         [ +  + ]:       24456 :     for (i = 0; i < entryvec->n; i++)
     164                 :             :     {
     165         [ -  + ]:       16304 :         if (unionkey(base, GETENTRY(entryvec, i), siglen))
     166                 :             :         {
     167                 :           0 :             result->flag |= LTG_ALLTRUE;
     168                 :           0 :             SET_VARSIZE(result, LTG_HDRSIZE);
     169                 :           0 :             break;
     170                 :             :         }
     171                 :             :     }
     172                 :             : 
     173                 :        8152 :     *size = VARSIZE(result);
     174                 :             : 
     175                 :        8152 :     PG_RETURN_POINTER(result);
     176                 :             : }
     177                 :             : 
     178                 :             : static int32
     179                 :           0 : sizebitvec(BITVECP sign, int siglen)
     180                 :             : {
     181                 :           0 :     return pg_popcount((const char *) sign, siglen);
     182                 :             : }
     183                 :             : 
     184                 :             : static int
     185                 :      126278 : hemdistsign(BITVECP a, BITVECP b, int siglen)
     186                 :             : {
     187                 :             :     int         i,
     188                 :             :                 diff,
     189                 :      126278 :                 dist = 0;
     190                 :             : 
     191         [ +  + ]:    60907342 :     ALOOPBYTE(siglen)
     192                 :             :     {
     193                 :    60781064 :         diff = (unsigned char) (a[i] ^ b[i]);
     194                 :             :         /* Using the popcount functions here isn't likely to win */
     195                 :    60781064 :         dist += pg_number_of_ones[diff];
     196                 :             :     }
     197                 :      126278 :     return dist;
     198                 :             : }
     199                 :             : 
     200                 :             : static int
     201                 :      126278 : hemdist(ltree_gist *a, ltree_gist *b, int siglen)
     202                 :             : {
     203         [ -  + ]:      126278 :     if (LTG_ISALLTRUE(a))
     204                 :             :     {
     205         [ #  # ]:           0 :         if (LTG_ISALLTRUE(b))
     206                 :           0 :             return 0;
     207                 :             :         else
     208                 :           0 :             return ASIGLENBIT(siglen) - sizebitvec(LTG_SIGN(b), siglen);
     209                 :             :     }
     210         [ -  + ]:      126278 :     else if (LTG_ISALLTRUE(b))
     211                 :           0 :         return ASIGLENBIT(siglen) - sizebitvec(LTG_SIGN(a), siglen);
     212                 :             : 
     213                 :      126278 :     return hemdistsign(LTG_SIGN(a), LTG_SIGN(b), siglen);
     214                 :             : }
     215                 :             : 
     216                 :             : 
     217                 :             : Datum
     218                 :       20033 : _ltree_penalty(PG_FUNCTION_ARGS)
     219                 :             : {
     220                 :       20033 :     ltree_gist *origval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     221                 :       20033 :     ltree_gist *newval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
     222                 :       20033 :     float      *penalty = (float *) PG_GETARG_POINTER(2);
     223         [ +  - ]:       20033 :     int         siglen = LTREE_GET_ASIGLEN();
     224                 :             : 
     225                 :       20033 :     *penalty = hemdist(origval, newval, siglen);
     226                 :       20033 :     PG_RETURN_POINTER(penalty);
     227                 :             : }
     228                 :             : 
     229                 :             : typedef struct
     230                 :             : {
     231                 :             :     OffsetNumber pos;
     232                 :             :     int32       cost;
     233                 :             : } SPLITCOST;
     234                 :             : 
     235                 :             : static int
     236                 :        8143 : comparecost(const void *a, const void *b)
     237                 :             : {
     238                 :        8143 :     return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
     239                 :             : }
     240                 :             : 
     241                 :             : Datum
     242                 :         918 : _ltree_picksplit(PG_FUNCTION_ARGS)
     243                 :             : {
     244                 :         918 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     245                 :         918 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     246         [ +  - ]:         918 :     int         siglen = LTREE_GET_ASIGLEN();
     247                 :             :     OffsetNumber k,
     248                 :             :                 j;
     249                 :             :     ltree_gist *datum_l,
     250                 :             :                *datum_r;
     251                 :             :     BITVECP     union_l,
     252                 :             :                 union_r;
     253                 :             :     int32       size_alpha,
     254                 :             :                 size_beta;
     255                 :             :     int32       size_waste,
     256                 :         918 :                 waste = -1;
     257                 :             :     int32       nbytes;
     258                 :         918 :     OffsetNumber seed_1 = 0,
     259                 :         918 :                 seed_2 = 0;
     260                 :             :     OffsetNumber *left,
     261                 :             :                *right;
     262                 :             :     OffsetNumber maxoff;
     263                 :             :     BITVECP     ptr;
     264                 :             :     int         i;
     265                 :             :     SPLITCOST  *costvector;
     266                 :             :     ltree_gist *_k,
     267                 :             :                *_j;
     268                 :             : 
     269                 :         918 :     maxoff = entryvec->n - 2;
     270                 :         918 :     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
     271                 :         918 :     v->spl_left = (OffsetNumber *) palloc(nbytes);
     272                 :         918 :     v->spl_right = (OffsetNumber *) palloc(nbytes);
     273                 :             : 
     274         [ +  + ]:        3987 :     for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
     275                 :             :     {
     276                 :        3069 :         _k = GETENTRY(entryvec, k);
     277         [ +  + ]:       93366 :         for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
     278                 :             :         {
     279                 :       90297 :             size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
     280         [ +  + ]:       90297 :             if (size_waste > waste)
     281                 :             :             {
     282                 :        1704 :                 waste = size_waste;
     283                 :        1704 :                 seed_1 = k;
     284                 :        1704 :                 seed_2 = j;
     285                 :             :             }
     286                 :             :         }
     287                 :             :     }
     288                 :             : 
     289                 :         918 :     left = v->spl_left;
     290                 :         918 :     v->spl_nleft = 0;
     291                 :         918 :     right = v->spl_right;
     292                 :         918 :     v->spl_nright = 0;
     293                 :             : 
     294   [ +  -  -  + ]:         918 :     if (seed_1 == 0 || seed_2 == 0)
     295                 :             :     {
     296                 :           0 :         seed_1 = 1;
     297                 :           0 :         seed_2 = 2;
     298                 :             :     }
     299                 :             : 
     300                 :             :     /* form initial .. */
     301                 :         918 :     datum_l = ltree_gist_alloc(LTG_ISALLTRUE(GETENTRY(entryvec, seed_1)),
     302                 :         918 :                                LTG_SIGN(GETENTRY(entryvec, seed_1)),
     303                 :             :                                siglen, NULL, NULL);
     304                 :             : 
     305                 :         918 :     datum_r = ltree_gist_alloc(LTG_ISALLTRUE(GETENTRY(entryvec, seed_2)),
     306                 :         918 :                                LTG_SIGN(GETENTRY(entryvec, seed_2)),
     307                 :             :                                siglen, NULL, NULL);
     308                 :             : 
     309                 :         918 :     maxoff = OffsetNumberNext(maxoff);
     310                 :             :     /* sort before ... */
     311                 :         918 :     costvector = palloc_array(SPLITCOST, maxoff);
     312         [ +  + ]:        5823 :     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
     313                 :             :     {
     314                 :        4905 :         costvector[j - 1].pos = j;
     315                 :        4905 :         _j = GETENTRY(entryvec, j);
     316                 :        4905 :         size_alpha = hemdist(datum_l, _j, siglen);
     317                 :        4905 :         size_beta = hemdist(datum_r, _j, siglen);
     318                 :        4905 :         costvector[j - 1].cost = abs(size_alpha - size_beta);
     319                 :             :     }
     320                 :         918 :     qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
     321                 :             : 
     322                 :         918 :     union_l = LTG_SIGN(datum_l);
     323                 :         918 :     union_r = LTG_SIGN(datum_r);
     324                 :             : 
     325         [ +  + ]:        5823 :     for (k = 0; k < maxoff; k++)
     326                 :             :     {
     327                 :        4905 :         j = costvector[k].pos;
     328         [ +  + ]:        4905 :         if (j == seed_1)
     329                 :             :         {
     330                 :         918 :             *left++ = j;
     331                 :         918 :             v->spl_nleft++;
     332                 :         918 :             continue;
     333                 :             :         }
     334         [ +  + ]:        3987 :         else if (j == seed_2)
     335                 :             :         {
     336                 :         918 :             *right++ = j;
     337                 :         918 :             v->spl_nright++;
     338                 :         918 :             continue;
     339                 :             :         }
     340                 :        3069 :         _j = GETENTRY(entryvec, j);
     341                 :        3069 :         size_alpha = hemdist(datum_l, _j, siglen);
     342                 :        3069 :         size_beta = hemdist(datum_r, _j, siglen);
     343                 :             : 
     344         [ +  + ]:        3069 :         if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
     345                 :             :         {
     346   [ +  -  -  + ]:        1446 :             if (LTG_ISALLTRUE(datum_l) || LTG_ISALLTRUE(_j))
     347                 :             :             {
     348         [ #  # ]:           0 :                 if (!LTG_ISALLTRUE(datum_l))
     349                 :           0 :                     memset(union_l, 0xff, siglen);
     350                 :             :             }
     351                 :             :             else
     352                 :             :             {
     353                 :        1446 :                 ptr = LTG_SIGN(_j);
     354         [ +  + ]:     1712586 :                 ALOOPBYTE(siglen)
     355                 :     1711140 :                     union_l[i] |= ptr[i];
     356                 :             :             }
     357                 :        1446 :             *left++ = j;
     358                 :        1446 :             v->spl_nleft++;
     359                 :             :         }
     360                 :             :         else
     361                 :             :         {
     362   [ +  -  -  + ]:        1623 :             if (LTG_ISALLTRUE(datum_r) || LTG_ISALLTRUE(_j))
     363                 :             :             {
     364         [ #  # ]:           0 :                 if (!LTG_ISALLTRUE(datum_r))
     365                 :           0 :                     memset(union_r, 0xff, siglen);
     366                 :             :             }
     367                 :             :             else
     368                 :             :             {
     369                 :        1623 :                 ptr = LTG_SIGN(_j);
     370         [ +  + ]:     2005143 :                 ALOOPBYTE(siglen)
     371                 :     2003520 :                     union_r[i] |= ptr[i];
     372                 :             :             }
     373                 :        1623 :             *right++ = j;
     374                 :        1623 :             v->spl_nright++;
     375                 :             :         }
     376                 :             :     }
     377                 :             : 
     378                 :         918 :     *right = *left = FirstOffsetNumber;
     379                 :             : 
     380                 :         918 :     v->spl_ldatum = PointerGetDatum(datum_l);
     381                 :         918 :     v->spl_rdatum = PointerGetDatum(datum_r);
     382                 :             : 
     383                 :         918 :     PG_RETURN_POINTER(v);
     384                 :             : }
     385                 :             : 
     386                 :             : static bool
     387                 :        2625 : gist_te(ltree_gist *key, ltree *query, int siglen)
     388                 :             : {
     389                 :        2625 :     ltree_level *curq = LTREE_FIRST(query);
     390                 :        2625 :     BITVECP     sign = LTG_SIGN(key);
     391                 :        2625 :     int         qlen = query->numlevel;
     392                 :             :     unsigned int hv;
     393                 :             : 
     394         [ -  + ]:        2625 :     if (LTG_ISALLTRUE(key))
     395                 :           0 :         return true;
     396                 :             : 
     397         [ +  + ]:        8838 :     while (qlen > 0)
     398                 :             :     {
     399                 :        6767 :         hv = ltree_crc32_sz(curq->name, curq->len);
     400         [ +  + ]:        6767 :         if (!GETBIT(sign, AHASHVAL(hv, siglen)))
     401                 :         554 :             return false;
     402                 :        6213 :         curq = LEVEL_NEXT(curq);
     403                 :        6213 :         qlen--;
     404                 :             :     }
     405                 :             : 
     406                 :        2071 :     return true;
     407                 :             : }
     408                 :             : 
     409                 :             : typedef struct LtreeSignature
     410                 :             : {
     411                 :             :     BITVECP     sign;
     412                 :             :     int         siglen;
     413                 :             : } LtreeSignature;
     414                 :             : 
     415                 :             : static bool
     416                 :        3813 : checkcondition_bit(void *cxt, ITEM *val)
     417                 :             : {
     418                 :        3813 :     LtreeSignature *sig = cxt;
     419                 :             : 
     420         [ +  - ]:        3813 :     return (FLG_CANLOOKSIGN(val->flag)) ? GETBIT(sig->sign, AHASHVAL(val->val, sig->siglen)) : true;
     421                 :             : }
     422                 :             : 
     423                 :             : static bool
     424                 :        2257 : gist_qtxt(ltree_gist *key, ltxtquery *query, int siglen)
     425                 :             : {
     426                 :             :     LtreeSignature sig;
     427                 :             : 
     428         [ -  + ]:        2257 :     if (LTG_ISALLTRUE(key))
     429                 :           0 :         return true;
     430                 :             : 
     431                 :        2257 :     sig.sign = LTG_SIGN(key);
     432                 :        2257 :     sig.siglen = siglen;
     433                 :             : 
     434                 :        2257 :     return ltree_execute(GETQUERY(query),
     435                 :             :                          &sig, false,
     436                 :             :                          checkcondition_bit);
     437                 :             : }
     438                 :             : 
     439                 :             : static bool
     440                 :       15360 : gist_qe(ltree_gist *key, lquery *query, int siglen)
     441                 :             : {
     442                 :       15360 :     lquery_level *curq = LQUERY_FIRST(query);
     443                 :       15360 :     BITVECP     sign = LTG_SIGN(key);
     444                 :       15360 :     int         qlen = query->numlevel;
     445                 :             : 
     446         [ -  + ]:       15360 :     if (LTG_ISALLTRUE(key))
     447                 :           0 :         return true;
     448                 :             : 
     449         [ +  + ]:       46625 :     while (qlen > 0)
     450                 :             :     {
     451   [ +  +  +  - ]:       37358 :         if (curq->numvar && LQL_CANLOOKSIGN(curq))
     452                 :             :         {
     453                 :       26082 :             bool        isexist = false;
     454                 :       26082 :             int         vlen = curq->numvar;
     455                 :       26082 :             lquery_variant *curv = LQL_FIRST(curq);
     456                 :             : 
     457         [ +  + ]:       32175 :             while (vlen > 0)
     458                 :             :             {
     459         [ +  + ]:       26082 :                 if (GETBIT(sign, AHASHVAL(curv->val, siglen)))
     460                 :             :                 {
     461                 :       19989 :                     isexist = true;
     462                 :       19989 :                     break;
     463                 :             :                 }
     464                 :        6093 :                 curv = LVAR_NEXT(curv);
     465                 :        6093 :                 vlen--;
     466                 :             :             }
     467         [ +  + ]:       26082 :             if (!isexist)
     468                 :        6093 :                 return false;
     469                 :             :         }
     470                 :             : 
     471                 :       31265 :         curq = LQL_NEXT(curq);
     472                 :       31265 :         qlen--;
     473                 :             :     }
     474                 :             : 
     475                 :        9267 :     return true;
     476                 :             : }
     477                 :             : 
     478                 :             : static bool
     479                 :        2381 : _arrq_cons(ltree_gist *key, ArrayType *_query, int siglen)
     480                 :             : {
     481         [ -  + ]:        2381 :     lquery     *query = (lquery *) ARR_DATA_PTR(_query);
     482                 :        2381 :     int         num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
     483                 :             : 
     484         [ -  + ]:        2381 :     if (ARR_NDIM(_query) > 1)
     485         [ #  # ]:           0 :         ereport(ERROR,
     486                 :             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
     487                 :             :                  errmsg("array must be one-dimensional")));
     488         [ -  + ]:        2381 :     if (array_contains_nulls(_query))
     489         [ #  # ]:           0 :         ereport(ERROR,
     490                 :             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
     491                 :             :                  errmsg("array must not contain nulls")));
     492                 :             : 
     493         [ +  + ]:        4341 :     while (num > 0)
     494                 :             :     {
     495         [ +  + ]:        3470 :         if (gist_qe(key, query, siglen))
     496                 :        1510 :             return true;
     497                 :        1960 :         num--;
     498                 :        1960 :         query = (lquery *) NEXTVAL(query);
     499                 :             :     }
     500                 :         871 :     return false;
     501                 :             : }
     502                 :             : 
     503                 :             : Datum
     504                 :       19153 : _ltree_consistent(PG_FUNCTION_ARGS)
     505                 :             : {
     506                 :       19153 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     507                 :       19153 :     void       *query = PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
     508                 :       19153 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     509                 :             : #ifdef NOT_USED
     510                 :             :     Oid         subtype = PG_GETARG_OID(3);
     511                 :             : #endif
     512                 :       19153 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     513         [ +  - ]:       19153 :     int         siglen = LTREE_GET_ASIGLEN();
     514                 :       19153 :     ltree_gist *key = (ltree_gist *) DatumGetPointer(entry->key);
     515                 :       19153 :     bool        res = false;
     516                 :             : 
     517                 :             :     /* All cases served by this function are inexact */
     518                 :       19153 :     *recheck = true;
     519                 :             : 
     520   [ +  +  +  +  :       19153 :     switch (strategy)
                      - ]
     521                 :             :     {
     522                 :        2625 :         case 10:
     523                 :             :         case 11:
     524                 :        2625 :             res = gist_te(key, (ltree *) query, siglen);
     525                 :        2625 :             break;
     526                 :       11890 :         case 12:
     527                 :             :         case 13:
     528                 :       11890 :             res = gist_qe(key, (lquery *) query, siglen);
     529                 :       11890 :             break;
     530                 :        2257 :         case 14:
     531                 :             :         case 15:
     532                 :        2257 :             res = gist_qtxt(key, (ltxtquery *) query, siglen);
     533                 :        2257 :             break;
     534                 :        2381 :         case 16:
     535                 :             :         case 17:
     536                 :        2381 :             res = _arrq_cons(key, (ArrayType *) query, siglen);
     537                 :        2381 :             break;
     538                 :           0 :         default:
     539                 :             :             /* internal error */
     540         [ #  # ]:           0 :             elog(ERROR, "unrecognized StrategyNumber: %d", strategy);
     541                 :             :     }
     542         [ -  + ]:       19153 :     PG_FREE_IF_COPY(query, 1);
     543                 :       19153 :     PG_RETURN_BOOL(res);
     544                 :             : }
     545                 :             : 
     546                 :             : Datum
     547                 :          10 : _ltree_gist_options(PG_FUNCTION_ARGS)
     548                 :             : {
     549                 :          10 :     local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
     550                 :             : 
     551                 :          10 :     init_local_reloptions(relopts, sizeof(LtreeGistOptions));
     552                 :          10 :     add_local_int_reloption(relopts, "siglen", "signature length",
     553                 :             :                             LTREE_ASIGLEN_DEFAULT, 1, LTREE_ASIGLEN_MAX,
     554                 :             :                             offsetof(LtreeGistOptions, siglen));
     555                 :             : 
     556                 :          10 :     PG_RETURN_VOID();
     557                 :             : }
        

Generated by: LCOV version 2.0-1