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

Generated by: LCOV version 1.13