LCOV - code coverage report
Current view: top level - contrib/ltree - _ltree_op.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 134 156 85.9 %
Date: 2024-05-19 07:11:14 Functions: 26 31 83.9 %
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           6 : PG_FUNCTION_INFO_V1(_ltree_isparent);
      16           4 : PG_FUNCTION_INFO_V1(_ltree_r_isparent);
      17           6 : PG_FUNCTION_INFO_V1(_ltree_risparent);
      18           4 : PG_FUNCTION_INFO_V1(_ltree_r_risparent);
      19           6 : PG_FUNCTION_INFO_V1(_ltq_regex);
      20           4 : PG_FUNCTION_INFO_V1(_ltq_rregex);
      21           6 : PG_FUNCTION_INFO_V1(_lt_q_regex);
      22           4 : PG_FUNCTION_INFO_V1(_lt_q_rregex);
      23           6 : PG_FUNCTION_INFO_V1(_ltxtq_exec);
      24           4 : PG_FUNCTION_INFO_V1(_ltxtq_rexec);
      25             : 
      26           6 : PG_FUNCTION_INFO_V1(_ltree_extract_isparent);
      27           6 : PG_FUNCTION_INFO_V1(_ltree_extract_risparent);
      28           6 : PG_FUNCTION_INFO_V1(_ltq_extract_regex);
      29           6 : PG_FUNCTION_INFO_V1(_ltxtq_extract_exec);
      30             : 
      31           6 : 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       40646 : array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
      39             : {
      40       40646 :     int         num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
      41       40646 :     ltree      *item = (ltree *) ARR_DATA_PTR(la);
      42             : 
      43       40646 :     if (ARR_NDIM(la) > 1)
      44           0 :         ereport(ERROR,
      45             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
      46             :                  errmsg("array must be one-dimensional")));
      47       40646 :     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       40646 :     if (found)
      53          12 :         *found = NULL;
      54      183564 :     while (num > 0)
      55             :     {
      56      145014 :         if (DatumGetBool(DirectFunctionCall2(callback,
      57             :                                              PointerGetDatum(item), PointerGetDatum(param))))
      58             :         {
      59             : 
      60        2096 :             if (found)
      61           8 :                 *found = item;
      62        2096 :             return true;
      63             :         }
      64      142918 :         num--;
      65      142918 :         item = NEXTVAL(item);
      66             :     }
      67             : 
      68       38550 :     return false;
      69             : }
      70             : 
      71             : Datum
      72        6024 : _ltree_isparent(PG_FUNCTION_ARGS)
      73             : {
      74        6024 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
      75        6024 :     ltree      *query = PG_GETARG_LTREE_P(1);
      76        6024 :     bool        res = array_iterator(la, ltree_isparent, (void *) query, NULL);
      77             : 
      78        6024 :     PG_FREE_IF_COPY(la, 0);
      79        6024 :     PG_FREE_IF_COPY(query, 1);
      80        6024 :     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        4620 : _ltree_risparent(PG_FUNCTION_ARGS)
      94             : {
      95        4620 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
      96        4620 :     ltree      *query = PG_GETARG_LTREE_P(1);
      97        4620 :     bool        res = array_iterator(la, ltree_risparent, (void *) query, NULL);
      98             : 
      99        4620 :     PG_FREE_IF_COPY(la, 0);
     100        4620 :     PG_FREE_IF_COPY(query, 1);
     101        4620 :     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       19150 : _ltq_regex(PG_FUNCTION_ARGS)
     115             : {
     116       19150 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     117       19150 :     lquery     *query = PG_GETARG_LQUERY_P(1);
     118       19150 :     bool        res = array_iterator(la, ltq_regex, (void *) query, NULL);
     119             : 
     120       19150 :     PG_FREE_IF_COPY(la, 0);
     121       19150 :     PG_FREE_IF_COPY(query, 1);
     122       19150 :     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        3736 : _lt_q_regex(PG_FUNCTION_ARGS)
     136             : {
     137        3736 :     ArrayType  *_tree = PG_GETARG_ARRAYTYPE_P(0);
     138        3736 :     ArrayType  *_query = PG_GETARG_ARRAYTYPE_P(1);
     139        3736 :     lquery     *query = (lquery *) ARR_DATA_PTR(_query);
     140        3736 :     bool        res = false;
     141        3736 :     int         num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
     142             : 
     143        3736 :     if (ARR_NDIM(_query) > 1)
     144           0 :         ereport(ERROR,
     145             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
     146             :                  errmsg("array must be one-dimensional")));
     147        3736 :     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       11048 :     while (num > 0)
     153             :     {
     154        7404 :         if (array_iterator(_tree, ltq_regex, (void *) query, NULL))
     155             :         {
     156          92 :             res = true;
     157          92 :             break;
     158             :         }
     159        7312 :         num--;
     160        7312 :         query = (lquery *) NEXTVAL(query);
     161             :     }
     162             : 
     163        3736 :     PG_FREE_IF_COPY(_tree, 0);
     164        3736 :     PG_FREE_IF_COPY(_query, 1);
     165        3736 :     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        3436 : _ltxtq_exec(PG_FUNCTION_ARGS)
     180             : {
     181        3436 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     182        3436 :     ltxtquery  *query = PG_GETARG_LTXTQUERY_P(1);
     183        3436 :     bool        res = array_iterator(la, ltxtq_exec, (void *) query, NULL);
     184             : 
     185        3436 :     PG_FREE_IF_COPY(la, 0);
     186        3436 :     PG_FREE_IF_COPY(query, 1);
     187        3436 :     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           4 : _ltree_extract_isparent(PG_FUNCTION_ARGS)
     202             : {
     203           4 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     204           4 :     ltree      *query = PG_GETARG_LTREE_P(1);
     205             :     ltree      *found,
     206             :                *item;
     207             : 
     208           4 :     if (!array_iterator(la, ltree_isparent, (void *) query, &found))
     209             :     {
     210           2 :         PG_FREE_IF_COPY(la, 0);
     211           2 :         PG_FREE_IF_COPY(query, 1);
     212           2 :         PG_RETURN_NULL();
     213             :     }
     214             : 
     215           2 :     item = (ltree *) palloc0(VARSIZE(found));
     216           2 :     memcpy(item, found, VARSIZE(found));
     217             : 
     218           2 :     PG_FREE_IF_COPY(la, 0);
     219           2 :     PG_FREE_IF_COPY(query, 1);
     220           2 :     PG_RETURN_POINTER(item);
     221             : }
     222             : 
     223             : Datum
     224           4 : _ltree_extract_risparent(PG_FUNCTION_ARGS)
     225             : {
     226           4 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     227           4 :     ltree      *query = PG_GETARG_LTREE_P(1);
     228             :     ltree      *found,
     229             :                *item;
     230             : 
     231           4 :     if (!array_iterator(la, ltree_risparent, (void *) query, &found))
     232             :     {
     233           2 :         PG_FREE_IF_COPY(la, 0);
     234           2 :         PG_FREE_IF_COPY(query, 1);
     235           2 :         PG_RETURN_NULL();
     236             :     }
     237             : 
     238           2 :     item = (ltree *) palloc0(VARSIZE(found));
     239           2 :     memcpy(item, found, VARSIZE(found));
     240             : 
     241           2 :     PG_FREE_IF_COPY(la, 0);
     242           2 :     PG_FREE_IF_COPY(query, 1);
     243           2 :     PG_RETURN_POINTER(item);
     244             : }
     245             : 
     246             : Datum
     247           2 : _ltq_extract_regex(PG_FUNCTION_ARGS)
     248             : {
     249           2 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     250           2 :     lquery     *query = PG_GETARG_LQUERY_P(1);
     251             :     ltree      *found,
     252             :                *item;
     253             : 
     254           2 :     if (!array_iterator(la, ltq_regex, (void *) 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           2 :     item = (ltree *) palloc0(VARSIZE(found));
     262           2 :     memcpy(item, found, VARSIZE(found));
     263             : 
     264           2 :     PG_FREE_IF_COPY(la, 0);
     265           2 :     PG_FREE_IF_COPY(query, 1);
     266           2 :     PG_RETURN_POINTER(item);
     267             : }
     268             : 
     269             : Datum
     270           2 : _ltxtq_extract_exec(PG_FUNCTION_ARGS)
     271             : {
     272           2 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     273           2 :     ltxtquery  *query = PG_GETARG_LTXTQUERY_P(1);
     274             :     ltree      *found,
     275             :                *item;
     276             : 
     277           2 :     if (!array_iterator(la, ltxtq_exec, (void *) 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           2 :     item = (ltree *) palloc0(VARSIZE(found));
     285           2 :     memcpy(item, found, VARSIZE(found));
     286             : 
     287           2 :     PG_FREE_IF_COPY(la, 0);
     288           2 :     PG_FREE_IF_COPY(query, 1);
     289           2 :     PG_RETURN_POINTER(item);
     290             : }
     291             : 
     292             : Datum
     293          16 : _lca(PG_FUNCTION_ARGS)
     294             : {
     295          16 :     ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
     296          16 :     int         num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
     297          16 :     ltree      *item = (ltree *) ARR_DATA_PTR(la);
     298             :     ltree     **a,
     299             :                *res;
     300             : 
     301          16 :     if (ARR_NDIM(la) > 1)
     302           0 :         ereport(ERROR,
     303             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
     304             :                  errmsg("array must be one-dimensional")));
     305          16 :     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          16 :     a = (ltree **) palloc(sizeof(ltree *) * num);
     311          40 :     while (num > 0)
     312             :     {
     313          24 :         num--;
     314          24 :         a[num] = item;
     315          24 :         item = NEXTVAL(item);
     316             :     }
     317          16 :     res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
     318          16 :     pfree(a);
     319             : 
     320          16 :     PG_FREE_IF_COPY(la, 0);
     321             : 
     322          16 :     if (res)
     323          12 :         PG_RETURN_POINTER(res);
     324             :     else
     325           4 :         PG_RETURN_NULL();
     326             : }

Generated by: LCOV version 1.14