LCOV - code coverage report
Current view: top level - contrib/ltree - _ltree_op.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 85.9 % 156 134
Test Date: 2026-02-28 20:14:43 Functions: 83.9 % 31 26
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  * contrib/ltree/_ltree_op.c
       3              :  *
       4              :  *
       5              :  * op function for ltree[]
       6              :  * Teodor Sigaev <teodor@stack.net>
       7              :  */
       8              : #include "postgres.h"
       9              : 
      10              : #include <ctype.h>
      11              : 
      12              : #include "ltree.h"
      13              : #include "utils/array.h"
      14              : 
      15            3 : PG_FUNCTION_INFO_V1(_ltree_isparent);
      16            2 : PG_FUNCTION_INFO_V1(_ltree_r_isparent);
      17            3 : PG_FUNCTION_INFO_V1(_ltree_risparent);
      18            2 : PG_FUNCTION_INFO_V1(_ltree_r_risparent);
      19            3 : PG_FUNCTION_INFO_V1(_ltq_regex);
      20            2 : PG_FUNCTION_INFO_V1(_ltq_rregex);
      21            3 : PG_FUNCTION_INFO_V1(_lt_q_regex);
      22            2 : PG_FUNCTION_INFO_V1(_lt_q_rregex);
      23            3 : PG_FUNCTION_INFO_V1(_ltxtq_exec);
      24            2 : PG_FUNCTION_INFO_V1(_ltxtq_rexec);
      25              : 
      26            3 : PG_FUNCTION_INFO_V1(_ltree_extract_isparent);
      27            3 : PG_FUNCTION_INFO_V1(_ltree_extract_risparent);
      28            3 : PG_FUNCTION_INFO_V1(_ltq_extract_regex);
      29            3 : PG_FUNCTION_INFO_V1(_ltxtq_extract_exec);
      30              : 
      31            3 : PG_FUNCTION_INFO_V1(_lca);
      32              : 
      33              : typedef Datum (*PGCALL2) (PG_FUNCTION_ARGS);
      34              : 
      35              : #define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
      36              : 
      37              : static bool
      38        20323 : array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
      39              : {
      40        20323 :     int         num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
      41        20323 :     ltree      *item = (ltree *) ARR_DATA_PTR(la);
      42              : 
      43        20323 :     if (ARR_NDIM(la) > 1)
      44            0 :         ereport(ERROR,
      45              :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
      46              :                  errmsg("array must be one-dimensional")));
      47        20323 :     if (array_contains_nulls(la))
      48            0 :         ereport(ERROR,
      49              :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
      50              :                  errmsg("array must not contain nulls")));
      51              : 
      52        20323 :     if (found)
      53            6 :         *found = NULL;
      54        91782 :     while (num > 0)
      55              :     {
      56        72507 :         if (DatumGetBool(DirectFunctionCall2(callback,
      57              :                                              PointerGetDatum(item), PointerGetDatum(param))))
      58              :         {
      59              : 
      60         1048 :             if (found)
      61            4 :                 *found = item;
      62         1048 :             return true;
      63              :         }
      64        71459 :         num--;
      65        71459 :         item = NEXTVAL(item);
      66              :     }
      67              : 
      68        19275 :     return false;
      69              : }
      70              : 
      71              : Datum
      72         3012 : _ltree_isparent(PG_FUNCTION_ARGS)
      73              : {
      74         3012 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
      75         3012 :     ltree      *query = PG_GETARG_LTREE_P(1);
      76         3012 :     bool        res = array_iterator(la, ltree_isparent, query, NULL);
      77              : 
      78         3012 :     PG_FREE_IF_COPY(la, 0);
      79         3012 :     PG_FREE_IF_COPY(query, 1);
      80         3012 :     PG_RETURN_BOOL(res);
      81              : }
      82              : 
      83              : Datum
      84            0 : _ltree_r_isparent(PG_FUNCTION_ARGS)
      85              : {
      86            0 :     PG_RETURN_DATUM(DirectFunctionCall2(_ltree_isparent,
      87              :                                         PG_GETARG_DATUM(1),
      88              :                                         PG_GETARG_DATUM(0)
      89              :                                         ));
      90              : }
      91              : 
      92              : Datum
      93         2310 : _ltree_risparent(PG_FUNCTION_ARGS)
      94              : {
      95         2310 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
      96         2310 :     ltree      *query = PG_GETARG_LTREE_P(1);
      97         2310 :     bool        res = array_iterator(la, ltree_risparent, query, NULL);
      98              : 
      99         2310 :     PG_FREE_IF_COPY(la, 0);
     100         2310 :     PG_FREE_IF_COPY(query, 1);
     101         2310 :     PG_RETURN_BOOL(res);
     102              : }
     103              : 
     104              : Datum
     105            0 : _ltree_r_risparent(PG_FUNCTION_ARGS)
     106              : {
     107            0 :     PG_RETURN_DATUM(DirectFunctionCall2(_ltree_risparent,
     108              :                                         PG_GETARG_DATUM(1),
     109              :                                         PG_GETARG_DATUM(0)
     110              :                                         ));
     111              : }
     112              : 
     113              : Datum
     114         9575 : _ltq_regex(PG_FUNCTION_ARGS)
     115              : {
     116         9575 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     117         9575 :     lquery     *query = PG_GETARG_LQUERY_P(1);
     118         9575 :     bool        res = array_iterator(la, ltq_regex, query, NULL);
     119              : 
     120         9575 :     PG_FREE_IF_COPY(la, 0);
     121         9575 :     PG_FREE_IF_COPY(query, 1);
     122         9575 :     PG_RETURN_BOOL(res);
     123              : }
     124              : 
     125              : Datum
     126            0 : _ltq_rregex(PG_FUNCTION_ARGS)
     127              : {
     128            0 :     PG_RETURN_DATUM(DirectFunctionCall2(_ltq_regex,
     129              :                                         PG_GETARG_DATUM(1),
     130              :                                         PG_GETARG_DATUM(0)
     131              :                                         ));
     132              : }
     133              : 
     134              : Datum
     135         1868 : _lt_q_regex(PG_FUNCTION_ARGS)
     136              : {
     137         1868 :     ArrayType  *_tree = PG_GETARG_ARRAYTYPE_P(0);
     138         1868 :     ArrayType  *_query = PG_GETARG_ARRAYTYPE_P(1);
     139         1868 :     lquery     *query = (lquery *) ARR_DATA_PTR(_query);
     140         1868 :     bool        res = false;
     141         1868 :     int         num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
     142              : 
     143         1868 :     if (ARR_NDIM(_query) > 1)
     144            0 :         ereport(ERROR,
     145              :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
     146              :                  errmsg("array must be one-dimensional")));
     147         1868 :     if (array_contains_nulls(_query))
     148            0 :         ereport(ERROR,
     149              :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
     150              :                  errmsg("array must not contain nulls")));
     151              : 
     152         5524 :     while (num > 0)
     153              :     {
     154         3702 :         if (array_iterator(_tree, ltq_regex, query, NULL))
     155              :         {
     156           46 :             res = true;
     157           46 :             break;
     158              :         }
     159         3656 :         num--;
     160         3656 :         query = (lquery *) NEXTVAL(query);
     161              :     }
     162              : 
     163         1868 :     PG_FREE_IF_COPY(_tree, 0);
     164         1868 :     PG_FREE_IF_COPY(_query, 1);
     165         1868 :     PG_RETURN_BOOL(res);
     166              : }
     167              : 
     168              : Datum
     169            0 : _lt_q_rregex(PG_FUNCTION_ARGS)
     170              : {
     171            0 :     PG_RETURN_DATUM(DirectFunctionCall2(_lt_q_regex,
     172              :                                         PG_GETARG_DATUM(1),
     173              :                                         PG_GETARG_DATUM(0)
     174              :                                         ));
     175              : }
     176              : 
     177              : 
     178              : Datum
     179         1718 : _ltxtq_exec(PG_FUNCTION_ARGS)
     180              : {
     181         1718 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     182         1718 :     ltxtquery  *query = PG_GETARG_LTXTQUERY_P(1);
     183         1718 :     bool        res = array_iterator(la, ltxtq_exec, query, NULL);
     184              : 
     185         1718 :     PG_FREE_IF_COPY(la, 0);
     186         1718 :     PG_FREE_IF_COPY(query, 1);
     187         1718 :     PG_RETURN_BOOL(res);
     188              : }
     189              : 
     190              : Datum
     191            0 : _ltxtq_rexec(PG_FUNCTION_ARGS)
     192              : {
     193            0 :     PG_RETURN_DATUM(DirectFunctionCall2(_ltxtq_exec,
     194              :                                         PG_GETARG_DATUM(1),
     195              :                                         PG_GETARG_DATUM(0)
     196              :                                         ));
     197              : }
     198              : 
     199              : 
     200              : Datum
     201            2 : _ltree_extract_isparent(PG_FUNCTION_ARGS)
     202              : {
     203            2 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     204            2 :     ltree      *query = PG_GETARG_LTREE_P(1);
     205              :     ltree      *found,
     206              :                *item;
     207              : 
     208            2 :     if (!array_iterator(la, ltree_isparent, query, &found))
     209              :     {
     210            1 :         PG_FREE_IF_COPY(la, 0);
     211            1 :         PG_FREE_IF_COPY(query, 1);
     212            1 :         PG_RETURN_NULL();
     213              :     }
     214              : 
     215            1 :     item = (ltree *) palloc0(VARSIZE(found));
     216            1 :     memcpy(item, found, VARSIZE(found));
     217              : 
     218            1 :     PG_FREE_IF_COPY(la, 0);
     219            1 :     PG_FREE_IF_COPY(query, 1);
     220            1 :     PG_RETURN_POINTER(item);
     221              : }
     222              : 
     223              : Datum
     224            2 : _ltree_extract_risparent(PG_FUNCTION_ARGS)
     225              : {
     226            2 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     227            2 :     ltree      *query = PG_GETARG_LTREE_P(1);
     228              :     ltree      *found,
     229              :                *item;
     230              : 
     231            2 :     if (!array_iterator(la, ltree_risparent, query, &found))
     232              :     {
     233            1 :         PG_FREE_IF_COPY(la, 0);
     234            1 :         PG_FREE_IF_COPY(query, 1);
     235            1 :         PG_RETURN_NULL();
     236              :     }
     237              : 
     238            1 :     item = (ltree *) palloc0(VARSIZE(found));
     239            1 :     memcpy(item, found, VARSIZE(found));
     240              : 
     241            1 :     PG_FREE_IF_COPY(la, 0);
     242            1 :     PG_FREE_IF_COPY(query, 1);
     243            1 :     PG_RETURN_POINTER(item);
     244              : }
     245              : 
     246              : Datum
     247            1 : _ltq_extract_regex(PG_FUNCTION_ARGS)
     248              : {
     249            1 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     250            1 :     lquery     *query = PG_GETARG_LQUERY_P(1);
     251              :     ltree      *found,
     252              :                *item;
     253              : 
     254            1 :     if (!array_iterator(la, ltq_regex, query, &found))
     255              :     {
     256            0 :         PG_FREE_IF_COPY(la, 0);
     257            0 :         PG_FREE_IF_COPY(query, 1);
     258            0 :         PG_RETURN_NULL();
     259              :     }
     260              : 
     261            1 :     item = (ltree *) palloc0(VARSIZE(found));
     262            1 :     memcpy(item, found, VARSIZE(found));
     263              : 
     264            1 :     PG_FREE_IF_COPY(la, 0);
     265            1 :     PG_FREE_IF_COPY(query, 1);
     266            1 :     PG_RETURN_POINTER(item);
     267              : }
     268              : 
     269              : Datum
     270            1 : _ltxtq_extract_exec(PG_FUNCTION_ARGS)
     271              : {
     272            1 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     273            1 :     ltxtquery  *query = PG_GETARG_LTXTQUERY_P(1);
     274              :     ltree      *found,
     275              :                *item;
     276              : 
     277            1 :     if (!array_iterator(la, ltxtq_exec, query, &found))
     278              :     {
     279            0 :         PG_FREE_IF_COPY(la, 0);
     280            0 :         PG_FREE_IF_COPY(query, 1);
     281            0 :         PG_RETURN_NULL();
     282              :     }
     283              : 
     284            1 :     item = (ltree *) palloc0(VARSIZE(found));
     285            1 :     memcpy(item, found, VARSIZE(found));
     286              : 
     287            1 :     PG_FREE_IF_COPY(la, 0);
     288            1 :     PG_FREE_IF_COPY(query, 1);
     289            1 :     PG_RETURN_POINTER(item);
     290              : }
     291              : 
     292              : Datum
     293            8 : _lca(PG_FUNCTION_ARGS)
     294              : {
     295            8 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     296            8 :     int         num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
     297            8 :     ltree      *item = (ltree *) ARR_DATA_PTR(la);
     298              :     ltree     **a,
     299              :                *res;
     300              : 
     301            8 :     if (ARR_NDIM(la) > 1)
     302            0 :         ereport(ERROR,
     303              :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
     304              :                  errmsg("array must be one-dimensional")));
     305            8 :     if (array_contains_nulls(la))
     306            0 :         ereport(ERROR,
     307              :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
     308              :                  errmsg("array must not contain nulls")));
     309              : 
     310            8 :     a = palloc_array(ltree *, num);
     311           20 :     while (num > 0)
     312              :     {
     313           12 :         num--;
     314           12 :         a[num] = item;
     315           12 :         item = NEXTVAL(item);
     316              :     }
     317            8 :     res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
     318            8 :     pfree(a);
     319              : 
     320            8 :     PG_FREE_IF_COPY(la, 0);
     321              : 
     322            8 :     if (res)
     323            6 :         PG_RETURN_POINTER(res);
     324              :     else
     325            2 :         PG_RETURN_NULL();
     326              : }
        

Generated by: LCOV version 2.0-1