LCOV - code coverage report
Current view: top level - contrib/ltree - _ltree_op.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 85.9 % 156 134
Test Date: 2026-07-03 19:57:34 Functions: 83.9 % 31 26
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 54.6 % 108 59

             Branch data     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