LCOV - code coverage report
Current view: top level - src/backend/utils/adt - jsonb_op.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 80.3 % 147 118
Test Date: 2026-07-22 12:15:41 Functions: 78.6 % 14 11
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 62.9 % 70 44

             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                 :        9159 : jsonb_exists(PG_FUNCTION_ARGS)
      22                 :             : {
      23                 :        9159 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
      24                 :        9159 :     text       *key = PG_GETARG_TEXT_PP(1);
      25                 :             :     JsonbValue  kval;
      26                 :        9159 :     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                 :        9159 :     kval.type = jbvString;
      35                 :        9159 :     kval.val.string.val = VARDATA_ANY(key);
      36                 :        9159 :     kval.val.string.len = VARSIZE_ANY_EXHDR(key);
      37                 :             : 
      38                 :        9159 :     v = findJsonbValueFromContainer(&jb->root,
      39                 :             :                                     JB_FOBJECT | JB_FARRAY,
      40                 :             :                                     &kval);
      41                 :             : 
      42                 :        9159 :     PG_RETURN_BOOL(v != NULL);
      43                 :             : }
      44                 :             : 
      45                 :             : Datum
      46                 :        5446 : jsonb_exists_any(PG_FUNCTION_ARGS)
      47                 :             : {
      48                 :        5446 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
      49                 :        5446 :     ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
      50                 :             :     int         i;
      51                 :             :     Datum      *key_datums;
      52                 :             :     bool       *key_nulls;
      53                 :             :     int         elem_count;
      54                 :             : 
      55                 :        5446 :     deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
      56                 :             : 
      57         [ +  + ]:       12020 :     for (i = 0; i < elem_count; i++)
      58                 :             :     {
      59                 :             :         JsonbValue  strVal;
      60                 :             : 
      61         [ -  + ]:        9300 :         if (key_nulls[i])
      62                 :           0 :             continue;
      63                 :             : 
      64                 :        9300 :         strVal.type = jbvString;
      65                 :             :         /* We rely on the array elements not being toasted */
      66                 :        9300 :         strVal.val.string.val = VARDATA_ANY(DatumGetPointer(key_datums[i]));
      67                 :        9300 :         strVal.val.string.len = VARSIZE_ANY_EXHDR(DatumGetPointer(key_datums[i]));
      68                 :             : 
      69         [ +  + ]:        9300 :         if (findJsonbValueFromContainer(&jb->root,
      70                 :             :                                         JB_FOBJECT | JB_FARRAY,
      71                 :             :                                         &strVal) != NULL)
      72                 :        2726 :             PG_RETURN_BOOL(true);
      73                 :             :     }
      74                 :             : 
      75                 :        2720 :     PG_RETURN_BOOL(false);
      76                 :             : }
      77                 :             : 
      78                 :             : Datum
      79                 :        4271 : jsonb_exists_all(PG_FUNCTION_ARGS)
      80                 :             : {
      81                 :        4271 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
      82                 :        4271 :     ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
      83                 :             :     int         i;
      84                 :             :     Datum      *key_datums;
      85                 :             :     bool       *key_nulls;
      86                 :             :     int         elem_count;
      87                 :             : 
      88                 :        4271 :     deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
      89                 :             : 
      90         [ +  + ]:        5616 :     for (i = 0; i < elem_count; i++)
      91                 :             :     {
      92                 :             :         JsonbValue  strVal;
      93                 :             : 
      94         [ -  + ]:        5245 :         if (key_nulls[i])
      95                 :           0 :             continue;
      96                 :             : 
      97                 :        5245 :         strVal.type = jbvString;
      98                 :             :         /* We rely on the array elements not being toasted */
      99                 :        5245 :         strVal.val.string.val = VARDATA_ANY(DatumGetPointer(key_datums[i]));
     100                 :        5245 :         strVal.val.string.len = VARSIZE_ANY_EXHDR(DatumGetPointer(key_datums[i]));
     101                 :             : 
     102         [ +  + ]:        5245 :         if (findJsonbValueFromContainer(&jb->root,
     103                 :             :                                         JB_FOBJECT | JB_FARRAY,
     104                 :             :                                         &strVal) == NULL)
     105                 :        3900 :             PG_RETURN_BOOL(false);
     106                 :             :     }
     107                 :             : 
     108                 :         371 :     PG_RETURN_BOOL(true);
     109                 :             : }
     110                 :             : 
     111                 :             : Datum
     112                 :       28889 : jsonb_contains(PG_FUNCTION_ARGS)
     113                 :             : {
     114                 :       28889 :     Jsonb      *val = PG_GETARG_JSONB_P(0);
     115                 :       28889 :     Jsonb      *tmpl = PG_GETARG_JSONB_P(1);
     116                 :             : 
     117                 :             :     JsonbIterator *it1,
     118                 :             :                *it2;
     119                 :             : 
     120         [ +  + ]:       28889 :     if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
     121                 :          20 :         PG_RETURN_BOOL(false);
     122                 :             : 
     123                 :       28869 :     it1 = JsonbIteratorInit(&val->root);
     124                 :       28869 :     it2 = JsonbIteratorInit(&tmpl->root);
     125                 :             : 
     126                 :       28869 :     PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
     127                 :             : }
     128                 :             : 
     129                 :             : Datum
     130                 :          85 : jsonb_contained(PG_FUNCTION_ARGS)
     131                 :             : {
     132                 :             :     /* Commutator of "contains" */
     133                 :          85 :     Jsonb      *tmpl = PG_GETARG_JSONB_P(0);
     134                 :          85 :     Jsonb      *val = PG_GETARG_JSONB_P(1);
     135                 :             : 
     136                 :             :     JsonbIterator *it1,
     137                 :             :                *it2;
     138                 :             : 
     139         [ -  + ]:          85 :     if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
     140                 :           0 :         PG_RETURN_BOOL(false);
     141                 :             : 
     142                 :          85 :     it1 = JsonbIteratorInit(&val->root);
     143                 :          85 :     it2 = JsonbIteratorInit(&tmpl->root);
     144                 :             : 
     145                 :          85 :     PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
     146                 :             : }
     147                 :             : 
     148                 :             : Datum
     149                 :          10 : jsonb_ne(PG_FUNCTION_ARGS)
     150                 :             : {
     151                 :          10 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     152                 :          10 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     153                 :             :     bool        res;
     154                 :             : 
     155                 :          10 :     res = (compareJsonbContainers(&jba->root, &jbb->root) != 0);
     156                 :             : 
     157         [ -  + ]:          10 :     PG_FREE_IF_COPY(jba, 0);
     158         [ -  + ]:          10 :     PG_FREE_IF_COPY(jbb, 1);
     159                 :          10 :     PG_RETURN_BOOL(res);
     160                 :             : }
     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                 :             :     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                 :             : }
     178                 :             : 
     179                 :             : Datum
     180                 :         464 : jsonb_gt(PG_FUNCTION_ARGS)
     181                 :             : {
     182                 :         464 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     183                 :         464 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     184                 :             :     bool        res;
     185                 :             : 
     186                 :         464 :     res = (compareJsonbContainers(&jba->root, &jbb->root) > 0);
     187                 :             : 
     188         [ +  + ]:         464 :     PG_FREE_IF_COPY(jba, 0);
     189         [ -  + ]:         464 :     PG_FREE_IF_COPY(jbb, 1);
     190                 :         464 :     PG_RETURN_BOOL(res);
     191                 :             : }
     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                 :             :     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                 :             : }
     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                 :             :     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                 :             : }
     220                 :             : 
     221                 :             : Datum
     222                 :       16746 : jsonb_eq(PG_FUNCTION_ARGS)
     223                 :             : {
     224                 :       16746 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     225                 :       16746 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     226                 :             :     bool        res;
     227                 :             : 
     228                 :       16746 :     res = (compareJsonbContainers(&jba->root, &jbb->root) == 0);
     229                 :             : 
     230         [ +  + ]:       16746 :     PG_FREE_IF_COPY(jba, 0);
     231         [ +  + ]:       16746 :     PG_FREE_IF_COPY(jbb, 1);
     232                 :       16746 :     PG_RETURN_BOOL(res);
     233                 :             : }
     234                 :             : 
     235                 :             : Datum
     236                 :      161958 : jsonb_cmp(PG_FUNCTION_ARGS)
     237                 :             : {
     238                 :      161958 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     239                 :      161958 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     240                 :             :     int         res;
     241                 :             : 
     242                 :      161958 :     res = compareJsonbContainers(&jba->root, &jbb->root);
     243                 :             : 
     244         [ +  + ]:      161958 :     PG_FREE_IF_COPY(jba, 0);
     245         [ +  + ]:      161958 :     PG_FREE_IF_COPY(jbb, 1);
     246                 :      161958 :     PG_RETURN_INT32(res);
     247                 :             : }
     248                 :             : 
     249                 :             : /*
     250                 :             :  * Hash operator class jsonb hashing function
     251                 :             :  */
     252                 :             : Datum
     253                 :        8120 : jsonb_hash(PG_FUNCTION_ARGS)
     254                 :             : {
     255                 :        8120 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
     256                 :             :     JsonbIterator *it;
     257                 :             :     JsonbValue  v;
     258                 :             :     JsonbIteratorToken r;
     259                 :        8120 :     uint32      hash = 0;
     260                 :             : 
     261         [ +  + ]:        8120 :     if (JB_ROOT_COUNT(jb) == 0)
     262                 :         944 :         PG_RETURN_INT32(0);
     263                 :             : 
     264                 :        7176 :     it = JsonbIteratorInit(&jb->root);
     265                 :             : 
     266         [ +  + ]:       98608 :     while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
     267                 :             :     {
     268   [ +  +  +  +  :       91432 :         switch (r)
                      - ]
     269                 :             :         {
     270                 :             :                 /* Rotation is left to JsonbHashScalarValue() */
     271                 :          56 :             case WJB_BEGIN_ARRAY:
     272                 :          56 :                 hash ^= JB_FARRAY;
     273                 :          56 :                 break;
     274                 :        7224 :             case WJB_BEGIN_OBJECT:
     275                 :        7224 :                 hash ^= JB_FOBJECT;
     276                 :        7224 :                 break;
     277                 :       76872 :             case WJB_KEY:
     278                 :             :             case WJB_VALUE:
     279                 :             :             case WJB_ELEM:
     280                 :       76872 :                 JsonbHashScalarValue(&v, &hash);
     281                 :       76872 :                 break;
     282                 :        7280 :             case WJB_END_ARRAY:
     283                 :             :             case WJB_END_OBJECT:
     284                 :        7280 :                 break;
     285                 :           0 :             default:
     286         [ #  # ]:           0 :                 elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
     287                 :             :         }
     288                 :             :     }
     289                 :             : 
     290         [ +  + ]:        7176 :     PG_FREE_IF_COPY(jb, 0);
     291                 :        7176 :     PG_RETURN_INT32(hash);
     292                 :             : }
     293                 :             : 
     294                 :             : Datum
     295                 :          24 : jsonb_hash_extended(PG_FUNCTION_ARGS)
     296                 :             : {
     297                 :          24 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
     298                 :          24 :     uint64      seed = PG_GETARG_INT64(1);
     299                 :             :     JsonbIterator *it;
     300                 :             :     JsonbValue  v;
     301                 :             :     JsonbIteratorToken r;
     302                 :          24 :     uint64      hash = 0;
     303                 :             : 
     304         [ -  + ]:          24 :     if (JB_ROOT_COUNT(jb) == 0)
     305                 :           0 :         PG_RETURN_UINT64(seed);
     306                 :             : 
     307                 :          24 :     it = JsonbIteratorInit(&jb->root);
     308                 :             : 
     309         [ +  + ]:         296 :     while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
     310                 :             :     {
     311   [ +  +  +  +  :         272 :         switch (r)
                      - ]
     312                 :             :         {
     313                 :             :                 /* Rotation is left to JsonbHashScalarValueExtended() */
     314                 :          16 :             case WJB_BEGIN_ARRAY:
     315                 :          16 :                 hash ^= ((uint64) JB_FARRAY) << 32 | JB_FARRAY;
     316                 :          16 :                 break;
     317                 :          48 :             case WJB_BEGIN_OBJECT:
     318                 :          48 :                 hash ^= ((uint64) JB_FOBJECT) << 32 | JB_FOBJECT;
     319                 :          48 :                 break;
     320                 :         144 :             case WJB_KEY:
     321                 :             :             case WJB_VALUE:
     322                 :             :             case WJB_ELEM:
     323                 :         144 :                 JsonbHashScalarValueExtended(&v, &hash, seed);
     324                 :         144 :                 break;
     325                 :          64 :             case WJB_END_ARRAY:
     326                 :             :             case WJB_END_OBJECT:
     327                 :          64 :                 break;
     328                 :           0 :             default:
     329         [ #  # ]:           0 :                 elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
     330                 :             :         }
     331                 :             :     }
     332                 :             : 
     333         [ -  + ]:          24 :     PG_FREE_IF_COPY(jb, 0);
     334                 :          24 :     PG_RETURN_UINT64(hash);
     335                 :             : }
        

Generated by: LCOV version 2.0-1