Header And Logo

PostgreSQL
| The world's most advanced open source database.

ltree_gist.c

Go to the documentation of this file.
00001 /*
00002  * GiST support for ltree
00003  * Teodor Sigaev <[email protected]>
00004  * contrib/ltree/ltree_gist.c
00005  */
00006 #include "postgres.h"
00007 
00008 #include "access/gist.h"
00009 #include "access/skey.h"
00010 #include "crc32.h"
00011 #include "ltree.h"
00012 
00013 #define NEXTVAL(x) ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
00014 
00015 PG_FUNCTION_INFO_V1(ltree_gist_in);
00016 Datum       ltree_gist_in(PG_FUNCTION_ARGS);
00017 
00018 PG_FUNCTION_INFO_V1(ltree_gist_out);
00019 Datum       ltree_gist_out(PG_FUNCTION_ARGS);
00020 
00021 Datum
00022 ltree_gist_in(PG_FUNCTION_ARGS)
00023 {
00024     ereport(ERROR,
00025             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00026              errmsg("ltree_gist_in() not implemented")));
00027     PG_RETURN_DATUM(0);
00028 }
00029 
00030 Datum
00031 ltree_gist_out(PG_FUNCTION_ARGS)
00032 {
00033     ereport(ERROR,
00034             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00035              errmsg("ltree_gist_out() not implemented")));
00036     PG_RETURN_DATUM(0);
00037 }
00038 
00039 PG_FUNCTION_INFO_V1(ltree_compress);
00040 Datum       ltree_compress(PG_FUNCTION_ARGS);
00041 
00042 PG_FUNCTION_INFO_V1(ltree_decompress);
00043 Datum       ltree_decompress(PG_FUNCTION_ARGS);
00044 
00045 PG_FUNCTION_INFO_V1(ltree_same);
00046 Datum       ltree_same(PG_FUNCTION_ARGS);
00047 
00048 PG_FUNCTION_INFO_V1(ltree_union);
00049 Datum       ltree_union(PG_FUNCTION_ARGS);
00050 
00051 PG_FUNCTION_INFO_V1(ltree_penalty);
00052 Datum       ltree_penalty(PG_FUNCTION_ARGS);
00053 
00054 PG_FUNCTION_INFO_V1(ltree_picksplit);
00055 Datum       ltree_picksplit(PG_FUNCTION_ARGS);
00056 
00057 PG_FUNCTION_INFO_V1(ltree_consistent);
00058 Datum       ltree_consistent(PG_FUNCTION_ARGS);
00059 
00060 #define ISEQ(a,b)   ( (a)->numlevel == (b)->numlevel && ltree_compare(a,b)==0 )
00061 #define GETENTRY(vec,pos) ((ltree_gist *) DatumGetPointer((vec)->vector[(pos)].key))
00062 
00063 Datum
00064 ltree_compress(PG_FUNCTION_ARGS)
00065 {
00066     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00067     GISTENTRY  *retval = entry;
00068 
00069     if (entry->leafkey)
00070     {                           /* ltree */
00071         ltree_gist *key;
00072         ltree      *val = (ltree *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
00073         int32       len = LTG_HDRSIZE + VARSIZE(val);
00074 
00075         key = (ltree_gist *) palloc(len);
00076         SET_VARSIZE(key, len);
00077         key->flag = LTG_ONENODE;
00078         memcpy((void *) LTG_NODE(key), (void *) val, VARSIZE(val));
00079 
00080         retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
00081         gistentryinit(*retval, PointerGetDatum(key),
00082                       entry->rel, entry->page,
00083                       entry->offset, FALSE);
00084     }
00085     PG_RETURN_POINTER(retval);
00086 }
00087 
00088 Datum
00089 ltree_decompress(PG_FUNCTION_ARGS)
00090 {
00091     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00092     ltree_gist *key = (ltree_gist *) DatumGetPointer(PG_DETOAST_DATUM(entry->key));
00093 
00094     if (PointerGetDatum(key) != entry->key)
00095     {
00096         GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
00097 
00098         gistentryinit(*retval, PointerGetDatum(key),
00099                       entry->rel, entry->page,
00100                       entry->offset, FALSE);
00101         PG_RETURN_POINTER(retval);
00102     }
00103     PG_RETURN_POINTER(entry);
00104 }
00105 
00106 Datum
00107 ltree_same(PG_FUNCTION_ARGS)
00108 {
00109     ltree_gist *a = (ltree_gist *) PG_GETARG_POINTER(0);
00110     ltree_gist *b = (ltree_gist *) PG_GETARG_POINTER(1);
00111     bool       *result = (bool *) PG_GETARG_POINTER(2);
00112 
00113     *result = false;
00114     if (LTG_ISONENODE(a) != LTG_ISONENODE(b))
00115         PG_RETURN_POINTER(result);
00116 
00117     if (LTG_ISONENODE(a))
00118         *result = (ISEQ(LTG_NODE(a), LTG_NODE(b))) ? true : false;
00119     else
00120     {
00121         int32       i;
00122         BITVECP     sa = LTG_SIGN(a),
00123                     sb = LTG_SIGN(b);
00124 
00125         if (LTG_ISALLTRUE(a) != LTG_ISALLTRUE(b))
00126             PG_RETURN_POINTER(result);
00127 
00128         if (!ISEQ(LTG_LNODE(a), LTG_LNODE(b)))
00129             PG_RETURN_POINTER(result);
00130         if (!ISEQ(LTG_RNODE(a), LTG_RNODE(b)))
00131             PG_RETURN_POINTER(result);
00132 
00133         *result = true;
00134         if (!LTG_ISALLTRUE(a))
00135         {
00136             LOOPBYTE
00137             {
00138                 if (sa[i] != sb[i])
00139                 {
00140                     *result = false;
00141                     break;
00142                 }
00143             }
00144         }
00145     }
00146 
00147     PG_RETURN_POINTER(result);
00148 }
00149 
00150 static void
00151 hashing(BITVECP sign, ltree *t)
00152 {
00153     int         tlen = t->numlevel;
00154     ltree_level *cur = LTREE_FIRST(t);
00155     int         hash;
00156 
00157     while (tlen > 0)
00158     {
00159         hash = ltree_crc32_sz(cur->name, cur->len);
00160         HASH(sign, hash);
00161         cur = LEVEL_NEXT(cur);
00162         tlen--;
00163     }
00164 }
00165 
00166 Datum
00167 ltree_union(PG_FUNCTION_ARGS)
00168 {
00169     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
00170     int        *size = (int *) PG_GETARG_POINTER(1);
00171     BITVEC      base;
00172     int32       i,
00173                 j;
00174     ltree_gist *result,
00175                *cur;
00176     ltree      *left = NULL,
00177                *right = NULL,
00178                *curtree;
00179     bool        isalltrue = false;
00180     bool        isleqr;
00181 
00182     MemSet((void *) base, 0, sizeof(BITVEC));
00183     for (j = 0; j < entryvec->n; j++)
00184     {
00185         cur = GETENTRY(entryvec, j);
00186         if (LTG_ISONENODE(cur))
00187         {
00188             curtree = LTG_NODE(cur);
00189             hashing(base, curtree);
00190             if (!left || ltree_compare(left, curtree) > 0)
00191                 left = curtree;
00192             if (!right || ltree_compare(right, curtree) < 0)
00193                 right = curtree;
00194         }
00195         else
00196         {
00197             if (isalltrue || LTG_ISALLTRUE(cur))
00198                 isalltrue = true;
00199             else
00200             {
00201                 BITVECP     sc = LTG_SIGN(cur);
00202 
00203                 LOOPBYTE
00204                     ((unsigned char *) base)[i] |= sc[i];
00205             }
00206 
00207             curtree = LTG_LNODE(cur);
00208             if (!left || ltree_compare(left, curtree) > 0)
00209                 left = curtree;
00210             curtree = LTG_RNODE(cur);
00211             if (!right || ltree_compare(right, curtree) < 0)
00212                 right = curtree;
00213         }
00214     }
00215 
00216     if (isalltrue == false)
00217     {
00218         isalltrue = true;
00219         LOOPBYTE
00220         {
00221             if (((unsigned char *) base)[i] != 0xff)
00222             {
00223                 isalltrue = false;
00224                 break;
00225             }
00226         }
00227     }
00228 
00229     isleqr = (left == right || ISEQ(left, right)) ? true : false;
00230     *size = LTG_HDRSIZE + ((isalltrue) ? 0 : SIGLEN) + VARSIZE(left) + ((isleqr) ? 0 : VARSIZE(right));
00231 
00232     result = (ltree_gist *) palloc(*size);
00233     SET_VARSIZE(result, *size);
00234     result->flag = 0;
00235 
00236     if (isalltrue)
00237         result->flag |= LTG_ALLTRUE;
00238     else
00239         memcpy((void *) LTG_SIGN(result), base, SIGLEN);
00240 
00241     memcpy((void *) LTG_LNODE(result), (void *) left, VARSIZE(left));
00242     if (isleqr)
00243         result->flag |= LTG_NORIGHT;
00244     else
00245         memcpy((void *) LTG_RNODE(result), (void *) right, VARSIZE(right));
00246 
00247     PG_RETURN_POINTER(result);
00248 }
00249 
00250 Datum
00251 ltree_penalty(PG_FUNCTION_ARGS)
00252 {
00253     ltree_gist *origval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
00254     ltree_gist *newval = (ltree_gist *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
00255     float      *penalty = (float *) PG_GETARG_POINTER(2);
00256     int32       cmpr,
00257                 cmpl;
00258 
00259     cmpl = ltree_compare(LTG_GETLNODE(origval), LTG_GETLNODE(newval));
00260     cmpr = ltree_compare(LTG_GETRNODE(newval), LTG_GETRNODE(origval));
00261 
00262     *penalty = Max(cmpl, 0) + Max(cmpr, 0);
00263 
00264     PG_RETURN_POINTER(penalty);
00265 }
00266 
00267 /* used for sorting */
00268 typedef struct rix
00269 {
00270     int         index;
00271     ltree      *r;
00272 } RIX;
00273 
00274 static int
00275 treekey_cmp(const void *a, const void *b)
00276 {
00277     return ltree_compare(
00278                          ((const RIX *) a)->r,
00279                          ((const RIX *) b)->r
00280         );
00281 }
00282 
00283 
00284 Datum
00285 ltree_picksplit(PG_FUNCTION_ARGS)
00286 {
00287     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
00288     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
00289     OffsetNumber j;
00290     int32       i;
00291     RIX        *array;
00292     OffsetNumber maxoff;
00293     int         nbytes;
00294     int         size;
00295     ltree      *lu_l,
00296                *lu_r,
00297                *ru_l,
00298                *ru_r;
00299     ltree_gist *lu,
00300                *ru;
00301     BITVEC      ls,
00302                 rs;
00303     bool        lisat = false,
00304                 risat = false,
00305                 isleqr;
00306 
00307     memset((void *) ls, 0, sizeof(BITVEC));
00308     memset((void *) rs, 0, sizeof(BITVEC));
00309     maxoff = entryvec->n - 1;
00310     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
00311     v->spl_left = (OffsetNumber *) palloc(nbytes);
00312     v->spl_right = (OffsetNumber *) palloc(nbytes);
00313     v->spl_nleft = 0;
00314     v->spl_nright = 0;
00315     array = (RIX *) palloc(sizeof(RIX) * (maxoff + 1));
00316 
00317     /* copy the data into RIXes, and sort the RIXes */
00318     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
00319     {
00320         array[j].index = j;
00321         lu = GETENTRY(entryvec, j);     /* use as tmp val */
00322         array[j].r = LTG_GETLNODE(lu);
00323     }
00324 
00325     qsort((void *) &array[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1,
00326           sizeof(RIX), treekey_cmp);
00327 
00328     lu_l = lu_r = ru_l = ru_r = NULL;
00329     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
00330     {
00331         lu = GETENTRY(entryvec, array[j].index);        /* use as tmp val */
00332         if (j <= (maxoff - FirstOffsetNumber + 1) / 2)
00333         {
00334             v->spl_left[v->spl_nleft] = array[j].index;
00335             v->spl_nleft++;
00336             if (lu_r == NULL || ltree_compare(LTG_GETRNODE(lu), lu_r) > 0)
00337                 lu_r = LTG_GETRNODE(lu);
00338             if (LTG_ISONENODE(lu))
00339                 hashing(ls, LTG_NODE(lu));
00340             else
00341             {
00342                 if (lisat || LTG_ISALLTRUE(lu))
00343                     lisat = true;
00344                 else
00345                 {
00346                     BITVECP     sc = LTG_SIGN(lu);
00347 
00348                     LOOPBYTE
00349                         ((unsigned char *) ls)[i] |= sc[i];
00350                 }
00351             }
00352         }
00353         else
00354         {
00355             v->spl_right[v->spl_nright] = array[j].index;
00356             v->spl_nright++;
00357             if (ru_r == NULL || ltree_compare(LTG_GETRNODE(lu), ru_r) > 0)
00358                 ru_r = LTG_GETRNODE(lu);
00359             if (LTG_ISONENODE(lu))
00360                 hashing(rs, LTG_NODE(lu));
00361             else
00362             {
00363                 if (risat || LTG_ISALLTRUE(lu))
00364                     risat = true;
00365                 else
00366                 {
00367                     BITVECP     sc = LTG_SIGN(lu);
00368 
00369                     LOOPBYTE
00370                         ((unsigned char *) rs)[i] |= sc[i];
00371                 }
00372             }
00373         }
00374     }
00375 
00376     if (lisat == false)
00377     {
00378         lisat = true;
00379         LOOPBYTE
00380         {
00381             if (((unsigned char *) ls)[i] != 0xff)
00382             {
00383                 lisat = false;
00384                 break;
00385             }
00386         }
00387     }
00388 
00389     if (risat == false)
00390     {
00391         risat = true;
00392         LOOPBYTE
00393         {
00394             if (((unsigned char *) rs)[i] != 0xff)
00395             {
00396                 risat = false;
00397                 break;
00398             }
00399         }
00400     }
00401 
00402     lu_l = LTG_GETLNODE(GETENTRY(entryvec, array[FirstOffsetNumber].index));
00403     isleqr = (lu_l == lu_r || ISEQ(lu_l, lu_r)) ? true : false;
00404     size = LTG_HDRSIZE + ((lisat) ? 0 : SIGLEN) + VARSIZE(lu_l) + ((isleqr) ? 0 : VARSIZE(lu_r));
00405     lu = (ltree_gist *) palloc(size);
00406     SET_VARSIZE(lu, size);
00407     lu->flag = 0;
00408     if (lisat)
00409         lu->flag |= LTG_ALLTRUE;
00410     else
00411         memcpy((void *) LTG_SIGN(lu), ls, SIGLEN);
00412     memcpy((void *) LTG_LNODE(lu), (void *) lu_l, VARSIZE(lu_l));
00413     if (isleqr)
00414         lu->flag |= LTG_NORIGHT;
00415     else
00416         memcpy((void *) LTG_RNODE(lu), (void *) lu_r, VARSIZE(lu_r));
00417 
00418 
00419     ru_l = LTG_GETLNODE(GETENTRY(entryvec, array[1 + ((maxoff - FirstOffsetNumber + 1) / 2)].index));
00420     isleqr = (ru_l == ru_r || ISEQ(ru_l, ru_r)) ? true : false;
00421     size = LTG_HDRSIZE + ((risat) ? 0 : SIGLEN) + VARSIZE(ru_l) + ((isleqr) ? 0 : VARSIZE(ru_r));
00422     ru = (ltree_gist *) palloc(size);
00423     SET_VARSIZE(ru, size);
00424     ru->flag = 0;
00425     if (risat)
00426         ru->flag |= LTG_ALLTRUE;
00427     else
00428         memcpy((void *) LTG_SIGN(ru), rs, SIGLEN);
00429     memcpy((void *) LTG_LNODE(ru), (void *) ru_l, VARSIZE(ru_l));
00430     if (isleqr)
00431         ru->flag |= LTG_NORIGHT;
00432     else
00433         memcpy((void *) LTG_RNODE(ru), (void *) ru_r, VARSIZE(ru_r));
00434 
00435     v->spl_ldatum = PointerGetDatum(lu);
00436     v->spl_rdatum = PointerGetDatum(ru);
00437 
00438     PG_RETURN_POINTER(v);
00439 }
00440 
00441 static bool
00442 gist_isparent(ltree_gist *key, ltree *query)
00443 {
00444     int32       numlevel = query->numlevel;
00445     int         i;
00446 
00447     for (i = query->numlevel; i >= 0; i--)
00448     {
00449         query->numlevel = i;
00450         if (ltree_compare(query, LTG_GETLNODE(key)) >= 0 && ltree_compare(query, LTG_GETRNODE(key)) <= 0)
00451         {
00452             query->numlevel = numlevel;
00453             return true;
00454         }
00455     }
00456 
00457     query->numlevel = numlevel;
00458     return false;
00459 }
00460 
00461 static ltree *
00462 copy_ltree(ltree *src)
00463 {
00464     ltree      *dst = (ltree *) palloc(VARSIZE(src));
00465 
00466     memcpy(dst, src, VARSIZE(src));
00467     return dst;
00468 }
00469 
00470 static bool
00471 gist_ischild(ltree_gist *key, ltree *query)
00472 {
00473     ltree      *left = copy_ltree(LTG_GETLNODE(key));
00474     ltree      *right = copy_ltree(LTG_GETRNODE(key));
00475     bool        res = true;
00476 
00477     if (left->numlevel > query->numlevel)
00478         left->numlevel = query->numlevel;
00479 
00480     if (ltree_compare(query, left) < 0)
00481         res = false;
00482 
00483     if (right->numlevel > query->numlevel)
00484         right->numlevel = query->numlevel;
00485 
00486     if (res && ltree_compare(query, right) > 0)
00487         res = false;
00488 
00489     pfree(left);
00490     pfree(right);
00491 
00492     return res;
00493 }
00494 
00495 static bool
00496 gist_qe(ltree_gist *key, lquery *query)
00497 {
00498     lquery_level *curq = LQUERY_FIRST(query);
00499     BITVECP     sign = LTG_SIGN(key);
00500     int         qlen = query->numlevel;
00501 
00502     if (LTG_ISALLTRUE(key))
00503         return true;
00504 
00505     while (qlen > 0)
00506     {
00507         if (curq->numvar && LQL_CANLOOKSIGN(curq))
00508         {
00509             bool        isexist = false;
00510             int         vlen = curq->numvar;
00511             lquery_variant *curv = LQL_FIRST(curq);
00512 
00513             while (vlen > 0)
00514             {
00515                 if (GETBIT(sign, HASHVAL(curv->val)))
00516                 {
00517                     isexist = true;
00518                     break;
00519                 }
00520                 curv = LVAR_NEXT(curv);
00521                 vlen--;
00522             }
00523             if (!isexist)
00524                 return false;
00525         }
00526 
00527         curq = LQL_NEXT(curq);
00528         qlen--;
00529     }
00530 
00531     return true;
00532 }
00533 
00534 static int
00535 gist_tqcmp(ltree *t, lquery *q)
00536 {
00537     ltree_level *al = LTREE_FIRST(t);
00538     lquery_level *ql = LQUERY_FIRST(q);
00539     lquery_variant *bl;
00540     int         an = t->numlevel;
00541     int         bn = q->firstgood;
00542     int         res = 0;
00543 
00544     while (an > 0 && bn > 0)
00545     {
00546         bl = LQL_FIRST(ql);
00547         if ((res = memcmp(al->name, bl->name, Min(al->len, bl->len))) == 0)
00548         {
00549             if (al->len != bl->len)
00550                 return al->len - bl->len;
00551         }
00552         else
00553             return res;
00554         an--;
00555         bn--;
00556         al = LEVEL_NEXT(al);
00557         ql = LQL_NEXT(ql);
00558     }
00559 
00560     return Min(t->numlevel, q->firstgood) - q->firstgood;
00561 }
00562 
00563 static bool
00564 gist_between(ltree_gist *key, lquery *query)
00565 {
00566     if (query->firstgood == 0)
00567         return true;
00568 
00569     if (gist_tqcmp(LTG_GETLNODE(key), query) > 0)
00570         return false;
00571 
00572     if (gist_tqcmp(LTG_GETRNODE(key), query) < 0)
00573         return false;
00574 
00575     return true;
00576 }
00577 
00578 static bool
00579 checkcondition_bit(void *checkval, ITEM *val)
00580 {
00581     return (FLG_CANLOOKSIGN(val->flag)) ? GETBIT(checkval, HASHVAL(val->val)) : true;
00582 }
00583 
00584 static bool
00585 gist_qtxt(ltree_gist *key, ltxtquery *query)
00586 {
00587     if (LTG_ISALLTRUE(key))
00588         return true;
00589 
00590     return ltree_execute(
00591                          GETQUERY(query),
00592                          (void *) LTG_SIGN(key), false,
00593                          checkcondition_bit
00594         );
00595 }
00596 
00597 static bool
00598 arrq_cons(ltree_gist *key, ArrayType *_query)
00599 {
00600     lquery     *query = (lquery *) ARR_DATA_PTR(_query);
00601     int         num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
00602 
00603     if (ARR_NDIM(_query) > 1)
00604         ereport(ERROR,
00605                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
00606                  errmsg("array must be one-dimensional")));
00607     if (array_contains_nulls(_query))
00608         ereport(ERROR,
00609                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
00610                  errmsg("array must not contain nulls")));
00611 
00612     while (num > 0)
00613     {
00614         if (gist_qe(key, query) && gist_between(key, query))
00615             return true;
00616         num--;
00617         query = NEXTVAL(query);
00618     }
00619     return false;
00620 }
00621 
00622 Datum
00623 ltree_consistent(PG_FUNCTION_ARGS)
00624 {
00625     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
00626     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
00627 
00628     /* Oid      subtype = PG_GETARG_OID(3); */
00629     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
00630     ltree_gist *key = (ltree_gist *) DatumGetPointer(entry->key);
00631     void       *query = NULL;
00632     bool        res = false;
00633 
00634     /* All cases served by this function are exact */
00635     *recheck = false;
00636 
00637     switch (strategy)
00638     {
00639         case BTLessStrategyNumber:
00640             query = PG_GETARG_LTREE(1);
00641             res = (GIST_LEAF(entry)) ?
00642                 (ltree_compare((ltree *) query, LTG_NODE(key)) > 0)
00643                 :
00644                 (ltree_compare((ltree *) query, LTG_GETLNODE(key)) >= 0);
00645             break;
00646         case BTLessEqualStrategyNumber:
00647             query = PG_GETARG_LTREE(1);
00648             res = (ltree_compare((ltree *) query, LTG_GETLNODE(key)) >= 0);
00649             break;
00650         case BTEqualStrategyNumber:
00651             query = PG_GETARG_LTREE(1);
00652             if (GIST_LEAF(entry))
00653                 res = (ltree_compare((ltree *) query, LTG_NODE(key)) == 0);
00654             else
00655                 res = (
00656                        ltree_compare((ltree *) query, LTG_GETLNODE(key)) >= 0
00657                        &&
00658                        ltree_compare((ltree *) query, LTG_GETRNODE(key)) <= 0
00659                     );
00660             break;
00661         case BTGreaterEqualStrategyNumber:
00662             query = PG_GETARG_LTREE(1);
00663             res = (ltree_compare((ltree *) query, LTG_GETRNODE(key)) <= 0);
00664             break;
00665         case BTGreaterStrategyNumber:
00666             query = PG_GETARG_LTREE(1);
00667             res = (GIST_LEAF(entry)) ?
00668                 (ltree_compare((ltree *) query, LTG_GETRNODE(key)) < 0)
00669                 :
00670                 (ltree_compare((ltree *) query, LTG_GETRNODE(key)) <= 0);
00671             break;
00672         case 10:
00673             query = PG_GETARG_LTREE_COPY(1);
00674             res = (GIST_LEAF(entry)) ?
00675                 inner_isparent((ltree *) query, LTG_NODE(key))
00676                 :
00677                 gist_isparent(key, (ltree *) query);
00678             break;
00679         case 11:
00680             query = PG_GETARG_LTREE(1);
00681             res = (GIST_LEAF(entry)) ?
00682                 inner_isparent(LTG_NODE(key), (ltree *) query)
00683                 :
00684                 gist_ischild(key, (ltree *) query);
00685             break;
00686         case 12:
00687         case 13:
00688             query = PG_GETARG_LQUERY(1);
00689             if (GIST_LEAF(entry))
00690                 res = DatumGetBool(DirectFunctionCall2(ltq_regex,
00691                                               PointerGetDatum(LTG_NODE(key)),
00692                                             PointerGetDatum((lquery *) query)
00693                                                        ));
00694             else
00695                 res = (gist_qe(key, (lquery *) query) && gist_between(key, (lquery *) query));
00696             break;
00697         case 14:
00698         case 15:
00699             query = PG_GETARG_LQUERY(1);
00700             if (GIST_LEAF(entry))
00701                 res = DatumGetBool(DirectFunctionCall2(ltxtq_exec,
00702                                               PointerGetDatum(LTG_NODE(key)),
00703                                             PointerGetDatum((lquery *) query)
00704                                                        ));
00705             else
00706                 res = gist_qtxt(key, (ltxtquery *) query);
00707             break;
00708         case 16:
00709         case 17:
00710             query = DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
00711             if (GIST_LEAF(entry))
00712                 res = DatumGetBool(DirectFunctionCall2(lt_q_regex,
00713                                               PointerGetDatum(LTG_NODE(key)),
00714                                          PointerGetDatum((ArrayType *) query)
00715                                                        ));
00716             else
00717                 res = arrq_cons(key, (ArrayType *) query);
00718             break;
00719         default:
00720             /* internal error */
00721             elog(ERROR, "unrecognized StrategyNumber: %d", strategy);
00722     }
00723 
00724     PG_FREE_IF_COPY(query, 1);
00725     PG_RETURN_BOOL(res);
00726 }