LCOV - code coverage report
Current view: top level - src/backend/utils/adt - jsonb_op.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 110 137 80.3 %
Date: 2019-06-19 16:07:09 Functions: 11 14 78.6 %
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-2019, 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        9002 : jsonb_exists(PG_FUNCTION_ARGS)
      23             : {
      24        9002 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
      25        9002 :     text       *key = PG_GETARG_TEXT_PP(1);
      26             :     JsonbValue  kval;
      27        9002 :     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        9002 :     kval.type = jbvString;
      36        9002 :     kval.val.string.val = VARDATA_ANY(key);
      37        9002 :     kval.val.string.len = VARSIZE_ANY_EXHDR(key);
      38             : 
      39        9002 :     v = findJsonbValueFromContainer(&jb->root,
      40             :                                     JB_FOBJECT | JB_FARRAY,
      41             :                                     &kval);
      42             : 
      43        9002 :     PG_RETURN_BOOL(v != NULL);
      44             : }
      45             : 
      46             : Datum
      47        5436 : jsonb_exists_any(PG_FUNCTION_ARGS)
      48             : {
      49        5436 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
      50        5436 :     ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
      51             :     int         i;
      52             :     Datum      *key_datums;
      53             :     bool       *key_nulls;
      54             :     int         elem_count;
      55             : 
      56        5436 :     deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
      57             :                       &elem_count);
      58             : 
      59       12004 :     for (i = 0; i < elem_count; i++)
      60             :     {
      61             :         JsonbValue  strVal;
      62             : 
      63        9288 :         if (key_nulls[i])
      64           0 :             continue;
      65             : 
      66        9288 :         strVal.type = jbvString;
      67        9288 :         strVal.val.string.val = VARDATA(key_datums[i]);
      68        9288 :         strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
      69             : 
      70        9288 :         if (findJsonbValueFromContainer(&jb->root,
      71             :                                         JB_FOBJECT | JB_FARRAY,
      72             :                                         &strVal) != NULL)
      73        2720 :             PG_RETURN_BOOL(true);
      74             :     }
      75             : 
      76        2716 :     PG_RETURN_BOOL(false);
      77             : }
      78             : 
      79             : Datum
      80        4260 : jsonb_exists_all(PG_FUNCTION_ARGS)
      81             : {
      82        4260 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
      83        4260 :     ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
      84             :     int         i;
      85             :     Datum      *key_datums;
      86             :     bool       *key_nulls;
      87             :     int         elem_count;
      88             : 
      89        4260 :     deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
      90             :                       &elem_count);
      91             : 
      92        5592 :     for (i = 0; i < elem_count; i++)
      93             :     {
      94             :         JsonbValue  strVal;
      95             : 
      96        5228 :         if (key_nulls[i])
      97           0 :             continue;
      98             : 
      99        5228 :         strVal.type = jbvString;
     100        5228 :         strVal.val.string.val = VARDATA(key_datums[i]);
     101        5228 :         strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
     102             : 
     103        5228 :         if (findJsonbValueFromContainer(&jb->root,
     104             :                                         JB_FOBJECT | JB_FARRAY,
     105             :                                         &strVal) == NULL)
     106        3896 :             PG_RETURN_BOOL(false);
     107             :     }
     108             : 
     109         364 :     PG_RETURN_BOOL(true);
     110             : }
     111             : 
     112             : Datum
     113       28848 : jsonb_contains(PG_FUNCTION_ARGS)
     114             : {
     115       28848 :     Jsonb      *val = PG_GETARG_JSONB_P(0);
     116       28848 :     Jsonb      *tmpl = PG_GETARG_JSONB_P(1);
     117             : 
     118             :     JsonbIterator *it1,
     119             :                *it2;
     120             : 
     121       28848 :     if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
     122          20 :         PG_RETURN_BOOL(false);
     123             : 
     124       28828 :     it1 = JsonbIteratorInit(&val->root);
     125       28828 :     it2 = JsonbIteratorInit(&tmpl->root);
     126             : 
     127       28828 :     PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
     128             : }
     129             : 
     130             : Datum
     131          68 : jsonb_contained(PG_FUNCTION_ARGS)
     132             : {
     133             :     /* Commutator of "contains" */
     134          68 :     Jsonb      *tmpl = PG_GETARG_JSONB_P(0);
     135          68 :     Jsonb      *val = PG_GETARG_JSONB_P(1);
     136             : 
     137             :     JsonbIterator *it1,
     138             :                *it2;
     139             : 
     140          68 :     if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
     141           0 :         PG_RETURN_BOOL(false);
     142             : 
     143          68 :     it1 = JsonbIteratorInit(&val->root);
     144          68 :     it2 = JsonbIteratorInit(&tmpl->root);
     145             : 
     146          68 :     PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
     147             : }
     148             : 
     149             : Datum
     150           8 : jsonb_ne(PG_FUNCTION_ARGS)
     151             : {
     152           8 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     153           8 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     154             :     bool        res;
     155             : 
     156           8 :     res = (compareJsonbContainers(&jba->root, &jbb->root) != 0);
     157             : 
     158           8 :     PG_FREE_IF_COPY(jba, 0);
     159           8 :     PG_FREE_IF_COPY(jbb, 1);
     160           8 :     PG_RETURN_BOOL(res);
     161             : }
     162             : 
     163             : /*
     164             :  * B-Tree operator class operators, support function
     165             :  */
     166             : Datum
     167           0 : jsonb_lt(PG_FUNCTION_ARGS)
     168             : {
     169           0 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     170           0 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     171             :     bool        res;
     172             : 
     173           0 :     res = (compareJsonbContainers(&jba->root, &jbb->root) < 0);
     174             : 
     175           0 :     PG_FREE_IF_COPY(jba, 0);
     176           0 :     PG_FREE_IF_COPY(jbb, 1);
     177           0 :     PG_RETURN_BOOL(res);
     178             : }
     179             : 
     180             : Datum
     181        3628 : jsonb_gt(PG_FUNCTION_ARGS)
     182             : {
     183        3628 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     184        3628 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     185             :     bool        res;
     186             : 
     187        3628 :     res = (compareJsonbContainers(&jba->root, &jbb->root) > 0);
     188             : 
     189        3628 :     PG_FREE_IF_COPY(jba, 0);
     190        3628 :     PG_FREE_IF_COPY(jbb, 1);
     191        3628 :     PG_RETURN_BOOL(res);
     192             : }
     193             : 
     194             : Datum
     195           0 : jsonb_le(PG_FUNCTION_ARGS)
     196             : {
     197           0 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     198           0 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     199             :     bool        res;
     200             : 
     201           0 :     res = (compareJsonbContainers(&jba->root, &jbb->root) <= 0);
     202             : 
     203           0 :     PG_FREE_IF_COPY(jba, 0);
     204           0 :     PG_FREE_IF_COPY(jbb, 1);
     205           0 :     PG_RETURN_BOOL(res);
     206             : }
     207             : 
     208             : Datum
     209           0 : jsonb_ge(PG_FUNCTION_ARGS)
     210             : {
     211           0 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     212           0 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     213             :     bool        res;
     214             : 
     215           0 :     res = (compareJsonbContainers(&jba->root, &jbb->root) >= 0);
     216             : 
     217           0 :     PG_FREE_IF_COPY(jba, 0);
     218           0 :     PG_FREE_IF_COPY(jbb, 1);
     219           0 :     PG_RETURN_BOOL(res);
     220             : }
     221             : 
     222             : Datum
     223       16684 : jsonb_eq(PG_FUNCTION_ARGS)
     224             : {
     225       16684 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     226       16684 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     227             :     bool        res;
     228             : 
     229       16684 :     res = (compareJsonbContainers(&jba->root, &jbb->root) == 0);
     230             : 
     231       16684 :     PG_FREE_IF_COPY(jba, 0);
     232       16684 :     PG_FREE_IF_COPY(jbb, 1);
     233       16684 :     PG_RETURN_BOOL(res);
     234             : }
     235             : 
     236             : Datum
     237      250772 : jsonb_cmp(PG_FUNCTION_ARGS)
     238             : {
     239      250772 :     Jsonb      *jba = PG_GETARG_JSONB_P(0);
     240      250772 :     Jsonb      *jbb = PG_GETARG_JSONB_P(1);
     241             :     int         res;
     242             : 
     243      250772 :     res = compareJsonbContainers(&jba->root, &jbb->root);
     244             : 
     245      250772 :     PG_FREE_IF_COPY(jba, 0);
     246      250772 :     PG_FREE_IF_COPY(jbb, 1);
     247      250772 :     PG_RETURN_INT32(res);
     248             : }
     249             : 
     250             : /*
     251             :  * Hash operator class jsonb hashing function
     252             :  */
     253             : Datum
     254        8120 : jsonb_hash(PG_FUNCTION_ARGS)
     255             : {
     256        8120 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
     257             :     JsonbIterator *it;
     258             :     JsonbValue  v;
     259             :     JsonbIteratorToken r;
     260        8120 :     uint32      hash = 0;
     261             : 
     262        8120 :     if (JB_ROOT_COUNT(jb) == 0)
     263         944 :         PG_RETURN_INT32(0);
     264             : 
     265        7176 :     it = JsonbIteratorInit(&jb->root);
     266             : 
     267      105784 :     while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
     268             :     {
     269       91432 :         switch (r)
     270             :         {
     271             :                 /* Rotation is left to JsonbHashScalarValue() */
     272             :             case WJB_BEGIN_ARRAY:
     273          56 :                 hash ^= JB_FARRAY;
     274          56 :                 break;
     275             :             case WJB_BEGIN_OBJECT:
     276        7224 :                 hash ^= JB_FOBJECT;
     277        7224 :                 break;
     278             :             case WJB_KEY:
     279             :             case WJB_VALUE:
     280             :             case WJB_ELEM:
     281       76872 :                 JsonbHashScalarValue(&v, &hash);
     282       76872 :                 break;
     283             :             case WJB_END_ARRAY:
     284             :             case WJB_END_OBJECT:
     285        7280 :                 break;
     286             :             default:
     287           0 :                 elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
     288             :         }
     289             :     }
     290             : 
     291        7176 :     PG_FREE_IF_COPY(jb, 0);
     292        7176 :     PG_RETURN_INT32(hash);
     293             : }
     294             : 
     295             : Datum
     296          24 : jsonb_hash_extended(PG_FUNCTION_ARGS)
     297             : {
     298          24 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
     299          24 :     uint64      seed = PG_GETARG_INT64(1);
     300             :     JsonbIterator *it;
     301             :     JsonbValue  v;
     302             :     JsonbIteratorToken r;
     303          24 :     uint64      hash = 0;
     304             : 
     305          24 :     if (JB_ROOT_COUNT(jb) == 0)
     306           0 :         PG_RETURN_UINT64(seed);
     307             : 
     308          24 :     it = JsonbIteratorInit(&jb->root);
     309             : 
     310         320 :     while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
     311             :     {
     312         272 :         switch (r)
     313             :         {
     314             :                 /* Rotation is left to JsonbHashScalarValueExtended() */
     315             :             case WJB_BEGIN_ARRAY:
     316          16 :                 hash ^= ((uint64) JB_FARRAY) << 32 | JB_FARRAY;
     317          16 :                 break;
     318             :             case WJB_BEGIN_OBJECT:
     319          48 :                 hash ^= ((uint64) JB_FOBJECT) << 32 | JB_FOBJECT;
     320          48 :                 break;
     321             :             case WJB_KEY:
     322             :             case WJB_VALUE:
     323             :             case WJB_ELEM:
     324         144 :                 JsonbHashScalarValueExtended(&v, &hash, seed);
     325         144 :                 break;
     326             :             case WJB_END_ARRAY:
     327             :             case WJB_END_OBJECT:
     328          64 :                 break;
     329             :             default:
     330           0 :                 elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
     331             :         }
     332             :     }
     333             : 
     334          24 :     PG_FREE_IF_COPY(jb, 0);
     335          24 :     PG_RETURN_UINT64(hash);
     336             : }

Generated by: LCOV version 1.13