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

Generated by: LCOV version 1.13