LCOV - code coverage report
Current view: top level - contrib/ltree - ltree_op.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 293 317 92.4 %
Date: 2024-11-21 09:14:53 Functions: 47 50 94.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * op function for ltree
       3             :  * Teodor Sigaev <teodor@stack.net>
       4             :  * contrib/ltree/ltree_op.c
       5             :  */
       6             : #include "postgres.h"
       7             : 
       8             : #include <ctype.h>
       9             : 
      10             : #include "common/hashfn.h"
      11             : #include "ltree.h"
      12             : #include "utils/builtins.h"
      13             : #include "utils/selfuncs.h"
      14             : #include "varatt.h"
      15             : 
      16           6 : PG_MODULE_MAGIC;
      17             : 
      18             : /* compare functions */
      19           6 : PG_FUNCTION_INFO_V1(ltree_cmp);
      20           6 : PG_FUNCTION_INFO_V1(ltree_lt);
      21           6 : PG_FUNCTION_INFO_V1(ltree_le);
      22           6 : PG_FUNCTION_INFO_V1(ltree_eq);
      23           4 : PG_FUNCTION_INFO_V1(ltree_ne);
      24           6 : PG_FUNCTION_INFO_V1(ltree_ge);
      25           6 : PG_FUNCTION_INFO_V1(ltree_gt);
      26           6 : PG_FUNCTION_INFO_V1(hash_ltree);
      27           6 : PG_FUNCTION_INFO_V1(hash_ltree_extended);
      28           6 : PG_FUNCTION_INFO_V1(nlevel);
      29           6 : PG_FUNCTION_INFO_V1(ltree_isparent);
      30           6 : PG_FUNCTION_INFO_V1(ltree_risparent);
      31           6 : PG_FUNCTION_INFO_V1(subltree);
      32          12 : PG_FUNCTION_INFO_V1(subpath);
      33          12 : PG_FUNCTION_INFO_V1(ltree_index);
      34           6 : PG_FUNCTION_INFO_V1(ltree_addltree);
      35           6 : PG_FUNCTION_INFO_V1(ltree_addtext);
      36           4 : PG_FUNCTION_INFO_V1(ltree_textadd);
      37          32 : PG_FUNCTION_INFO_V1(lca);
      38           6 : PG_FUNCTION_INFO_V1(ltree2text);
      39           6 : PG_FUNCTION_INFO_V1(text2ltree);
      40           4 : PG_FUNCTION_INFO_V1(ltreeparentsel);
      41             : 
      42             : int
      43      276984 : ltree_compare(const ltree *a, const ltree *b)
      44             : {
      45      276984 :     ltree_level *al = LTREE_FIRST(a);
      46      276984 :     ltree_level *bl = LTREE_FIRST(b);
      47      276984 :     int         an = a->numlevel;
      48      276984 :     int         bn = b->numlevel;
      49             : 
      50      476690 :     while (an > 0 && bn > 0)
      51             :     {
      52             :         int         res;
      53             : 
      54      453344 :         if ((res = memcmp(al->name, bl->name, Min(al->len, bl->len))) == 0)
      55             :         {
      56      217488 :             if (al->len != bl->len)
      57       17782 :                 return (al->len - bl->len) * 10 * (an + 1);
      58             :         }
      59             :         else
      60             :         {
      61      235856 :             if (res < 0)
      62      115404 :                 res = -1;
      63             :             else
      64      120452 :                 res = 1;
      65      235856 :             return res * 10 * (an + 1);
      66             :         }
      67             : 
      68      199706 :         an--;
      69      199706 :         bn--;
      70      199706 :         al = LEVEL_NEXT(al);
      71      199706 :         bl = LEVEL_NEXT(bl);
      72             :     }
      73             : 
      74       23346 :     return (a->numlevel - b->numlevel) * 10 * (an + 1);
      75             : }
      76             : 
      77             : #define RUNCMP                      \
      78             : ltree *a = PG_GETARG_LTREE_P(0);    \
      79             : ltree *b = PG_GETARG_LTREE_P(1);    \
      80             : int res = ltree_compare(a,b);       \
      81             : PG_FREE_IF_COPY(a,0);               \
      82             : PG_FREE_IF_COPY(b,1)
      83             : 
      84             : Datum
      85      142436 : ltree_cmp(PG_FUNCTION_ARGS)
      86             : {
      87      142436 :     RUNCMP;
      88      142436 :     PG_RETURN_INT32(res);
      89             : }
      90             : 
      91             : Datum
      92        4278 : ltree_lt(PG_FUNCTION_ARGS)
      93             : {
      94        4278 :     RUNCMP;
      95        4278 :     PG_RETURN_BOOL(res < 0);
      96             : }
      97             : 
      98             : Datum
      99        4280 : ltree_le(PG_FUNCTION_ARGS)
     100             : {
     101        4280 :     RUNCMP;
     102        4280 :     PG_RETURN_BOOL(res <= 0);
     103             : }
     104             : 
     105             : Datum
     106        4032 : ltree_eq(PG_FUNCTION_ARGS)
     107             : {
     108        4032 :     RUNCMP;
     109        4032 :     PG_RETURN_BOOL(res == 0);
     110             : }
     111             : 
     112             : Datum
     113        4064 : ltree_ge(PG_FUNCTION_ARGS)
     114             : {
     115        4064 :     RUNCMP;
     116        4064 :     PG_RETURN_BOOL(res >= 0);
     117             : }
     118             : 
     119             : Datum
     120        4064 : ltree_gt(PG_FUNCTION_ARGS)
     121             : {
     122        4064 :     RUNCMP;
     123        4064 :     PG_RETURN_BOOL(res > 0);
     124             : }
     125             : 
     126             : Datum
     127           0 : ltree_ne(PG_FUNCTION_ARGS)
     128             : {
     129           0 :     RUNCMP;
     130           0 :     PG_RETURN_BOOL(res != 0);
     131             : }
     132             : 
     133             : /* Compute a hash for the ltree */
     134             : Datum
     135        6062 : hash_ltree(PG_FUNCTION_ARGS)
     136             : {
     137        6062 :     ltree      *a = PG_GETARG_LTREE_P(0);
     138        6062 :     uint32      result = 1;
     139        6062 :     int         an = a->numlevel;
     140        6062 :     ltree_level *al = LTREE_FIRST(a);
     141             : 
     142       45744 :     while (an > 0)
     143             :     {
     144       39682 :         uint32      levelHash = DatumGetUInt32(hash_any((unsigned char *) al->name, al->len));
     145             : 
     146             :         /*
     147             :          * Combine hash values of successive elements by multiplying the
     148             :          * current value by 31 and adding on the new element's hash value.
     149             :          *
     150             :          * This method is borrowed from hash_array(), which see for further
     151             :          * commentary.
     152             :          */
     153       39682 :         result = (result << 5) - result + levelHash;
     154             : 
     155       39682 :         an--;
     156       39682 :         al = LEVEL_NEXT(al);
     157             :     }
     158             : 
     159        6062 :     PG_FREE_IF_COPY(a, 0);
     160        6062 :     PG_RETURN_UINT32(result);
     161             : }
     162             : 
     163             : /* Compute an extended hash for the ltree */
     164             : Datum
     165          24 : hash_ltree_extended(PG_FUNCTION_ARGS)
     166             : {
     167          24 :     ltree      *a = PG_GETARG_LTREE_P(0);
     168          24 :     const uint64 seed = PG_GETARG_INT64(1);
     169          24 :     uint64      result = 1;
     170          24 :     int         an = a->numlevel;
     171          24 :     ltree_level *al = LTREE_FIRST(a);
     172             : 
     173             :     /*
     174             :      * If the path has length zero, return 1 + seed to ensure that the low 32
     175             :      * bits of the result match hash_ltree when the seed is 0, as required by
     176             :      * the hash index support functions, but to also return a different value
     177             :      * when there is a seed.
     178             :      */
     179          24 :     if (an == 0)
     180             :     {
     181           4 :         PG_FREE_IF_COPY(a, 0);
     182           4 :         PG_RETURN_UINT64(result + seed);
     183             :     }
     184             : 
     185          56 :     while (an > 0)
     186             :     {
     187          36 :         uint64      levelHash = DatumGetUInt64(hash_any_extended((unsigned char *) al->name, al->len, seed));
     188             : 
     189          36 :         result = (result << 5) - result + levelHash;
     190             : 
     191          36 :         an--;
     192          36 :         al = LEVEL_NEXT(al);
     193             :     }
     194             : 
     195          20 :     PG_FREE_IF_COPY(a, 0);
     196          20 :     PG_RETURN_UINT64(result);
     197             : }
     198             : 
     199             : Datum
     200           4 : nlevel(PG_FUNCTION_ARGS)
     201             : {
     202           4 :     ltree      *a = PG_GETARG_LTREE_P(0);
     203           4 :     int         res = a->numlevel;
     204             : 
     205           4 :     PG_FREE_IF_COPY(a, 0);
     206           4 :     PG_RETURN_INT32(res);
     207             : }
     208             : 
     209             : bool
     210       42376 : inner_isparent(const ltree *c, const ltree *p)
     211             : {
     212       42376 :     ltree_level *cl = LTREE_FIRST(c);
     213       42376 :     ltree_level *pl = LTREE_FIRST(p);
     214       42376 :     int         pn = p->numlevel;
     215             : 
     216       42376 :     if (pn > c->numlevel)
     217       20332 :         return false;
     218             : 
     219       24038 :     while (pn > 0)
     220             :     {
     221       23766 :         if (cl->len != pl->len)
     222       15920 :             return false;
     223        7846 :         if (memcmp(cl->name, pl->name, cl->len) != 0)
     224        5852 :             return false;
     225             : 
     226        1994 :         pn--;
     227        1994 :         cl = LEVEL_NEXT(cl);
     228        1994 :         pl = LEVEL_NEXT(pl);
     229             :     }
     230         272 :     return true;
     231             : }
     232             : 
     233             : Datum
     234       23076 : ltree_isparent(PG_FUNCTION_ARGS)
     235             : {
     236       23076 :     ltree      *c = PG_GETARG_LTREE_P(1);
     237       23076 :     ltree      *p = PG_GETARG_LTREE_P(0);
     238       23076 :     bool        res = inner_isparent(c, p);
     239             : 
     240       23076 :     PG_FREE_IF_COPY(c, 1);
     241       23076 :     PG_FREE_IF_COPY(p, 0);
     242       23076 :     PG_RETURN_BOOL(res);
     243             : }
     244             : 
     245             : Datum
     246       18640 : ltree_risparent(PG_FUNCTION_ARGS)
     247             : {
     248       18640 :     ltree      *c = PG_GETARG_LTREE_P(0);
     249       18640 :     ltree      *p = PG_GETARG_LTREE_P(1);
     250       18640 :     bool        res = inner_isparent(c, p);
     251             : 
     252       18640 :     PG_FREE_IF_COPY(c, 0);
     253       18640 :     PG_FREE_IF_COPY(p, 1);
     254       18640 :     PG_RETURN_BOOL(res);
     255             : }
     256             : 
     257             : 
     258             : static ltree *
     259          18 : inner_subltree(ltree *t, int32 startpos, int32 endpos)
     260             : {
     261          18 :     char       *start = NULL,
     262          18 :                *end = NULL;
     263          18 :     ltree_level *ptr = LTREE_FIRST(t);
     264             :     ltree      *res;
     265             :     int         i;
     266             : 
     267          18 :     if (startpos < 0 || endpos < 0 || startpos >= t->numlevel || startpos > endpos)
     268           0 :         ereport(ERROR,
     269             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     270             :                  errmsg("invalid positions")));
     271             : 
     272          18 :     if (endpos > t->numlevel)
     273           4 :         endpos = t->numlevel;
     274             : 
     275          18 :     start = end = (char *) ptr;
     276          38 :     for (i = 0; i < endpos; i++)
     277             :     {
     278          36 :         if (i == startpos)
     279          14 :             start = (char *) ptr;
     280          36 :         if (i == endpos - 1)
     281             :         {
     282          16 :             end = (char *) LEVEL_NEXT(ptr);
     283          16 :             break;
     284             :         }
     285          20 :         ptr = LEVEL_NEXT(ptr);
     286             :     }
     287             : 
     288          18 :     res = (ltree *) palloc0(LTREE_HDRSIZE + (end - start));
     289          18 :     SET_VARSIZE(res, LTREE_HDRSIZE + (end - start));
     290          18 :     res->numlevel = endpos - startpos;
     291             : 
     292          18 :     memcpy(LTREE_FIRST(res), start, end - start);
     293             : 
     294          18 :     return res;
     295             : }
     296             : 
     297             : Datum
     298           2 : subltree(PG_FUNCTION_ARGS)
     299             : {
     300           2 :     ltree      *t = PG_GETARG_LTREE_P(0);
     301           2 :     ltree      *res = inner_subltree(t, PG_GETARG_INT32(1), PG_GETARG_INT32(2));
     302             : 
     303           2 :     PG_FREE_IF_COPY(t, 0);
     304           2 :     PG_RETURN_POINTER(res);
     305             : }
     306             : 
     307             : Datum
     308          16 : subpath(PG_FUNCTION_ARGS)
     309             : {
     310          16 :     ltree      *t = PG_GETARG_LTREE_P(0);
     311          16 :     int32       start = PG_GETARG_INT32(1);
     312          16 :     int32       len = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
     313             :     int32       end;
     314             :     ltree      *res;
     315             : 
     316          16 :     end = start + len;
     317             : 
     318          16 :     if (start < 0)
     319             :     {
     320           2 :         start = t->numlevel + start;
     321           2 :         end = start + len;
     322             :     }
     323          16 :     if (start < 0)
     324             :     {                           /* start > t->numlevel */
     325           0 :         start = t->numlevel + start;
     326           0 :         end = start + len;
     327             :     }
     328             : 
     329          16 :     if (len < 0)
     330           4 :         end = t->numlevel + len;
     331          12 :     else if (len == 0)
     332           8 :         end = (fcinfo->nargs == 3) ? start : 0xffff;
     333             : 
     334          16 :     res = inner_subltree(t, start, end);
     335             : 
     336          16 :     PG_FREE_IF_COPY(t, 0);
     337          16 :     PG_RETURN_POINTER(res);
     338             : }
     339             : 
     340             : static ltree *
     341          12 : ltree_concat(ltree *a, ltree *b)
     342             : {
     343             :     ltree      *r;
     344          12 :     int         numlevel = (int) a->numlevel + b->numlevel;
     345             : 
     346          12 :     if (numlevel > LTREE_MAX_LEVELS)
     347           2 :         ereport(ERROR,
     348             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     349             :                  errmsg("number of ltree levels (%d) exceeds the maximum allowed (%d)",
     350             :                         numlevel, LTREE_MAX_LEVELS)));
     351             : 
     352          10 :     r = (ltree *) palloc0(VARSIZE(a) + VARSIZE(b) - LTREE_HDRSIZE);
     353          10 :     SET_VARSIZE(r, VARSIZE(a) + VARSIZE(b) - LTREE_HDRSIZE);
     354          10 :     r->numlevel = (uint16) numlevel;
     355             : 
     356          10 :     memcpy(LTREE_FIRST(r), LTREE_FIRST(a), VARSIZE(a) - LTREE_HDRSIZE);
     357          10 :     memcpy(((char *) LTREE_FIRST(r)) + VARSIZE(a) - LTREE_HDRSIZE,
     358             :            LTREE_FIRST(b),
     359          10 :            VARSIZE(b) - LTREE_HDRSIZE);
     360          10 :     return r;
     361             : }
     362             : 
     363             : Datum
     364          10 : ltree_addltree(PG_FUNCTION_ARGS)
     365             : {
     366          10 :     ltree      *a = PG_GETARG_LTREE_P(0);
     367          10 :     ltree      *b = PG_GETARG_LTREE_P(1);
     368             :     ltree      *r;
     369             : 
     370          10 :     r = ltree_concat(a, b);
     371           8 :     PG_FREE_IF_COPY(a, 0);
     372           8 :     PG_FREE_IF_COPY(b, 1);
     373           8 :     PG_RETURN_POINTER(r);
     374             : }
     375             : 
     376             : Datum
     377           2 : ltree_addtext(PG_FUNCTION_ARGS)
     378             : {
     379           2 :     ltree      *a = PG_GETARG_LTREE_P(0);
     380           2 :     text       *b = PG_GETARG_TEXT_PP(1);
     381             :     char       *s;
     382             :     ltree      *r,
     383             :                *tmp;
     384             : 
     385           2 :     s = text_to_cstring(b);
     386             : 
     387           2 :     tmp = (ltree *) DatumGetPointer(DirectFunctionCall1(ltree_in,
     388             :                                                         PointerGetDatum(s)));
     389             : 
     390           2 :     pfree(s);
     391             : 
     392           2 :     r = ltree_concat(a, tmp);
     393             : 
     394           2 :     pfree(tmp);
     395             : 
     396           2 :     PG_FREE_IF_COPY(a, 0);
     397           2 :     PG_FREE_IF_COPY(b, 1);
     398           2 :     PG_RETURN_POINTER(r);
     399             : }
     400             : 
     401             : Datum
     402          36 : ltree_index(PG_FUNCTION_ARGS)
     403             : {
     404          36 :     ltree      *a = PG_GETARG_LTREE_P(0);
     405          36 :     ltree      *b = PG_GETARG_LTREE_P(1);
     406          36 :     int         start = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
     407             :     int         i,
     408             :                 j;
     409             :     ltree_level *startptr,
     410             :                *aptr,
     411             :                *bptr;
     412          36 :     bool        found = false;
     413             : 
     414          36 :     if (start < 0)
     415             :     {
     416          10 :         if (-start >= a->numlevel)
     417           2 :             start = 0;
     418             :         else
     419           8 :             start = (int) (a->numlevel) + start;
     420             :     }
     421             : 
     422          36 :     if (a->numlevel - start < b->numlevel || a->numlevel == 0 || b->numlevel == 0)
     423             :     {
     424           2 :         PG_FREE_IF_COPY(a, 0);
     425           2 :         PG_FREE_IF_COPY(b, 1);
     426           2 :         PG_RETURN_INT32(-1);
     427             :     }
     428             : 
     429          34 :     startptr = LTREE_FIRST(a);
     430         218 :     for (i = 0; i <= a->numlevel - b->numlevel; i++)
     431             :     {
     432         212 :         if (i >= start)
     433             :         {
     434         116 :             aptr = startptr;
     435         116 :             bptr = LTREE_FIRST(b);
     436         186 :             for (j = 0; j < b->numlevel; j++)
     437             :             {
     438         158 :                 if (!(aptr->len == bptr->len && memcmp(aptr->name, bptr->name, aptr->len) == 0))
     439             :                     break;
     440          70 :                 aptr = LEVEL_NEXT(aptr);
     441          70 :                 bptr = LEVEL_NEXT(bptr);
     442             :             }
     443             : 
     444         116 :             if (j == b->numlevel)
     445             :             {
     446          28 :                 found = true;
     447          28 :                 break;
     448             :             }
     449             :         }
     450         184 :         startptr = LEVEL_NEXT(startptr);
     451             :     }
     452             : 
     453          34 :     if (!found)
     454           6 :         i = -1;
     455             : 
     456          34 :     PG_FREE_IF_COPY(a, 0);
     457          34 :     PG_FREE_IF_COPY(b, 1);
     458          34 :     PG_RETURN_INT32(i);
     459             : }
     460             : 
     461             : Datum
     462           0 : ltree_textadd(PG_FUNCTION_ARGS)
     463             : {
     464           0 :     ltree      *a = PG_GETARG_LTREE_P(1);
     465           0 :     text       *b = PG_GETARG_TEXT_PP(0);
     466             :     char       *s;
     467             :     ltree      *r,
     468             :                *tmp;
     469             : 
     470           0 :     s = text_to_cstring(b);
     471             : 
     472           0 :     tmp = (ltree *) DatumGetPointer(DirectFunctionCall1(ltree_in,
     473             :                                                         PointerGetDatum(s)));
     474             : 
     475           0 :     pfree(s);
     476             : 
     477           0 :     r = ltree_concat(tmp, a);
     478             : 
     479           0 :     pfree(tmp);
     480             : 
     481           0 :     PG_FREE_IF_COPY(a, 1);
     482           0 :     PG_FREE_IF_COPY(b, 0);
     483           0 :     PG_RETURN_POINTER(r);
     484             : }
     485             : 
     486             : /*
     487             :  * Common code for variants of lca(), find longest common ancestor of inputs
     488             :  *
     489             :  * Returns NULL if there is no common ancestor, ie, the longest common
     490             :  * prefix is empty.
     491             :  */
     492             : ltree *
     493          28 : lca_inner(ltree **a, int len)
     494             : {
     495             :     int         tmp,
     496             :                 num,
     497             :                 i,
     498             :                 reslen;
     499             :     ltree     **ptr;
     500             :     ltree_level *l1,
     501             :                *l2;
     502             :     ltree      *res;
     503             : 
     504          28 :     if (len <= 0)
     505           2 :         return NULL;            /* no inputs? */
     506          26 :     if ((*a)->numlevel == 0)
     507           2 :         return NULL;            /* any empty input means NULL result */
     508             : 
     509             :     /* num is the length of the longest common ancestor so far */
     510          24 :     num = (*a)->numlevel - 1;
     511             : 
     512             :     /* Compare each additional input to *a */
     513          24 :     ptr = a + 1;
     514          46 :     while (ptr - a < len)
     515             :     {
     516          24 :         if ((*ptr)->numlevel == 0)
     517           2 :             return NULL;
     518          22 :         else if ((*ptr)->numlevel == 1)
     519           4 :             num = 0;
     520             :         else
     521             :         {
     522          18 :             l1 = LTREE_FIRST(*a);
     523          18 :             l2 = LTREE_FIRST(*ptr);
     524          18 :             tmp = Min(num, (*ptr)->numlevel - 1);
     525          18 :             num = 0;
     526          46 :             for (i = 0; i < tmp; i++)
     527             :             {
     528          42 :                 if (l1->len == l2->len &&
     529          36 :                     memcmp(l1->name, l2->name, l1->len) == 0)
     530          28 :                     num = i + 1;
     531             :                 else
     532             :                     break;
     533          28 :                 l1 = LEVEL_NEXT(l1);
     534          28 :                 l2 = LEVEL_NEXT(l2);
     535             :             }
     536             :         }
     537          22 :         ptr++;
     538             :     }
     539             : 
     540             :     /* Now compute size of result ... */
     541          22 :     reslen = LTREE_HDRSIZE;
     542          22 :     l1 = LTREE_FIRST(*a);
     543          42 :     for (i = 0; i < num; i++)
     544             :     {
     545          20 :         reslen += MAXALIGN(l1->len + LEVEL_HDRSIZE);
     546          20 :         l1 = LEVEL_NEXT(l1);
     547             :     }
     548             : 
     549             :     /* ... and construct it by copying from *a */
     550          22 :     res = (ltree *) palloc0(reslen);
     551          22 :     SET_VARSIZE(res, reslen);
     552          22 :     res->numlevel = num;
     553             : 
     554          22 :     l1 = LTREE_FIRST(*a);
     555          22 :     l2 = LTREE_FIRST(res);
     556             : 
     557          42 :     for (i = 0; i < num; i++)
     558             :     {
     559          20 :         memcpy(l2, l1, MAXALIGN(l1->len + LEVEL_HDRSIZE));
     560          20 :         l1 = LEVEL_NEXT(l1);
     561          20 :         l2 = LEVEL_NEXT(l2);
     562             :     }
     563             : 
     564          22 :     return res;
     565             : }
     566             : 
     567             : Datum
     568          12 : lca(PG_FUNCTION_ARGS)
     569             : {
     570             :     int         i;
     571             :     ltree     **a,
     572             :                *res;
     573             : 
     574          12 :     a = (ltree **) palloc(sizeof(ltree *) * fcinfo->nargs);
     575          42 :     for (i = 0; i < fcinfo->nargs; i++)
     576          30 :         a[i] = PG_GETARG_LTREE_P(i);
     577          12 :     res = lca_inner(a, (int) fcinfo->nargs);
     578          42 :     for (i = 0; i < fcinfo->nargs; i++)
     579          30 :         PG_FREE_IF_COPY(a[i], i);
     580          12 :     pfree(a);
     581             : 
     582          12 :     if (res)
     583          10 :         PG_RETURN_POINTER(res);
     584             :     else
     585           2 :         PG_RETURN_NULL();
     586             : }
     587             : 
     588             : Datum
     589           2 : text2ltree(PG_FUNCTION_ARGS)
     590             : {
     591           2 :     text       *in = PG_GETARG_TEXT_PP(0);
     592             :     char       *s;
     593             :     ltree      *out;
     594             : 
     595           2 :     s = text_to_cstring(in);
     596             : 
     597           2 :     out = (ltree *) DatumGetPointer(DirectFunctionCall1(ltree_in,
     598             :                                                         PointerGetDatum(s)));
     599           2 :     pfree(s);
     600           2 :     PG_FREE_IF_COPY(in, 0);
     601           2 :     PG_RETURN_POINTER(out);
     602             : }
     603             : 
     604             : 
     605             : Datum
     606           2 : ltree2text(PG_FUNCTION_ARGS)
     607             : {
     608           2 :     ltree      *in = PG_GETARG_LTREE_P(0);
     609             :     char       *ptr;
     610             :     int         i;
     611             :     ltree_level *curlevel;
     612             :     text       *out;
     613             : 
     614           2 :     out = (text *) palloc(VARSIZE(in) + VARHDRSZ);
     615           2 :     ptr = VARDATA(out);
     616           2 :     curlevel = LTREE_FIRST(in);
     617          12 :     for (i = 0; i < in->numlevel; i++)
     618             :     {
     619          10 :         if (i != 0)
     620             :         {
     621           8 :             *ptr = '.';
     622           8 :             ptr++;
     623             :         }
     624          10 :         memcpy(ptr, curlevel->name, curlevel->len);
     625          10 :         ptr += curlevel->len;
     626          10 :         curlevel = LEVEL_NEXT(curlevel);
     627             :     }
     628             : 
     629           2 :     SET_VARSIZE(out, ptr - ((char *) out));
     630           2 :     PG_FREE_IF_COPY(in, 0);
     631             : 
     632           2 :     PG_RETURN_POINTER(out);
     633             : }
     634             : 
     635             : 
     636             : /*
     637             :  *  ltreeparentsel - Selectivity of parent relationship for ltree data types.
     638             :  *
     639             :  * This function is not used anymore, if the ltree extension has been
     640             :  * updated to 1.2 or later.
     641             :  */
     642             : Datum
     643           0 : ltreeparentsel(PG_FUNCTION_ARGS)
     644             : {
     645           0 :     PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
     646           0 :     Oid         operator = PG_GETARG_OID(1);
     647           0 :     List       *args = (List *) PG_GETARG_POINTER(2);
     648           0 :     int         varRelid = PG_GETARG_INT32(3);
     649             :     double      selec;
     650             : 
     651             :     /* Use generic restriction selectivity logic, with default 0.001. */
     652           0 :     selec = generic_restriction_selectivity(root, operator, InvalidOid,
     653             :                                             args, varRelid,
     654             :                                             0.001);
     655             : 
     656           0 :     PG_RETURN_FLOAT8((float8) selec);
     657             : }

Generated by: LCOV version 1.14