LCOV - code coverage report
Current view: top level - src/backend/utils/adt - jsonb_op.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 80.9 % 183 148
Test Date: 2026-01-26 10:56:24 Functions: 78.6 % 14 11
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 60.0 % 80 48

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * jsonb_op.c
       4                 :             :  *       Special operators for jsonb only, used by various index access methods
       5                 :             :  *
       6                 :             :  * Copyright (c) 2014-2026, PostgreSQL Global Development Group
       7                 :             :  *
       8                 :             :  *
       9                 :             :  * IDENTIFICATION
      10                 :             :  *        src/backend/utils/adt/jsonb_op.c
      11                 :             :  *
      12                 :             :  *-------------------------------------------------------------------------
      13                 :             :  */
      14                 :             : #include "postgres.h"
      15                 :             : 
      16                 :             : #include "catalog/pg_type.h"
      17                 :             : #include "utils/fmgrprotos.h"
      18                 :             : #include "utils/jsonb.h"
      19                 :             : 
      20                 :             : Datum
      21                 :        2286 : jsonb_exists(PG_FUNCTION_ARGS)
      22                 :             : {
      23                 :        2286 :         Jsonb      *jb = PG_GETARG_JSONB_P(0);
      24                 :        2286 :         text       *key = PG_GETARG_TEXT_PP(1);
      25                 :        2286 :         JsonbValue      kval;
      26                 :        2286 :         JsonbValue *v = NULL;
      27                 :             : 
      28                 :             :         /*
      29                 :             :          * We only match Object keys (which are naturally always Strings), or
      30                 :             :          * string elements in arrays.  In particular, we do not match non-string
      31                 :             :          * scalar elements.  Existence of a key/element is only considered at the
      32                 :             :          * top level.  No recursion occurs.
      33                 :             :          */
      34                 :        2286 :         kval.type = jbvString;
      35                 :        2286 :         kval.val.string.val = VARDATA_ANY(key);
      36                 :        2286 :         kval.val.string.len = VARSIZE_ANY_EXHDR(key);
      37                 :             : 
      38                 :        2286 :         v = findJsonbValueFromContainer(&jb->root,
      39                 :             :                                                                         JB_FOBJECT | JB_FARRAY,
      40                 :             :                                                                         &kval);
      41                 :             : 
      42                 :        4572 :         PG_RETURN_BOOL(v != NULL);
      43                 :        2286 : }
      44                 :             : 
      45                 :             : Datum
      46                 :        1359 : jsonb_exists_any(PG_FUNCTION_ARGS)
      47                 :             : {
      48                 :        1359 :         Jsonb      *jb = PG_GETARG_JSONB_P(0);
      49                 :        1359 :         ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
      50                 :        1359 :         int                     i;
      51                 :        1359 :         Datum      *key_datums;
      52                 :        1359 :         bool       *key_nulls;
      53                 :        1359 :         int                     elem_count;
      54                 :             : 
      55                 :        1359 :         deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
      56                 :             : 
      57         [ +  + ]:        3001 :         for (i = 0; i < elem_count; i++)
      58                 :             :         {
      59                 :        2322 :                 JsonbValue      strVal;
      60                 :             : 
      61         [ -  + ]:        2322 :                 if (key_nulls[i])
      62                 :           0 :                         continue;
      63                 :             : 
      64                 :        2322 :                 strVal.type = jbvString;
      65                 :             :                 /* We rely on the array elements not being toasted */
      66                 :        2322 :                 strVal.val.string.val = VARDATA_ANY(DatumGetPointer(key_datums[i]));
      67                 :        2322 :                 strVal.val.string.len = VARSIZE_ANY_EXHDR(DatumGetPointer(key_datums[i]));
      68                 :             : 
      69                 :        2322 :                 if (findJsonbValueFromContainer(&jb->root,
      70                 :             :                                                                                 JB_FOBJECT | JB_FARRAY,
      71         [ +  + ]:        2322 :                                                                                 &strVal) != NULL)
      72                 :         680 :                         PG_RETURN_BOOL(true);
      73      [ -  +  + ]:        2322 :         }
      74                 :             : 
      75                 :         679 :         PG_RETURN_BOOL(false);
      76                 :        1359 : }
      77                 :             : 
      78                 :             : Datum
      79                 :        1065 : jsonb_exists_all(PG_FUNCTION_ARGS)
      80                 :             : {
      81                 :        1065 :         Jsonb      *jb = PG_GETARG_JSONB_P(0);
      82                 :        1065 :         ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
      83                 :        1065 :         int                     i;
      84                 :        1065 :         Datum      *key_datums;
      85                 :        1065 :         bool       *key_nulls;
      86                 :        1065 :         int                     elem_count;
      87                 :             : 
      88                 :        1065 :         deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
      89                 :             : 
      90         [ +  + ]:        1398 :         for (i = 0; i < elem_count; i++)
      91                 :             :         {
      92                 :        1307 :                 JsonbValue      strVal;
      93                 :             : 
      94         [ -  + ]:        1307 :                 if (key_nulls[i])
      95                 :           0 :                         continue;
      96                 :             : 
      97                 :        1307 :                 strVal.type = jbvString;
      98                 :             :                 /* We rely on the array elements not being toasted */
      99                 :        1307 :                 strVal.val.string.val = VARDATA_ANY(DatumGetPointer(key_datums[i]));
     100                 :        1307 :                 strVal.val.string.len = VARSIZE_ANY_EXHDR(DatumGetPointer(key_datums[i]));
     101                 :             : 
     102                 :        1307 :                 if (findJsonbValueFromContainer(&jb->root,
     103                 :             :                                                                                 JB_FOBJECT | JB_FARRAY,
     104         [ +  + ]:        1307 :                                                                                 &strVal) == NULL)
     105                 :         974 :                         PG_RETURN_BOOL(false);
     106      [ -  +  + ]:        1307 :         }
     107                 :             : 
     108                 :          91 :         PG_RETURN_BOOL(true);
     109                 :        1065 : }
     110                 :             : 
     111                 :             : Datum
     112                 :        7212 : jsonb_contains(PG_FUNCTION_ARGS)
     113                 :             : {
     114                 :        7212 :         Jsonb      *val = PG_GETARG_JSONB_P(0);
     115                 :        7212 :         Jsonb      *tmpl = PG_GETARG_JSONB_P(1);
     116                 :             : 
     117                 :        7212 :         JsonbIterator *it1,
     118                 :             :                            *it2;
     119                 :             : 
     120         [ +  + ]:        7212 :         if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
     121                 :           5 :                 PG_RETURN_BOOL(false);
     122                 :             : 
     123                 :        7207 :         it1 = JsonbIteratorInit(&val->root);
     124                 :        7207 :         it2 = JsonbIteratorInit(&tmpl->root);
     125                 :             : 
     126                 :        7207 :         PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
     127                 :        7212 : }
     128                 :             : 
     129                 :             : Datum
     130                 :          17 : jsonb_contained(PG_FUNCTION_ARGS)
     131                 :             : {
     132                 :             :         /* Commutator of "contains" */
     133                 :          17 :         Jsonb      *tmpl = PG_GETARG_JSONB_P(0);
     134                 :          17 :         Jsonb      *val = PG_GETARG_JSONB_P(1);
     135                 :             : 
     136                 :          17 :         JsonbIterator *it1,
     137                 :             :                            *it2;
     138                 :             : 
     139         [ -  + ]:          17 :         if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
     140                 :           0 :                 PG_RETURN_BOOL(false);
     141                 :             : 
     142                 :          17 :         it1 = JsonbIteratorInit(&val->root);
     143                 :          17 :         it2 = JsonbIteratorInit(&tmpl->root);
     144                 :             : 
     145                 :          17 :         PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
     146                 :          17 : }
     147                 :             : 
     148                 :             : Datum
     149                 :           2 : jsonb_ne(PG_FUNCTION_ARGS)
     150                 :             : {
     151                 :           2 :         Jsonb      *jba = PG_GETARG_JSONB_P(0);
     152                 :           2 :         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     153                 :           2 :         bool            res;
     154                 :             : 
     155                 :           2 :         res = (compareJsonbContainers(&jba->root, &jbb->root) != 0);
     156                 :             : 
     157         [ +  - ]:           2 :         PG_FREE_IF_COPY(jba, 0);
     158         [ +  - ]:           2 :         PG_FREE_IF_COPY(jbb, 1);
     159                 :           4 :         PG_RETURN_BOOL(res);
     160                 :           2 : }
     161                 :             : 
     162                 :             : /*
     163                 :             :  * B-Tree operator class operators, support function
     164                 :             :  */
     165                 :             : Datum
     166                 :           0 : jsonb_lt(PG_FUNCTION_ARGS)
     167                 :             : {
     168                 :           0 :         Jsonb      *jba = PG_GETARG_JSONB_P(0);
     169                 :           0 :         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     170                 :           0 :         bool            res;
     171                 :             : 
     172                 :           0 :         res = (compareJsonbContainers(&jba->root, &jbb->root) < 0);
     173                 :             : 
     174         [ #  # ]:           0 :         PG_FREE_IF_COPY(jba, 0);
     175         [ #  # ]:           0 :         PG_FREE_IF_COPY(jbb, 1);
     176                 :           0 :         PG_RETURN_BOOL(res);
     177                 :           0 : }
     178                 :             : 
     179                 :             : Datum
     180                 :         926 : jsonb_gt(PG_FUNCTION_ARGS)
     181                 :             : {
     182                 :         926 :         Jsonb      *jba = PG_GETARG_JSONB_P(0);
     183                 :         926 :         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     184                 :         926 :         bool            res;
     185                 :             : 
     186                 :         926 :         res = (compareJsonbContainers(&jba->root, &jbb->root) > 0);
     187                 :             : 
     188         [ +  + ]:         926 :         PG_FREE_IF_COPY(jba, 0);
     189         [ +  - ]:         926 :         PG_FREE_IF_COPY(jbb, 1);
     190                 :        1852 :         PG_RETURN_BOOL(res);
     191                 :         926 : }
     192                 :             : 
     193                 :             : Datum
     194                 :           0 : jsonb_le(PG_FUNCTION_ARGS)
     195                 :             : {
     196                 :           0 :         Jsonb      *jba = PG_GETARG_JSONB_P(0);
     197                 :           0 :         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     198                 :           0 :         bool            res;
     199                 :             : 
     200                 :           0 :         res = (compareJsonbContainers(&jba->root, &jbb->root) <= 0);
     201                 :             : 
     202         [ #  # ]:           0 :         PG_FREE_IF_COPY(jba, 0);
     203         [ #  # ]:           0 :         PG_FREE_IF_COPY(jbb, 1);
     204                 :           0 :         PG_RETURN_BOOL(res);
     205                 :           0 : }
     206                 :             : 
     207                 :             : Datum
     208                 :           0 : jsonb_ge(PG_FUNCTION_ARGS)
     209                 :             : {
     210                 :           0 :         Jsonb      *jba = PG_GETARG_JSONB_P(0);
     211                 :           0 :         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     212                 :           0 :         bool            res;
     213                 :             : 
     214                 :           0 :         res = (compareJsonbContainers(&jba->root, &jbb->root) >= 0);
     215                 :             : 
     216         [ #  # ]:           0 :         PG_FREE_IF_COPY(jba, 0);
     217         [ #  # ]:           0 :         PG_FREE_IF_COPY(jbb, 1);
     218                 :           0 :         PG_RETURN_BOOL(res);
     219                 :           0 : }
     220                 :             : 
     221                 :             : Datum
     222                 :        4171 : jsonb_eq(PG_FUNCTION_ARGS)
     223                 :             : {
     224                 :        4171 :         Jsonb      *jba = PG_GETARG_JSONB_P(0);
     225                 :        4171 :         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     226                 :        4171 :         bool            res;
     227                 :             : 
     228                 :        4171 :         res = (compareJsonbContainers(&jba->root, &jbb->root) == 0);
     229                 :             : 
     230         [ +  + ]:        4171 :         PG_FREE_IF_COPY(jba, 0);
     231         [ +  + ]:        4171 :         PG_FREE_IF_COPY(jbb, 1);
     232                 :        8342 :         PG_RETURN_BOOL(res);
     233                 :        4171 : }
     234                 :             : 
     235                 :             : Datum
     236                 :       40522 : jsonb_cmp(PG_FUNCTION_ARGS)
     237                 :             : {
     238                 :       40522 :         Jsonb      *jba = PG_GETARG_JSONB_P(0);
     239                 :       40522 :         Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     240                 :       40522 :         int                     res;
     241                 :             : 
     242                 :       40522 :         res = compareJsonbContainers(&jba->root, &jbb->root);
     243                 :             : 
     244         [ +  + ]:       40522 :         PG_FREE_IF_COPY(jba, 0);
     245         [ +  + ]:       40522 :         PG_FREE_IF_COPY(jbb, 1);
     246                 :       81044 :         PG_RETURN_INT32(res);
     247                 :       40522 : }
     248                 :             : 
     249                 :             : /*
     250                 :             :  * Hash operator class jsonb hashing function
     251                 :             :  */
     252                 :             : Datum
     253                 :        2030 : jsonb_hash(PG_FUNCTION_ARGS)
     254                 :             : {
     255                 :        2030 :         Jsonb      *jb = PG_GETARG_JSONB_P(0);
     256                 :        2030 :         JsonbIterator *it;
     257                 :        2030 :         JsonbValue      v;
     258                 :        2030 :         JsonbIteratorToken r;
     259                 :        2030 :         uint32          hash = 0;
     260                 :             : 
     261         [ +  + ]:        2030 :         if (JB_ROOT_COUNT(jb) == 0)
     262                 :         236 :                 PG_RETURN_INT32(0);
     263                 :             : 
     264                 :        1794 :         it = JsonbIteratorInit(&jb->root);
     265                 :             : 
     266         [ +  + ]:       24652 :         while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
     267                 :             :         {
     268   [ +  +  -  +  :       22858 :                 switch (r)
                      + ]
     269                 :             :                 {
     270                 :             :                                 /* Rotation is left to JsonbHashScalarValue() */
     271                 :             :                         case WJB_BEGIN_ARRAY:
     272                 :          14 :                                 hash ^= JB_FARRAY;
     273                 :          14 :                                 break;
     274                 :             :                         case WJB_BEGIN_OBJECT:
     275                 :        1806 :                                 hash ^= JB_FOBJECT;
     276                 :        1806 :                                 break;
     277                 :             :                         case WJB_KEY:
     278                 :             :                         case WJB_VALUE:
     279                 :             :                         case WJB_ELEM:
     280                 :       19218 :                                 JsonbHashScalarValue(&v, &hash);
     281                 :       19218 :                                 break;
     282                 :             :                         case WJB_END_ARRAY:
     283                 :             :                         case WJB_END_OBJECT:
     284                 :        1820 :                                 break;
     285                 :             :                         default:
     286   [ #  #  #  # ]:           0 :                                 elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
     287                 :           0 :                 }
     288                 :             :         }
     289                 :             : 
     290         [ +  + ]:        1794 :         PG_FREE_IF_COPY(jb, 0);
     291                 :        1794 :         PG_RETURN_INT32(hash);
     292                 :        2030 : }
     293                 :             : 
     294                 :             : Datum
     295                 :           6 : jsonb_hash_extended(PG_FUNCTION_ARGS)
     296                 :             : {
     297                 :           6 :         Jsonb      *jb = PG_GETARG_JSONB_P(0);
     298                 :           6 :         uint64          seed = PG_GETARG_INT64(1);
     299                 :           6 :         JsonbIterator *it;
     300                 :           6 :         JsonbValue      v;
     301                 :           6 :         JsonbIteratorToken r;
     302                 :           6 :         uint64          hash = 0;
     303                 :             : 
     304         [ +  - ]:           6 :         if (JB_ROOT_COUNT(jb) == 0)
     305                 :           0 :                 PG_RETURN_UINT64(seed);
     306                 :             : 
     307                 :           6 :         it = JsonbIteratorInit(&jb->root);
     308                 :             : 
     309         [ +  + ]:          74 :         while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
     310                 :             :         {
     311   [ +  +  -  +  :          68 :                 switch (r)
                      + ]
     312                 :             :                 {
     313                 :             :                                 /* Rotation is left to JsonbHashScalarValueExtended() */
     314                 :             :                         case WJB_BEGIN_ARRAY:
     315                 :           4 :                                 hash ^= ((uint64) JB_FARRAY) << 32 | JB_FARRAY;
     316                 :           4 :                                 break;
     317                 :             :                         case WJB_BEGIN_OBJECT:
     318                 :          12 :                                 hash ^= ((uint64) JB_FOBJECT) << 32 | JB_FOBJECT;
     319                 :          12 :                                 break;
     320                 :             :                         case WJB_KEY:
     321                 :             :                         case WJB_VALUE:
     322                 :             :                         case WJB_ELEM:
     323                 :          36 :                                 JsonbHashScalarValueExtended(&v, &hash, seed);
     324                 :          36 :                                 break;
     325                 :             :                         case WJB_END_ARRAY:
     326                 :             :                         case WJB_END_OBJECT:
     327                 :          16 :                                 break;
     328                 :             :                         default:
     329   [ #  #  #  # ]:           0 :                                 elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
     330                 :           0 :                 }
     331                 :             :         }
     332                 :             : 
     333         [ +  - ]:           6 :         PG_FREE_IF_COPY(jb, 0);
     334                 :           6 :         PG_RETURN_UINT64(hash);
     335                 :           6 : }
        

Generated by: LCOV version 2.3.2-1