LCOV - code coverage report
Current view: top level - contrib/ltree - _ltree_gist.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 88.6 % 271 240
Test Date: 2026-03-16 09:16:26 Functions: 96.0 % 25 24
Legend: Lines:     hit not hit

            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         5872 : _ltree_compress(PG_FUNCTION_ARGS)
      50              : {
      51         5872 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
      52         5872 :     GISTENTRY  *retval = entry;
      53         5872 :     int         siglen = LTREE_GET_ASIGLEN();
      54              : 
      55         5872 :     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         3872 :     else if (!LTG_ISALLTRUE(DatumGetPointer(entry->key)))
      86              :     {
      87              :         int32       i;
      88              :         ltree_gist *key;
      89         3872 :         BITVECP     sign = LTG_SIGN(DatumGetPointer(entry->key));
      90              : 
      91         3872 :         ALOOPBYTE(siglen)
      92              :         {
      93         3872 :             if ((sign[i] & 0xff) != 0xff)
      94         3872 :                 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         8163 : _ltree_same(PG_FUNCTION_ARGS)
     108              : {
     109         8163 :     ltree_gist *a = (ltree_gist *) PG_GETARG_POINTER(0);
     110         8163 :     ltree_gist *b = (ltree_gist *) PG_GETARG_POINTER(1);
     111         8163 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     112         8163 :     int         siglen = LTREE_GET_ASIGLEN();
     113              : 
     114         8163 :     if (LTG_ISALLTRUE(a) && LTG_ISALLTRUE(b))
     115            0 :         *result = true;
     116         8163 :     else if (LTG_ISALLTRUE(a))
     117            0 :         *result = false;
     118         8163 :     else if (LTG_ISALLTRUE(b))
     119            0 :         *result = false;
     120              :     else
     121              :     {
     122              :         int32       i;
     123         8163 :         BITVECP     sa = LTG_SIGN(a),
     124         8163 :                     sb = LTG_SIGN(b);
     125              : 
     126         8163 :         *result = true;
     127     11867119 :         ALOOPBYTE(siglen)
     128              :         {
     129     11861036 :             if (sa[i] != sb[i])
     130              :             {
     131         2080 :                 *result = false;
     132         2080 :                 break;
     133              :             }
     134              :         }
     135              :     }
     136         8163 :     PG_RETURN_POINTER(result);
     137              : }
     138              : 
     139              : static int32
     140        16326 : unionkey(BITVECP sbase, ltree_gist *add, int siglen)
     141              : {
     142              :     int32       i;
     143        16326 :     BITVECP     sadd = LTG_SIGN(add);
     144              : 
     145        16326 :     if (LTG_ISALLTRUE(add))
     146            0 :         return 1;
     147              : 
     148     29631022 :     ALOOPBYTE(siglen)
     149     29614696 :         sbase[i] |= sadd[i];
     150        16326 :     return 0;
     151              : }
     152              : 
     153              : Datum
     154         8163 : _ltree_union(PG_FUNCTION_ARGS)
     155              : {
     156         8163 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     157         8163 :     int        *size = (int *) PG_GETARG_POINTER(1);
     158         8163 :     int         siglen = LTREE_GET_ASIGLEN();
     159              :     int32       i;
     160         8163 :     ltree_gist *result = ltree_gist_alloc(false, NULL, siglen, NULL, NULL);
     161         8163 :     BITVECP     base = LTG_SIGN(result);
     162              : 
     163        24489 :     for (i = 0; i < entryvec->n; i++)
     164              :     {
     165        16326 :         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         8163 :     *size = VARSIZE(result);
     174              : 
     175         8163 :     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       125269 : hemdistsign(BITVECP a, BITVECP b, int siglen)
     186              : {
     187              :     int         i,
     188              :                 diff,
     189       125269 :                 dist = 0;
     190              : 
     191     59267309 :     ALOOPBYTE(siglen)
     192              :     {
     193     59142040 :         diff = (unsigned char) (a[i] ^ b[i]);
     194              :         /* Using the popcount functions here isn't likely to win */
     195     59142040 :         dist += pg_number_of_ones[diff];
     196              :     }
     197       125269 :     return dist;
     198              : }
     199              : 
     200              : static int
     201       125269 : hemdist(ltree_gist *a, ltree_gist *b, int siglen)
     202              : {
     203       125269 :     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       125269 :     else if (LTG_ISALLTRUE(b))
     211            0 :         return ASIGLENBIT(siglen) - sizebitvec(LTG_SIGN(a), siglen);
     212              : 
     213       125269 :     return hemdistsign(LTG_SIGN(a), LTG_SIGN(b), siglen);
     214              : }
     215              : 
     216              : 
     217              : Datum
     218        19354 : _ltree_penalty(PG_FUNCTION_ARGS)
     219              : {
     220        19354 :     ltree_gist *origval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     221        19354 :     ltree_gist *newval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
     222        19354 :     float      *penalty = (float *) PG_GETARG_POINTER(2);
     223        19354 :     int         siglen = LTREE_GET_ASIGLEN();
     224              : 
     225        19354 :     *penalty = hemdist(origval, newval, siglen);
     226        19354 :     PG_RETURN_POINTER(penalty);
     227              : }
     228              : 
     229              : typedef struct
     230              : {
     231              :     OffsetNumber pos;
     232              :     int32       cost;
     233              : } SPLITCOST;
     234              : 
     235              : static int
     236         7989 : comparecost(const void *a, const void *b)
     237              : {
     238         7989 :     return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
     239              : }
     240              : 
     241              : Datum
     242          896 : _ltree_picksplit(PG_FUNCTION_ARGS)
     243              : {
     244          896 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     245          896 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     246          896 :     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          896 :                 waste = -1;
     257              :     int32       nbytes;
     258          896 :     OffsetNumber seed_1 = 0,
     259          896 :                 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          896 :     maxoff = entryvec->n - 2;
     270          896 :     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
     271          896 :     v->spl_left = (OffsetNumber *) palloc(nbytes);
     272          896 :     v->spl_right = (OffsetNumber *) palloc(nbytes);
     273              : 
     274         3921 :     for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
     275              :     {
     276         3025 :         _k = GETENTRY(entryvec, k);
     277        93256 :         for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
     278              :         {
     279        90231 :             size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
     280        90231 :             if (size_waste > waste)
     281              :             {
     282         1620 :                 waste = size_waste;
     283         1620 :                 seed_1 = k;
     284         1620 :                 seed_2 = j;
     285              :             }
     286              :         }
     287              :     }
     288              : 
     289          896 :     left = v->spl_left;
     290          896 :     v->spl_nleft = 0;
     291          896 :     right = v->spl_right;
     292          896 :     v->spl_nright = 0;
     293              : 
     294          896 :     if (seed_1 == 0 || seed_2 == 0)
     295              :     {
     296            0 :         seed_1 = 1;
     297            0 :         seed_2 = 2;
     298              :     }
     299              : 
     300              :     /* form initial .. */
     301          896 :     datum_l = ltree_gist_alloc(LTG_ISALLTRUE(GETENTRY(entryvec, seed_1)),
     302          896 :                                LTG_SIGN(GETENTRY(entryvec, seed_1)),
     303              :                                siglen, NULL, NULL);
     304              : 
     305          896 :     datum_r = ltree_gist_alloc(LTG_ISALLTRUE(GETENTRY(entryvec, seed_2)),
     306          896 :                                LTG_SIGN(GETENTRY(entryvec, seed_2)),
     307              :                                siglen, NULL, NULL);
     308              : 
     309          896 :     maxoff = OffsetNumberNext(maxoff);
     310              :     /* sort before ... */
     311          896 :     costvector = palloc_array(SPLITCOST, maxoff);
     312         5713 :     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
     313              :     {
     314         4817 :         costvector[j - 1].pos = j;
     315         4817 :         _j = GETENTRY(entryvec, j);
     316         4817 :         size_alpha = hemdist(datum_l, _j, siglen);
     317         4817 :         size_beta = hemdist(datum_r, _j, siglen);
     318         4817 :         costvector[j - 1].cost = abs(size_alpha - size_beta);
     319              :     }
     320          896 :     qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
     321              : 
     322          896 :     union_l = LTG_SIGN(datum_l);
     323          896 :     union_r = LTG_SIGN(datum_r);
     324              : 
     325         5713 :     for (k = 0; k < maxoff; k++)
     326              :     {
     327         4817 :         j = costvector[k].pos;
     328         4817 :         if (j == seed_1)
     329              :         {
     330          896 :             *left++ = j;
     331          896 :             v->spl_nleft++;
     332          896 :             continue;
     333              :         }
     334         3921 :         else if (j == seed_2)
     335              :         {
     336          896 :             *right++ = j;
     337          896 :             v->spl_nright++;
     338          896 :             continue;
     339              :         }
     340         3025 :         _j = GETENTRY(entryvec, j);
     341         3025 :         size_alpha = hemdist(datum_l, _j, siglen);
     342         3025 :         size_beta = hemdist(datum_r, _j, siglen);
     343              : 
     344         3025 :         if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
     345              :         {
     346         1449 :             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         1449 :                 ptr = LTG_SIGN(_j);
     354      1656785 :                 ALOOPBYTE(siglen)
     355      1655336 :                     union_l[i] |= ptr[i];
     356              :             }
     357         1449 :             *left++ = j;
     358         1449 :             v->spl_nleft++;
     359              :         }
     360              :         else
     361              :         {
     362         1576 :             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         1576 :                 ptr = LTG_SIGN(_j);
     370      1971844 :                 ALOOPBYTE(siglen)
     371      1970268 :                     union_r[i] |= ptr[i];
     372              :             }
     373         1576 :             *right++ = j;
     374         1576 :             v->spl_nright++;
     375              :         }
     376              :     }
     377              : 
     378          896 :     *right = *left = FirstOffsetNumber;
     379              : 
     380          896 :     v->spl_ldatum = PointerGetDatum(datum_l);
     381          896 :     v->spl_rdatum = PointerGetDatum(datum_r);
     382              : 
     383          896 :     PG_RETURN_POINTER(v);
     384              : }
     385              : 
     386              : static bool
     387         2188 : gist_te(ltree_gist *key, ltree *query, int siglen)
     388              : {
     389         2188 :     ltree_level *curq = LTREE_FIRST(query);
     390         2188 :     BITVECP     sign = LTG_SIGN(key);
     391         2188 :     int         qlen = query->numlevel;
     392              :     unsigned int hv;
     393              : 
     394         2188 :     if (LTG_ISALLTRUE(key))
     395            0 :         return true;
     396              : 
     397         7831 :     while (qlen > 0)
     398              :     {
     399         5950 :         hv = ltree_crc32_sz(curq->name, curq->len);
     400         5950 :         if (!GETBIT(sign, AHASHVAL(hv, siglen)))
     401          307 :             return false;
     402         5643 :         curq = LEVEL_NEXT(curq);
     403         5643 :         qlen--;
     404              :     }
     405              : 
     406         1881 :     return true;
     407              : }
     408              : 
     409              : typedef struct LtreeSignature
     410              : {
     411              :     BITVECP     sign;
     412              :     int         siglen;
     413              : } LtreeSignature;
     414              : 
     415              : static bool
     416         3084 : checkcondition_bit(void *cxt, ITEM *val)
     417              : {
     418         3084 :     LtreeSignature *sig = cxt;
     419              : 
     420         3084 :     return (FLG_CANLOOKSIGN(val->flag)) ? GETBIT(sig->sign, AHASHVAL(val->val, sig->siglen)) : true;
     421              : }
     422              : 
     423              : static bool
     424         1775 : gist_qtxt(ltree_gist *key, ltxtquery *query, int siglen)
     425              : {
     426              :     LtreeSignature sig;
     427              : 
     428         1775 :     if (LTG_ISALLTRUE(key))
     429            0 :         return true;
     430              : 
     431         1775 :     sig.sign = LTG_SIGN(key);
     432         1775 :     sig.siglen = siglen;
     433              : 
     434         1775 :     return ltree_execute(GETQUERY(query),
     435              :                          &sig, false,
     436              :                          checkcondition_bit);
     437              : }
     438              : 
     439              : static bool
     440        13114 : gist_qe(ltree_gist *key, lquery *query, int siglen)
     441              : {
     442        13114 :     lquery_level *curq = LQUERY_FIRST(query);
     443        13114 :     BITVECP     sign = LTG_SIGN(key);
     444        13114 :     int         qlen = query->numlevel;
     445              : 
     446        13114 :     if (LTG_ISALLTRUE(key))
     447            0 :         return true;
     448              : 
     449        42135 :     while (qlen > 0)
     450              :     {
     451        33421 :         if (curq->numvar && LQL_CANLOOKSIGN(curq))
     452              :         {
     453        23114 :             bool        isexist = false;
     454        23114 :             int         vlen = curq->numvar;
     455        23114 :             lquery_variant *curv = LQL_FIRST(curq);
     456              : 
     457        27514 :             while (vlen > 0)
     458              :             {
     459        23114 :                 if (GETBIT(sign, AHASHVAL(curv->val, siglen)))
     460              :                 {
     461        18714 :                     isexist = true;
     462        18714 :                     break;
     463              :                 }
     464         4400 :                 curv = LVAR_NEXT(curv);
     465         4400 :                 vlen--;
     466              :             }
     467        23114 :             if (!isexist)
     468         4400 :                 return false;
     469              :         }
     470              : 
     471        29021 :         curq = LQL_NEXT(curq);
     472        29021 :         qlen--;
     473              :     }
     474              : 
     475         8714 :     return true;
     476              : }
     477              : 
     478              : static bool
     479         2219 : _arrq_cons(ltree_gist *key, ArrayType *_query, int siglen)
     480              : {
     481         2219 :     lquery     *query = (lquery *) ARR_DATA_PTR(_query);
     482         2219 :     int         num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
     483              : 
     484         2219 :     if (ARR_NDIM(_query) > 1)
     485            0 :         ereport(ERROR,
     486              :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
     487              :                  errmsg("array must be one-dimensional")));
     488         2219 :     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         3956 :     while (num > 0)
     494              :     {
     495         3256 :         if (gist_qe(key, query, siglen))
     496         1519 :             return true;
     497         1737 :         num--;
     498         1737 :         query = (lquery *) NEXTVAL(query);
     499              :     }
     500          700 :     return false;
     501              : }
     502              : 
     503              : Datum
     504        16040 : _ltree_consistent(PG_FUNCTION_ARGS)
     505              : {
     506        16040 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     507        16040 :     void       *query = PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
     508        16040 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     509              : #ifdef NOT_USED
     510              :     Oid         subtype = PG_GETARG_OID(3);
     511              : #endif
     512        16040 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     513        16040 :     int         siglen = LTREE_GET_ASIGLEN();
     514        16040 :     ltree_gist *key = (ltree_gist *) DatumGetPointer(entry->key);
     515        16040 :     bool        res = false;
     516              : 
     517              :     /* All cases served by this function are inexact */
     518        16040 :     *recheck = true;
     519              : 
     520        16040 :     switch (strategy)
     521              :     {
     522         2188 :         case 10:
     523              :         case 11:
     524         2188 :             res = gist_te(key, (ltree *) query, siglen);
     525         2188 :             break;
     526         9858 :         case 12:
     527              :         case 13:
     528         9858 :             res = gist_qe(key, (lquery *) query, siglen);
     529         9858 :             break;
     530         1775 :         case 14:
     531              :         case 15:
     532         1775 :             res = gist_qtxt(key, (ltxtquery *) query, siglen);
     533         1775 :             break;
     534         2219 :         case 16:
     535              :         case 17:
     536         2219 :             res = _arrq_cons(key, (ArrayType *) query, siglen);
     537         2219 :             break;
     538            0 :         default:
     539              :             /* internal error */
     540            0 :             elog(ERROR, "unrecognized StrategyNumber: %d", strategy);
     541              :     }
     542        16040 :     PG_FREE_IF_COPY(query, 1);
     543        16040 :     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