LCOV - code coverage report
Current view: top level - src/backend/utils/adt - jsonb_op.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 80.3 % 147 118
Test Date: 2026-02-17 17:20:33 Functions: 78.6 % 14 11
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.0-1