PostgreSQL Source Code  git master
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-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
23 {
24  Jsonb *jb = PG_GETARG_JSONB_P(0);
26  JsonbValue kval;
27  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  kval.type = jbvString;
36  kval.val.string.val = VARDATA_ANY(key);
37  kval.val.string.len = VARSIZE_ANY_EXHDR(key);
38 
41  &kval);
42 
43  PG_RETURN_BOOL(v != NULL);
44 }
45 
46 Datum
48 {
49  Jsonb *jb = PG_GETARG_JSONB_P(0);
51  int i;
52  Datum *key_datums;
53  bool *key_nulls;
54  int elem_count;
55 
56  deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
57 
58  for (i = 0; i < elem_count; i++)
59  {
61 
62  if (key_nulls[i])
63  continue;
64 
65  strVal.type = jbvString;
66  /* We rely on the array elements not being toasted */
67  strVal.val.string.val = VARDATA_ANY(key_datums[i]);
68  strVal.val.string.len = VARSIZE_ANY_EXHDR(key_datums[i]);
69 
72  &strVal) != NULL)
73  PG_RETURN_BOOL(true);
74  }
75 
76  PG_RETURN_BOOL(false);
77 }
78 
79 Datum
81 {
82  Jsonb *jb = PG_GETARG_JSONB_P(0);
84  int i;
85  Datum *key_datums;
86  bool *key_nulls;
87  int elem_count;
88 
89  deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
90 
91  for (i = 0; i < elem_count; i++)
92  {
94 
95  if (key_nulls[i])
96  continue;
97 
98  strVal.type = jbvString;
99  /* We rely on the array elements not being toasted */
100  strVal.val.string.val = VARDATA_ANY(key_datums[i]);
101  strVal.val.string.len = VARSIZE_ANY_EXHDR(key_datums[i]);
102 
105  &strVal) == NULL)
106  PG_RETURN_BOOL(false);
107  }
108 
109  PG_RETURN_BOOL(true);
110 }
111 
112 Datum
114 {
116  Jsonb *tmpl = PG_GETARG_JSONB_P(1);
117 
118  JsonbIterator *it1,
119  *it2;
120 
122  PG_RETURN_BOOL(false);
123 
124  it1 = JsonbIteratorInit(&val->root);
125  it2 = JsonbIteratorInit(&tmpl->root);
126 
127  PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
128 }
129 
130 Datum
132 {
133  /* Commutator of "contains" */
134  Jsonb *tmpl = PG_GETARG_JSONB_P(0);
136 
137  JsonbIterator *it1,
138  *it2;
139 
141  PG_RETURN_BOOL(false);
142 
143  it1 = JsonbIteratorInit(&val->root);
144  it2 = JsonbIteratorInit(&tmpl->root);
145 
146  PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
147 }
148 
149 Datum
151 {
152  Jsonb *jba = PG_GETARG_JSONB_P(0);
153  Jsonb *jbb = PG_GETARG_JSONB_P(1);
154  bool res;
155 
156  res = (compareJsonbContainers(&jba->root, &jbb->root) != 0);
157 
158  PG_FREE_IF_COPY(jba, 0);
159  PG_FREE_IF_COPY(jbb, 1);
161 }
162 
163 /*
164  * B-Tree operator class operators, support function
165  */
166 Datum
168 {
169  Jsonb *jba = PG_GETARG_JSONB_P(0);
170  Jsonb *jbb = PG_GETARG_JSONB_P(1);
171  bool res;
172 
173  res = (compareJsonbContainers(&jba->root, &jbb->root) < 0);
174 
175  PG_FREE_IF_COPY(jba, 0);
176  PG_FREE_IF_COPY(jbb, 1);
178 }
179 
180 Datum
182 {
183  Jsonb *jba = PG_GETARG_JSONB_P(0);
184  Jsonb *jbb = PG_GETARG_JSONB_P(1);
185  bool res;
186 
187  res = (compareJsonbContainers(&jba->root, &jbb->root) > 0);
188 
189  PG_FREE_IF_COPY(jba, 0);
190  PG_FREE_IF_COPY(jbb, 1);
192 }
193 
194 Datum
196 {
197  Jsonb *jba = PG_GETARG_JSONB_P(0);
198  Jsonb *jbb = PG_GETARG_JSONB_P(1);
199  bool res;
200 
201  res = (compareJsonbContainers(&jba->root, &jbb->root) <= 0);
202 
203  PG_FREE_IF_COPY(jba, 0);
204  PG_FREE_IF_COPY(jbb, 1);
206 }
207 
208 Datum
210 {
211  Jsonb *jba = PG_GETARG_JSONB_P(0);
212  Jsonb *jbb = PG_GETARG_JSONB_P(1);
213  bool res;
214 
215  res = (compareJsonbContainers(&jba->root, &jbb->root) >= 0);
216 
217  PG_FREE_IF_COPY(jba, 0);
218  PG_FREE_IF_COPY(jbb, 1);
220 }
221 
222 Datum
224 {
225  Jsonb *jba = PG_GETARG_JSONB_P(0);
226  Jsonb *jbb = PG_GETARG_JSONB_P(1);
227  bool res;
228 
229  res = (compareJsonbContainers(&jba->root, &jbb->root) == 0);
230 
231  PG_FREE_IF_COPY(jba, 0);
232  PG_FREE_IF_COPY(jbb, 1);
234 }
235 
236 Datum
238 {
239  Jsonb *jba = PG_GETARG_JSONB_P(0);
240  Jsonb *jbb = PG_GETARG_JSONB_P(1);
241  int res;
242 
243  res = compareJsonbContainers(&jba->root, &jbb->root);
244 
245  PG_FREE_IF_COPY(jba, 0);
246  PG_FREE_IF_COPY(jbb, 1);
248 }
249 
250 /*
251  * Hash operator class jsonb hashing function
252  */
253 Datum
255 {
256  Jsonb *jb = PG_GETARG_JSONB_P(0);
257  JsonbIterator *it;
258  JsonbValue v;
260  uint32 hash = 0;
261 
262  if (JB_ROOT_COUNT(jb) == 0)
263  PG_RETURN_INT32(0);
264 
265  it = JsonbIteratorInit(&jb->root);
266 
267  while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
268  {
269  switch (r)
270  {
271  /* Rotation is left to JsonbHashScalarValue() */
272  case WJB_BEGIN_ARRAY:
273  hash ^= JB_FARRAY;
274  break;
275  case WJB_BEGIN_OBJECT:
276  hash ^= JB_FOBJECT;
277  break;
278  case WJB_KEY:
279  case WJB_VALUE:
280  case WJB_ELEM:
282  break;
283  case WJB_END_ARRAY:
284  case WJB_END_OBJECT:
285  break;
286  default:
287  elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
288  }
289  }
290 
291  PG_FREE_IF_COPY(jb, 0);
293 }
294 
295 Datum
297 {
298  Jsonb *jb = PG_GETARG_JSONB_P(0);
299  uint64 seed = PG_GETARG_INT64(1);
300  JsonbIterator *it;
301  JsonbValue v;
303  uint64 hash = 0;
304 
305  if (JB_ROOT_COUNT(jb) == 0)
306  PG_RETURN_UINT64(seed);
307 
308  it = JsonbIteratorInit(&jb->root);
309 
310  while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
311  {
312  switch (r)
313  {
314  /* Rotation is left to JsonbHashScalarValueExtended() */
315  case WJB_BEGIN_ARRAY:
316  hash ^= ((uint64) JB_FARRAY) << 32 | JB_FARRAY;
317  break;
318  case WJB_BEGIN_OBJECT:
319  hash ^= ((uint64) JB_FOBJECT) << 32 | JB_FOBJECT;
320  break;
321  case WJB_KEY:
322  case WJB_VALUE:
323  case WJB_ELEM:
325  break;
326  case WJB_END_ARRAY:
327  case WJB_END_OBJECT:
328  break;
329  default:
330  elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
331  }
332  }
333 
334  PG_FREE_IF_COPY(jb, 0);
336 }
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3644
unsigned int uint32
Definition: c.h:495
#define ERROR
Definition: elog.h:39
#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:664
int i
Definition: isn.c:73
@ 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:195
Datum jsonb_exists_all(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:80
Datum jsonb_gt(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:181
Datum jsonb_hash_extended(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:296
Datum jsonb_exists_any(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:47
Datum jsonb_hash(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:254
Datum jsonb_contains(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:113
Datum jsonb_lt(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:167
Datum jsonb_contained(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:131
Datum jsonb_cmp(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:237
Datum jsonb_ge(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:209
Datum jsonb_ne(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:150
Datum jsonb_eq(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:223
Datum jsonb_exists(PG_FUNCTION_ARGS)
Definition: jsonb_op.c:22
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:819
int compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
Definition: jsonb_util.c:193
void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
Definition: jsonb_util.c:1318
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:855
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:346
void JsonbHashScalarValueExtended(const JsonbValue *scalarVal, uint64 *hash, uint64 seed)
Definition: jsonb_util.c:1361
bool JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
Definition: jsonb_util.c:1064
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:676
#define strVal(v)
Definition: value.h:82
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317