LCOV - code coverage report
Current view: top level - contrib/ltree - ltree_gist.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 356 381 93.4 %
Date: 2020-06-05 19:06:29 Functions: 30 32 93.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * GiST support for ltree
       3             :  * Teodor Sigaev <teodor@stack.net>
       4             :  * contrib/ltree/ltree_gist.c
       5             :  */
       6             : #include "postgres.h"
       7             : 
       8             : #include "access/gist.h"
       9             : #include "access/reloptions.h"
      10             : #include "access/stratnum.h"
      11             : #include "crc32.h"
      12             : #include "ltree.h"
      13             : 
      14             : #define NEXTVAL(x) ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
      15             : #define ISEQ(a,b)   ( (a)->numlevel == (b)->numlevel && ltree_compare(a,b)==0 )
      16             : 
      17           4 : PG_FUNCTION_INFO_V1(ltree_gist_in);
      18           4 : PG_FUNCTION_INFO_V1(ltree_gist_out);
      19             : 
      20             : Datum
      21           0 : ltree_gist_in(PG_FUNCTION_ARGS)
      22             : {
      23           0 :     ereport(ERROR,
      24             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
      25             :              errmsg("ltree_gist_in() not implemented")));
      26             :     PG_RETURN_DATUM(0);
      27             : }
      28             : 
      29             : Datum
      30           0 : ltree_gist_out(PG_FUNCTION_ARGS)
      31             : {
      32           0 :     ereport(ERROR,
      33             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
      34             :              errmsg("ltree_gist_out() not implemented")));
      35             :     PG_RETURN_DATUM(0);
      36             : }
      37             : 
      38             : ltree_gist *
      39       34200 : ltree_gist_alloc(bool isalltrue, BITVECP sign, int siglen,
      40             :                  ltree *left, ltree *right)
      41             : {
      42       44756 :     int32       size = LTG_HDRSIZE + (isalltrue ? 0 : siglen) +
      43       10556 :     (left ? VARSIZE(left) + (right ? VARSIZE(right) : 0) : 0);
      44       34200 :     ltree_gist *result = palloc(size);
      45             : 
      46       34200 :     SET_VARSIZE(result, size);
      47             : 
      48       34200 :     if (siglen)
      49             :     {
      50       30176 :         result->flag = 0;
      51             : 
      52       30176 :         if (isalltrue)
      53           0 :             result->flag |= LTG_ALLTRUE;
      54       30176 :         else if (sign)
      55       10184 :             memcpy(LTG_SIGN(result), sign, siglen);
      56             :         else
      57       19992 :             memset(LTG_SIGN(result), 0, siglen);
      58             : 
      59       30176 :         if (left)
      60             :         {
      61        6532 :             memcpy(LTG_LNODE(result, siglen), left, VARSIZE(left));
      62             : 
      63        6532 :             if (!right || left == right || ISEQ(left, right))
      64           0 :                 result->flag |= LTG_NORIGHT;
      65             :             else
      66        6532 :                 memcpy(LTG_RNODE(result, siglen), right, VARSIZE(right));
      67             :         }
      68             :     }
      69             :     else
      70             :     {
      71             :         Assert(left);
      72        4024 :         result->flag = LTG_ONENODE;
      73        4024 :         memcpy(LTG_NODE(result), left, VARSIZE(left));
      74             :     }
      75             : 
      76       34200 :     return result;
      77             : }
      78             : 
      79           6 : PG_FUNCTION_INFO_V1(ltree_compress);
      80           6 : PG_FUNCTION_INFO_V1(ltree_decompress);
      81           6 : PG_FUNCTION_INFO_V1(ltree_same);
      82           6 : PG_FUNCTION_INFO_V1(ltree_union);
      83           6 : PG_FUNCTION_INFO_V1(ltree_penalty);
      84           6 : PG_FUNCTION_INFO_V1(ltree_picksplit);
      85           6 : PG_FUNCTION_INFO_V1(ltree_consistent);
      86           6 : PG_FUNCTION_INFO_V1(ltree_gist_options);
      87             : 
      88             : #define GETENTRY(vec,pos) ((ltree_gist *) DatumGetPointer((vec)->vector[(pos)].key))
      89             : 
      90             : Datum
      91        4202 : ltree_compress(PG_FUNCTION_ARGS)
      92             : {
      93        4202 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
      94        4202 :     GISTENTRY  *retval = entry;
      95             : 
      96        4202 :     if (entry->leafkey)
      97             :     {                           /* ltree */
      98        4024 :         ltree      *val = DatumGetLtreeP(entry->key);
      99        4024 :         ltree_gist *key = ltree_gist_alloc(false, NULL, 0, val, 0);
     100             : 
     101        4024 :         retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
     102        4024 :         gistentryinit(*retval, PointerGetDatum(key),
     103             :                       entry->rel, entry->page,
     104             :                       entry->offset, false);
     105             :     }
     106        4202 :     PG_RETURN_POINTER(retval);
     107             : }
     108             : 
     109             : Datum
     110      201084 : ltree_decompress(PG_FUNCTION_ARGS)
     111             : {
     112      201084 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     113      201084 :     ltree_gist *key = (ltree_gist *) PG_DETOAST_DATUM(entry->key);
     114             : 
     115      201084 :     if (PointerGetDatum(key) != entry->key)
     116             :     {
     117           0 :         GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
     118             : 
     119           0 :         gistentryinit(*retval, PointerGetDatum(key),
     120             :                       entry->rel, entry->page,
     121             :                       entry->offset, false);
     122           0 :         PG_RETURN_POINTER(retval);
     123             :     }
     124      201084 :     PG_RETURN_POINTER(entry);
     125             : }
     126             : 
     127             : Datum
     128        6396 : ltree_same(PG_FUNCTION_ARGS)
     129             : {
     130        6396 :     ltree_gist *a = (ltree_gist *) PG_GETARG_POINTER(0);
     131        6396 :     ltree_gist *b = (ltree_gist *) PG_GETARG_POINTER(1);
     132        6396 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     133        6396 :     int         siglen = LTREE_GET_ASIGLEN();
     134             : 
     135        6396 :     *result = false;
     136        6396 :     if (LTG_ISONENODE(a) != LTG_ISONENODE(b))
     137           0 :         PG_RETURN_POINTER(result);
     138             : 
     139        6396 :     if (LTG_ISONENODE(a))
     140           0 :         *result = (ISEQ(LTG_NODE(a), LTG_NODE(b))) ? true : false;
     141             :     else
     142             :     {
     143             :         int32       i;
     144        6396 :         BITVECP     sa = LTG_SIGN(a),
     145        6396 :                     sb = LTG_SIGN(b);
     146             : 
     147        6396 :         if (LTG_ISALLTRUE(a) != LTG_ISALLTRUE(b))
     148           0 :             PG_RETURN_POINTER(result);
     149             : 
     150        6396 :         if (!ISEQ(LTG_LNODE(a, siglen), LTG_LNODE(b, siglen)))
     151          18 :             PG_RETURN_POINTER(result);
     152        6378 :         if (!ISEQ(LTG_RNODE(a, siglen), LTG_RNODE(b, siglen)))
     153          20 :             PG_RETURN_POINTER(result);
     154             : 
     155        6358 :         *result = true;
     156        6358 :         if (!LTG_ISALLTRUE(a))
     157             :         {
     158     9225614 :             LOOPBYTE(siglen)
     159             :             {
     160     9219260 :                 if (sa[i] != sb[i])
     161             :                 {
     162           4 :                     *result = false;
     163           4 :                     break;
     164             :                 }
     165             :             }
     166             :         }
     167             :     }
     168             : 
     169        6358 :     PG_RETURN_POINTER(result);
     170             : }
     171             : 
     172             : static void
     173       11540 : hashing(BITVECP sign, ltree *t, int siglen)
     174             : {
     175       11540 :     int         tlen = t->numlevel;
     176       11540 :     ltree_level *cur = LTREE_FIRST(t);
     177             :     int         hash;
     178             : 
     179       87340 :     while (tlen > 0)
     180             :     {
     181       75800 :         hash = ltree_crc32_sz(cur->name, cur->len);
     182       75800 :         HASH(sign, hash, siglen);
     183       75800 :         cur = LEVEL_NEXT(cur);
     184       75800 :         tlen--;
     185             :     }
     186       11540 : }
     187             : 
     188             : Datum
     189        6396 : ltree_union(PG_FUNCTION_ARGS)
     190             : {
     191        6396 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     192        6396 :     int        *size = (int *) PG_GETARG_POINTER(1);
     193        6396 :     int         siglen = LTREE_GET_ASIGLEN();
     194        6396 :     BITVECP     base = palloc0(siglen);
     195             :     int32       i,
     196             :                 j;
     197             :     ltree_gist *result,
     198             :                *cur;
     199        6396 :     ltree      *left = NULL,
     200        6396 :                *right = NULL,
     201             :                *curtree;
     202        6396 :     bool        isalltrue = false;
     203             : 
     204       19188 :     for (j = 0; j < entryvec->n; j++)
     205             :     {
     206       12792 :         cur = GETENTRY(entryvec, j);
     207       12792 :         if (LTG_ISONENODE(cur))
     208             :         {
     209        6396 :             curtree = LTG_NODE(cur);
     210        6396 :             hashing(base, curtree, siglen);
     211        6396 :             if (!left || ltree_compare(left, curtree) > 0)
     212          18 :                 left = curtree;
     213        6396 :             if (!right || ltree_compare(right, curtree) < 0)
     214          20 :                 right = curtree;
     215             :         }
     216             :         else
     217             :         {
     218        6396 :             if (isalltrue || LTG_ISALLTRUE(cur))
     219           0 :                 isalltrue = true;
     220             :             else
     221             :             {
     222        6396 :                 BITVECP     sc = LTG_SIGN(cur);
     223             : 
     224     9278748 :                 LOOPBYTE(siglen)
     225     9272352 :                     ((unsigned char *) base)[i] |= sc[i];
     226             :             }
     227             : 
     228        6396 :             curtree = LTG_LNODE(cur, siglen);
     229        6396 :             if (!left || ltree_compare(left, curtree) > 0)
     230        6396 :                 left = curtree;
     231        6396 :             curtree = LTG_RNODE(cur, siglen);
     232        6396 :             if (!right || ltree_compare(right, curtree) < 0)
     233        6396 :                 right = curtree;
     234             :         }
     235             :     }
     236             : 
     237        6396 :     if (isalltrue == false)
     238             :     {
     239        6396 :         isalltrue = true;
     240        6396 :         LOOPBYTE(siglen)
     241             :         {
     242        6396 :             if (((unsigned char *) base)[i] != 0xff)
     243             :             {
     244        6396 :                 isalltrue = false;
     245        6396 :                 break;
     246             :             }
     247             :         }
     248             :     }
     249             : 
     250        6396 :     result = ltree_gist_alloc(isalltrue, base, siglen, left, right);
     251             : 
     252        6396 :     *size = VARSIZE(result);
     253             : 
     254        6396 :     PG_RETURN_POINTER(result);
     255             : }
     256             : 
     257             : Datum
     258       19534 : ltree_penalty(PG_FUNCTION_ARGS)
     259             : {
     260       19534 :     ltree_gist *origval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     261       19534 :     ltree_gist *newval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
     262       19534 :     float      *penalty = (float *) PG_GETARG_POINTER(2);
     263       19534 :     int         siglen = LTREE_GET_ASIGLEN();
     264             :     int32       cmpr,
     265             :                 cmpl;
     266             : 
     267       19534 :     cmpl = ltree_compare(LTG_GETLNODE(origval, siglen), LTG_GETLNODE(newval, siglen));
     268       19534 :     cmpr = ltree_compare(LTG_GETRNODE(newval, siglen), LTG_GETRNODE(origval, siglen));
     269             : 
     270       19534 :     *penalty = Max(cmpl, 0) + Max(cmpr, 0);
     271             : 
     272       19534 :     PG_RETURN_POINTER(penalty);
     273             : }
     274             : 
     275             : /* used for sorting */
     276             : typedef struct rix
     277             : {
     278             :     int         index;
     279             :     ltree      *r;
     280             : } RIX;
     281             : 
     282             : static int
     283       36334 : treekey_cmp(const void *a, const void *b)
     284             : {
     285       72668 :     return ltree_compare(((const RIX *) a)->r,
     286       36334 :                          ((const RIX *) b)->r);
     287             : }
     288             : 
     289             : 
     290             : Datum
     291          68 : ltree_picksplit(PG_FUNCTION_ARGS)
     292             : {
     293          68 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     294          68 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     295          68 :     int         siglen = LTREE_GET_ASIGLEN();
     296             :     OffsetNumber j;
     297             :     int32       i;
     298             :     RIX        *array;
     299             :     OffsetNumber maxoff;
     300             :     int         nbytes;
     301             :     ltree      *lu_l,
     302             :                *lu_r,
     303             :                *ru_l,
     304             :                *ru_r;
     305             :     ltree_gist *lu,
     306             :                *ru;
     307          68 :     BITVECP     ls = palloc0(siglen),
     308          68 :                 rs = palloc0(siglen);
     309          68 :     bool        lisat = false,
     310          68 :                 risat = false;
     311             : 
     312          68 :     maxoff = entryvec->n - 1;
     313          68 :     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
     314          68 :     v->spl_left = (OffsetNumber *) palloc(nbytes);
     315          68 :     v->spl_right = (OffsetNumber *) palloc(nbytes);
     316          68 :     v->spl_nleft = 0;
     317          68 :     v->spl_nright = 0;
     318          68 :     array = (RIX *) palloc(sizeof(RIX) * (maxoff + 1));
     319             : 
     320             :     /* copy the data into RIXes, and sort the RIXes */
     321        5260 :     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
     322             :     {
     323        5192 :         array[j].index = j;
     324        5192 :         lu = GETENTRY(entryvec, j); /* use as tmp val */
     325        5192 :         array[j].r = LTG_GETLNODE(lu, siglen);
     326             :     }
     327             : 
     328          68 :     qsort((void *) &array[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1,
     329             :           sizeof(RIX), treekey_cmp);
     330             : 
     331          68 :     lu_l = lu_r = ru_l = ru_r = NULL;
     332        5260 :     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
     333             :     {
     334        5192 :         lu = GETENTRY(entryvec, array[j].index);    /* use as tmp val */
     335        5192 :         if (j <= (maxoff - FirstOffsetNumber + 1) / 2)
     336             :         {
     337        2584 :             v->spl_left[v->spl_nleft] = array[j].index;
     338        2584 :             v->spl_nleft++;
     339        2584 :             if (lu_r == NULL || ltree_compare(LTG_GETRNODE(lu, siglen), lu_r) > 0)
     340        2582 :                 lu_r = LTG_GETRNODE(lu, siglen);
     341        2584 :             if (LTG_ISONENODE(lu))
     342        2560 :                 hashing(ls, LTG_NODE(lu), siglen);
     343             :             else
     344             :             {
     345          24 :                 if (lisat || LTG_ISALLTRUE(lu))
     346           0 :                     lisat = true;
     347             :                 else
     348             :                 {
     349          24 :                     BITVECP     sc = LTG_SIGN(lu);
     350             : 
     351       48600 :                     LOOPBYTE(siglen)
     352       48576 :                         ((unsigned char *) ls)[i] |= sc[i];
     353             :                 }
     354             :             }
     355             :         }
     356             :         else
     357             :         {
     358        2608 :             v->spl_right[v->spl_nright] = array[j].index;
     359        2608 :             v->spl_nright++;
     360        2608 :             if (ru_r == NULL || ltree_compare(LTG_GETRNODE(lu, siglen), ru_r) > 0)
     361        2606 :                 ru_r = LTG_GETRNODE(lu, siglen);
     362        2608 :             if (LTG_ISONENODE(lu))
     363        2584 :                 hashing(rs, LTG_NODE(lu), siglen);
     364             :             else
     365             :             {
     366          24 :                 if (risat || LTG_ISALLTRUE(lu))
     367           0 :                     risat = true;
     368             :                 else
     369             :                 {
     370          24 :                     BITVECP     sc = LTG_SIGN(lu);
     371             : 
     372       48600 :                     LOOPBYTE(siglen)
     373       48576 :                         ((unsigned char *) rs)[i] |= sc[i];
     374             :                 }
     375             :             }
     376             :         }
     377             :     }
     378             : 
     379          68 :     if (lisat == false)
     380             :     {
     381          68 :         lisat = true;
     382          68 :         LOOPBYTE(siglen)
     383             :         {
     384          68 :             if (((unsigned char *) ls)[i] != 0xff)
     385             :             {
     386          68 :                 lisat = false;
     387          68 :                 break;
     388             :             }
     389             :         }
     390             :     }
     391             : 
     392          68 :     if (risat == false)
     393             :     {
     394          68 :         risat = true;
     395          68 :         LOOPBYTE(siglen)
     396             :         {
     397          68 :             if (((unsigned char *) rs)[i] != 0xff)
     398             :             {
     399          68 :                 risat = false;
     400          68 :                 break;
     401             :             }
     402             :         }
     403             :     }
     404             : 
     405          68 :     lu_l = LTG_GETLNODE(GETENTRY(entryvec, array[FirstOffsetNumber].index), siglen);
     406          68 :     lu = ltree_gist_alloc(lisat, ls, siglen, lu_l, lu_r);
     407             : 
     408          68 :     ru_l = LTG_GETLNODE(GETENTRY(entryvec, array[1 + ((maxoff - FirstOffsetNumber + 1) / 2)].index), siglen);
     409          68 :     ru = ltree_gist_alloc(risat, rs, siglen, ru_l, ru_r);
     410             : 
     411          68 :     pfree(ls);
     412          68 :     pfree(rs);
     413             : 
     414          68 :     v->spl_ldatum = PointerGetDatum(lu);
     415          68 :     v->spl_rdatum = PointerGetDatum(ru);
     416             : 
     417          68 :     PG_RETURN_POINTER(v);
     418             : }
     419             : 
     420             : static bool
     421          46 : gist_isparent(ltree_gist *key, ltree *query, int siglen)
     422             : {
     423          46 :     int32       numlevel = query->numlevel;
     424             :     int         i;
     425             : 
     426         198 :     for (i = query->numlevel; i >= 0; i--)
     427             :     {
     428         160 :         query->numlevel = i;
     429         168 :         if (ltree_compare(query, LTG_GETLNODE(key, siglen)) >= 0 &&
     430           8 :             ltree_compare(query, LTG_GETRNODE(key, siglen)) <= 0)
     431             :         {
     432           8 :             query->numlevel = numlevel;
     433           8 :             return true;
     434             :         }
     435             :     }
     436             : 
     437          38 :     query->numlevel = numlevel;
     438          38 :     return false;
     439             : }
     440             : 
     441             : static ltree *
     442          92 : copy_ltree(ltree *src)
     443             : {
     444          92 :     ltree      *dst = (ltree *) palloc0(VARSIZE(src));
     445             : 
     446          92 :     memcpy(dst, src, VARSIZE(src));
     447          92 :     return dst;
     448             : }
     449             : 
     450             : static bool
     451          46 : gist_ischild(ltree_gist *key, ltree *query, int siglen)
     452             : {
     453          46 :     ltree      *left = copy_ltree(LTG_GETLNODE(key, siglen));
     454          46 :     ltree      *right = copy_ltree(LTG_GETRNODE(key, siglen));
     455          46 :     bool        res = true;
     456             : 
     457          46 :     if (left->numlevel > query->numlevel)
     458          30 :         left->numlevel = query->numlevel;
     459             : 
     460          46 :     if (ltree_compare(query, left) < 0)
     461          38 :         res = false;
     462             : 
     463          46 :     if (right->numlevel > query->numlevel)
     464          44 :         right->numlevel = query->numlevel;
     465             : 
     466          46 :     if (res && ltree_compare(query, right) > 0)
     467           0 :         res = false;
     468             : 
     469          46 :     pfree(left);
     470          46 :     pfree(right);
     471             : 
     472          46 :     return res;
     473             : }
     474             : 
     475             : static bool
     476         406 : gist_qe(ltree_gist *key, lquery *query, int siglen)
     477             : {
     478         406 :     lquery_level *curq = LQUERY_FIRST(query);
     479         406 :     BITVECP     sign = LTG_SIGN(key);
     480         406 :     int         qlen = query->numlevel;
     481             : 
     482         406 :     if (LTG_ISALLTRUE(key))
     483           0 :         return true;
     484             : 
     485        1594 :     while (qlen > 0)
     486             :     {
     487        1188 :         if (curq->numvar && LQL_CANLOOKSIGN(curq))
     488             :         {
     489         782 :             bool        isexist = false;
     490         782 :             int         vlen = curq->numvar;
     491         782 :             lquery_variant *curv = LQL_FIRST(curq);
     492             : 
     493         782 :             while (vlen > 0)
     494             :             {
     495         782 :                 if (GETBIT(sign, HASHVAL(curv->val, siglen)))
     496             :                 {
     497         782 :                     isexist = true;
     498         782 :                     break;
     499             :                 }
     500           0 :                 curv = LVAR_NEXT(curv);
     501           0 :                 vlen--;
     502             :             }
     503         782 :             if (!isexist)
     504           0 :                 return false;
     505             :         }
     506             : 
     507        1188 :         curq = LQL_NEXT(curq);
     508        1188 :         qlen--;
     509             :     }
     510             : 
     511         406 :     return true;
     512             : }
     513             : 
     514             : static int
     515         532 : gist_tqcmp(ltree *t, lquery *q)
     516             : {
     517         532 :     ltree_level *al = LTREE_FIRST(t);
     518         532 :     lquery_level *ql = LQUERY_FIRST(q);
     519             :     lquery_variant *bl;
     520         532 :     int         an = t->numlevel;
     521         532 :     int         bn = q->firstgood;
     522         532 :     int         res = 0;
     523             : 
     524         628 :     while (an > 0 && bn > 0)
     525             :     {
     526         496 :         bl = LQL_FIRST(ql);
     527         496 :         if ((res = memcmp(al->name, bl->name, Min(al->len, bl->len))) == 0)
     528             :         {
     529         166 :             if (al->len != bl->len)
     530          70 :                 return al->len - bl->len;
     531             :         }
     532             :         else
     533         330 :             return res;
     534          96 :         an--;
     535          96 :         bn--;
     536          96 :         al = LEVEL_NEXT(al);
     537          96 :         ql = LQL_NEXT(ql);
     538             :     }
     539             : 
     540         132 :     return Min(t->numlevel, q->firstgood) - q->firstgood;
     541             : }
     542             : 
     543             : static bool
     544         406 : gist_between(ltree_gist *key, lquery *query, int siglen)
     545             : {
     546         406 :     if (query->firstgood == 0)
     547          76 :         return true;
     548             : 
     549         330 :     if (gist_tqcmp(LTG_GETLNODE(key, siglen), query) > 0)
     550         128 :         return false;
     551             : 
     552         202 :     if (gist_tqcmp(LTG_GETRNODE(key, siglen), query) < 0)
     553          90 :         return false;
     554             : 
     555         112 :     return true;
     556             : }
     557             : 
     558             : typedef struct LtreeSignature
     559             : {
     560             :     BITVECP     sign;
     561             :     int         siglen;
     562             : } LtreeSignature;
     563             : 
     564             : static bool
     565         152 : checkcondition_bit(void *cxt, ITEM *val)
     566             : {
     567         152 :     LtreeSignature *sig = cxt;
     568             : 
     569         152 :     return (FLG_CANLOOKSIGN(val->flag)) ? GETBIT(sig->sign, HASHVAL(val->val, sig->siglen)) : true;
     570             : }
     571             : 
     572             : static bool
     573          76 : gist_qtxt(ltree_gist *key, ltxtquery *query, int siglen)
     574             : {
     575             :     LtreeSignature sig;
     576             : 
     577          76 :     if (LTG_ISALLTRUE(key))
     578           0 :         return true;
     579             : 
     580          76 :     sig.sign = LTG_SIGN(key);
     581          76 :     sig.siglen = siglen;
     582             : 
     583          76 :     return ltree_execute(GETQUERY(query),
     584             :                          &sig, false,
     585             :                          checkcondition_bit);
     586             : }
     587             : 
     588             : static bool
     589          62 : arrq_cons(ltree_gist *key, ArrayType *_query, int siglen)
     590             : {
     591          62 :     lquery     *query = (lquery *) ARR_DATA_PTR(_query);
     592          62 :     int         num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
     593             : 
     594          62 :     if (ARR_NDIM(_query) > 1)
     595           0 :         ereport(ERROR,
     596             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
     597             :                  errmsg("array must be one-dimensional")));
     598          62 :     if (array_contains_nulls(_query))
     599           0 :         ereport(ERROR,
     600             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
     601             :                  errmsg("array must not contain nulls")));
     602             : 
     603         134 :     while (num > 0)
     604             :     {
     605          98 :         if (gist_qe(key, query, siglen) && gist_between(key, query, siglen))
     606          26 :             return true;
     607          72 :         num--;
     608          72 :         query = NEXTVAL(query);
     609             :     }
     610          36 :     return false;
     611             : }
     612             : 
     613             : Datum
     614       24438 : ltree_consistent(PG_FUNCTION_ARGS)
     615             : {
     616       24438 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     617       24438 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     618             : 
     619             :     /* Oid      subtype = PG_GETARG_OID(3); */
     620       24438 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     621       24438 :     int         siglen = LTREE_GET_ASIGLEN();
     622       24438 :     ltree_gist *key = (ltree_gist *) DatumGetPointer(entry->key);
     623       24438 :     void       *query = NULL;
     624       24438 :     bool        res = false;
     625             : 
     626             :     /* All cases served by this function are exact */
     627       24438 :     *recheck = false;
     628             : 
     629       24438 :     switch (strategy)
     630             :     {
     631         956 :         case BTLessStrategyNumber:
     632         956 :             query = PG_GETARG_LTREE_P(1);
     633        1912 :             res = (GIST_LEAF(entry)) ?
     634         910 :                 (ltree_compare((ltree *) query, LTG_NODE(key)) > 0)
     635        1912 :                 :
     636          46 :                 (ltree_compare((ltree *) query, LTG_GETLNODE(key, siglen)) >= 0);
     637         956 :             break;
     638         956 :         case BTLessEqualStrategyNumber:
     639         956 :             query = PG_GETARG_LTREE_P(1);
     640         956 :             res = (ltree_compare((ltree *) query, LTG_GETLNODE(key, siglen)) >= 0);
     641         956 :             break;
     642         626 :         case BTEqualStrategyNumber:
     643         626 :             query = PG_GETARG_LTREE_P(1);
     644         626 :             if (GIST_LEAF(entry))
     645         580 :                 res = (ltree_compare((ltree *) query, LTG_NODE(key)) == 0);
     646             :             else
     647          92 :                 res = (ltree_compare((ltree *) query, LTG_GETLNODE(key, siglen)) >= 0
     648          62 :                        &&
     649          16 :                        ltree_compare((ltree *) query, LTG_GETRNODE(key, siglen)) <= 0);
     650         626 :             break;
     651        3770 :         case BTGreaterEqualStrategyNumber:
     652        3770 :             query = PG_GETARG_LTREE_P(1);
     653        3770 :             res = (ltree_compare((ltree *) query, LTG_GETRNODE(key, siglen)) <= 0);
     654        3770 :             break;
     655        3770 :         case BTGreaterStrategyNumber:
     656        3770 :             query = PG_GETARG_LTREE_P(1);
     657        7540 :             res = (GIST_LEAF(entry)) ?
     658        3694 :                 (ltree_compare((ltree *) query, LTG_GETRNODE(key, siglen)) < 0)
     659        7540 :                 :
     660          76 :                 (ltree_compare((ltree *) query, LTG_GETRNODE(key, siglen)) <= 0);
     661        3770 :             break;
     662         376 :         case 10:
     663         376 :             query = PG_GETARG_LTREE_P_COPY(1);
     664         752 :             res = (GIST_LEAF(entry)) ?
     665         330 :                 inner_isparent((ltree *) query, LTG_NODE(key))
     666         706 :                 :
     667          46 :                 gist_isparent(key, (ltree *) query, siglen);
     668         376 :             break;
     669         376 :         case 11:
     670         376 :             query = PG_GETARG_LTREE_P(1);
     671         752 :             res = (GIST_LEAF(entry)) ?
     672         330 :                 inner_isparent(LTG_NODE(key), (ltree *) query)
     673         706 :                 :
     674          46 :                 gist_ischild(key, (ltree *) query, siglen);
     675         376 :             break;
     676        8250 :         case 12:
     677             :         case 13:
     678        8250 :             query = PG_GETARG_LQUERY_P(1);
     679        8250 :             if (GIST_LEAF(entry))
     680        7942 :                 res = DatumGetBool(DirectFunctionCall2(ltq_regex,
     681             :                                                        PointerGetDatum(LTG_NODE(key)),
     682             :                                                        PointerGetDatum((lquery *) query)
     683             :                                                        ));
     684             :             else
     685         616 :                 res = (gist_qe(key, (lquery *) query, siglen) &&
     686         308 :                        gist_between(key, (lquery *) query, siglen));
     687        8250 :             break;
     688        4100 :         case 14:
     689             :         case 15:
     690        4100 :             query = PG_GETARG_LTXTQUERY_P(1);
     691        4100 :             if (GIST_LEAF(entry))
     692        4024 :                 res = DatumGetBool(DirectFunctionCall2(ltxtq_exec,
     693             :                                                        PointerGetDatum(LTG_NODE(key)),
     694             :                                                        PointerGetDatum((ltxtquery *) query)
     695             :                                                        ));
     696             :             else
     697          76 :                 res = gist_qtxt(key, (ltxtquery *) query, siglen);
     698        4100 :             break;
     699        1258 :         case 16:
     700             :         case 17:
     701        1258 :             query = PG_GETARG_ARRAYTYPE_P(1);
     702        1258 :             if (GIST_LEAF(entry))
     703        1196 :                 res = DatumGetBool(DirectFunctionCall2(lt_q_regex,
     704             :                                                        PointerGetDatum(LTG_NODE(key)),
     705             :                                                        PointerGetDatum((ArrayType *) query)
     706             :                                                        ));
     707             :             else
     708          62 :                 res = arrq_cons(key, (ArrayType *) query, siglen);
     709        1258 :             break;
     710           0 :         default:
     711             :             /* internal error */
     712           0 :             elog(ERROR, "unrecognized StrategyNumber: %d", strategy);
     713             :     }
     714             : 
     715       24438 :     PG_FREE_IF_COPY(query, 1);
     716       24438 :     PG_RETURN_BOOL(res);
     717             : }
     718             : 
     719             : Datum
     720          18 : ltree_gist_options(PG_FUNCTION_ARGS)
     721             : {
     722          18 :     local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
     723             : 
     724          18 :     init_local_reloptions(relopts, sizeof(LtreeGistOptions));
     725          18 :     add_local_int_reloption(relopts, "siglen",
     726             :                             "signature length in bytes",
     727             :                             SIGLEN_DEFAULT, 1, SIGLEN_MAX,
     728             :                             offsetof(LtreeGistOptions, siglen));
     729             : 
     730          18 :     PG_RETURN_VOID();
     731             : }

Generated by: LCOV version 1.13