LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - jsonb_op.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 80.3 % 147 118 3 17 9 3 58 2 55 17 58 2
Current Date: 2023-04-08 15:15:32 Functions: 78.6 % 14 11 3 9 1 1 3 9
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a