PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
jsonb_op.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * jsonb_op.c
4  * Special operators for jsonb only, used by various index access methods
5  *
6  * Copyright (c) 2014-2024, 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
22 {
23  Jsonb *jb = PG_GETARG_JSONB_P(0);
25  JsonbValue kval;
26  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  kval.type = jbvString;
35  kval.val.string.val = VARDATA_ANY(key);
36  kval.val.string.len = VARSIZE_ANY_EXHDR(key);
37 
40  &kval);
41 
42  PG_RETURN_BOOL(v != NULL);
43 }
44 
45 Datum
47 {
48  Jsonb *jb = PG_GETARG_JSONB_P(0);
50  int i;
51  Datum *key_datums;
52  bool *key_nulls;
53  int elem_count;
54 
55  deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
56 
57  for (i = 0; i < elem_count; i++)
58  {
60 
61  if (key_nulls[i])
62  continue;
63 
64  strVal.type = jbvString;
65  /* We rely on the array elements not being toasted */
66  strVal.val.string.val = VARDATA_ANY(key_datums[i]);
67  strVal.val.string.len = VARSIZE_ANY_EXHDR(key_datums[i]);
68 
71  &strVal) != NULL)
72  PG_RETURN_BOOL(true);
73  }
74 
75  PG_RETURN_BOOL(false);
76 }
77 
78 Datum
80 {
81  Jsonb *jb = PG_GETARG_JSONB_P(0);
83  int i;
84  Datum *key_datums;
85  bool *key_nulls;
86  int elem_count;
87 
88  deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
89 
90  for (i = 0; i < elem_count; i++)
91  {
93 
94  if (key_nulls[i])
95  continue;
96 
97  strVal.type = jbvString;
98  /* We rely on the array elements not being toasted */
99  strVal.val.string.val = VARDATA_ANY(key_datums[i]);
100  strVal.val.string.len = VARSIZE_ANY_EXHDR(key_datums[i]);
101 
104  &strVal) == NULL)
105  PG_RETURN_BOOL(false);
106  }
107 
108  PG_RETURN_BOOL(true);
109 }
110 
111 Datum
113 {
115  Jsonb *tmpl = PG_GETARG_JSONB_P(1);
116 
117  JsonbIterator *it1,
118  *it2;
119 
121  PG_RETURN_BOOL(false);
122 
123  it1 = JsonbIteratorInit(&val->root);
124  it2 = JsonbIteratorInit(&tmpl->root);
125 
126  PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
127 }
128 
129 Datum
131 {
132  /* Commutator of "contains" */
133  Jsonb *tmpl = PG_GETARG_JSONB_P(0);
135 
136  JsonbIterator *it1,
137  *it2;
138 
140  PG_RETURN_BOOL(false);
141 
142  it1 = JsonbIteratorInit(&val->root);
143  it2 = JsonbIteratorInit(&tmpl->root);
144 
145  PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
146 }
147 
148 Datum
150 {
151  Jsonb *jba = PG_GETARG_JSONB_P(0);
152  Jsonb *jbb = PG_GETARG_JSONB_P(1);
153  bool res;
154 
155  res = (compareJsonbContainers(&jba->root, &jbb->root) != 0);
156 
157  PG_FREE_IF_COPY(jba, 0);
158  PG_FREE_IF_COPY(jbb, 1);
160 }
161 
162 /*
163  * B-Tree operator class operators, support function
164  */
165 Datum
167 {
168  Jsonb *jba = PG_GETARG_JSONB_P(0);
169  Jsonb *jbb = PG_GETARG_JSONB_P(1);
170  bool res;
171 
172  res = (compareJsonbContainers(&jba->root, &jbb->root) < 0);
173 
174  PG_FREE_IF_COPY(jba, 0);
175  PG_FREE_IF_COPY(jbb, 1);
177 }
178 
179 Datum
181 {
182  Jsonb *jba = PG_GETARG_JSONB_P(0);
183  Jsonb *jbb = PG_GETARG_JSONB_P(1);
184  bool res;
185 
186  res = (compareJsonbContainers(&jba->root, &jbb->root) > 0);
187 
188  PG_FREE_IF_COPY(jba, 0);
189  PG_FREE_IF_COPY(jbb, 1);
191 }
192 
193 Datum
195 {
196  Jsonb *jba = PG_GETARG_JSONB_P(0);
197  Jsonb *jbb = PG_GETARG_JSONB_P(1);
198  bool res;
199 
200  res = (compareJsonbContainers(&jba->root, &jbb->root) <= 0);
201 
202  PG_FREE_IF_COPY(jba, 0);
203  PG_FREE_IF_COPY(jbb, 1);
205 }
206 
207 Datum
209 {
210  Jsonb *jba = PG_GETARG_JSONB_P(0);
211  Jsonb *jbb = PG_GETARG_JSONB_P(1);
212  bool res;
213 
214  res = (compareJsonbContainers(&jba->root, &jbb->root) >= 0);
215 
216  PG_FREE_IF_COPY(jba, 0);
217  PG_FREE_IF_COPY(jbb, 1);
219 }
220 
221 Datum
223 {
224  Jsonb *jba = PG_GETARG_JSONB_P(0);
225  Jsonb *jbb = PG_GETARG_JSONB_P(1);
226  bool res;
227 
228  res = (compareJsonbContainers(&jba->root, &jbb->root) == 0);
229 
230  PG_FREE_IF_COPY(jba, 0);
231  PG_FREE_IF_COPY(jbb, 1);
233 }
234 
235 Datum
237 {
238  Jsonb *jba = PG_GETARG_JSONB_P(0);
239  Jsonb *jbb = PG_GETARG_JSONB_P(1);
240  int res;
241 
242  res = compareJsonbContainers(&jba->root, &jbb->root);
243 
244  PG_FREE_IF_COPY(jba, 0);
245  PG_FREE_IF_COPY(jbb, 1);
247 }
248 
249 /*
250  * Hash operator class jsonb hashing function
251  */
252 Datum
254 {
255  Jsonb *jb = PG_GETARG_JSONB_P(0);
256  JsonbIterator *it;
257  JsonbValue v;
259  uint32 hash = 0;
260 
261  if (JB_ROOT_COUNT(jb) == 0)
262  PG_RETURN_INT32(0);
263 
264  it = JsonbIteratorInit(&jb->root);
265 
266  while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
267  {
268  switch (r)
269  {
270  /* Rotation is left to JsonbHashScalarValue() */
271  case WJB_BEGIN_ARRAY:
272  hash ^= JB_FARRAY;
273  break;
274  case WJB_BEGIN_OBJECT:
275  hash ^= JB_FOBJECT;
276  break;
277  case WJB_KEY:
278  case WJB_VALUE:
279  case WJB_ELEM:
281  break;
282  case WJB_END_ARRAY:
283  case WJB_END_OBJECT:
284  break;
285  default:
286  elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
287  }
288  }
289 
290  PG_FREE_IF_COPY(jb, 0);
292 }
293 
294 Datum
296 {
297  Jsonb *jb = PG_GETARG_JSONB_P(0);
298  uint64 seed = PG_GETARG_INT64(1);
299  JsonbIterator *it;
300  JsonbValue v;
302  uint64 hash = 0;
303 
304  if (JB_ROOT_COUNT(jb) == 0)
305  PG_RETURN_UINT64(seed);
306 
307  it = JsonbIteratorInit(&jb->root);
308 
309  while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
310  {
311  switch (r)
312  {
313  /* Rotation is left to JsonbHashScalarValueExtended() */
314  case WJB_BEGIN_ARRAY:
315  hash ^= ((uint64) JB_FARRAY) << 32 | JB_FARRAY;
316  break;
317  case WJB_BEGIN_OBJECT:
318  hash ^= ((uint64) JB_FOBJECT) << 32 | JB_FOBJECT;
319  break;
320  case WJB_KEY:
321  case WJB_VALUE:
322  case WJB_ELEM:
324  break;
325  case WJB_END_ARRAY:
326  case WJB_END_OBJECT:
327  break;
328  default:
329  elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
330  }
331  }
332 
333  PG_FREE_IF_COPY(jb, 0);
335 }
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3697
unsigned int uint32
Definition: c.h:518
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:369
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
long val
Definition: informix.c:689
int i
Definition: isn.c:72
@ jbvString
Definition: jsonb.h:229
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:221
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:391
#define JB_FARRAY
Definition: jsonb.h:203
JsonbIteratorToken
Definition: jsonb.h:21
@ WJB_KEY
Definition: jsonb.h:23
@ WJB_DONE
Definition: jsonb.h:22
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_VALUE
Definition: jsonb.h:24
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_ELEM
Definition: jsonb.h:25
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:219
#define JB_FOBJECT
Definition: jsonb.h:202
Datum jsonb_le(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:194
Datum jsonb_exists_all(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:79
Datum jsonb_gt(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:180
Datum jsonb_hash_extended(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:295
Datum jsonb_exists_any(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:46
Datum jsonb_hash(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:253
Datum jsonb_contains(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:112
Datum jsonb_lt(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:166
Datum jsonb_contained(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:130
Datum jsonb_cmp(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:236
Datum jsonb_ge(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:208
Datum jsonb_ne(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:149
Datum jsonb_eq(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:222
Datum jsonb_exists(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:21
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:817
int compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
Definition: jsonb_util.c:191
void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
Definition: jsonb_util.c:1316
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:853
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:344
void JsonbHashScalarValueExtended(const JsonbValue *scalarVal, uint64 *hash, uint64 seed)
Definition: jsonb_util.c:1359
bool JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
Definition: jsonb_util.c:1062
uintptr_t Datum
Definition: postgres.h:64
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715
enum jbvType type
Definition: jsonb.h:255
char * val
Definition: jsonb.h:264
Definition: jsonb.h:213
JsonbContainer root
Definition: jsonb.h:215
Definition: c.h:692
#define strVal(v)
Definition: value.h:82
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317