1 /*-------------------------------------------------------------------------
4 * Special operators for jsonb only, used by various index access methods
6 * Copyright (c) 2014-2019, PostgreSQL Global Development Group
10 * src/backend/utils/adt/jsonb_op.c
12 *-------------------------------------------------------------------------
16 #include "catalog/pg_type.h"
17 #include "miscadmin.h"
18 #include "utils/builtins.h"
19 #include "utils/jsonb.h"
22 jsonb_exists(PG_FUNCTION_ARGS)
24 Jsonb *jb = PG_GETARG_JSONB_P(0);
25 text *key = PG_GETARG_TEXT_PP(1);
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.
35 kval.type = jbvString;
36 kval.val.string.val = VARDATA_ANY(key);
37 kval.val.string.len = VARSIZE_ANY_EXHDR(key);
39 v = findJsonbValueFromContainer(&jb->root,
40 JB_FOBJECT | JB_FARRAY,
43 PG_RETURN_BOOL(v != NULL);
47 jsonb_exists_any(PG_FUNCTION_ARGS)
49 Jsonb *jb = PG_GETARG_JSONB_P(0);
50 ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
56 deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
59 for (i = 0; i < elem_count; i++)
66 strVal.type = jbvString;
67 strVal.val.string.val = VARDATA(key_datums[i]);
68 strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
70 if (findJsonbValueFromContainer(&jb->root,
71 JB_FOBJECT | JB_FARRAY,
76 PG_RETURN_BOOL(false);
80 jsonb_exists_all(PG_FUNCTION_ARGS)
82 Jsonb *jb = PG_GETARG_JSONB_P(0);
83 ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
89 deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
92 for (i = 0; i < elem_count; i++)
99 strVal.type = jbvString;
100 strVal.val.string.val = VARDATA(key_datums[i]);
101 strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
103 if (findJsonbValueFromContainer(&jb->root,
104 JB_FOBJECT | JB_FARRAY,
106 PG_RETURN_BOOL(false);
109 PG_RETURN_BOOL(true);
113 jsonb_contains(PG_FUNCTION_ARGS)
115 Jsonb *val = PG_GETARG_JSONB_P(0);
116 Jsonb *tmpl = PG_GETARG_JSONB_P(1);
121 if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
122 PG_RETURN_BOOL(false);
124 it1 = JsonbIteratorInit(&val->root);
125 it2 = JsonbIteratorInit(&tmpl->root);
127 PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
131 jsonb_contained(PG_FUNCTION_ARGS)
133 /* Commutator of "contains" */
134 Jsonb *tmpl = PG_GETARG_JSONB_P(0);
135 Jsonb *val = PG_GETARG_JSONB_P(1);
140 if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
141 PG_RETURN_BOOL(false);
143 it1 = JsonbIteratorInit(&val->root);
144 it2 = JsonbIteratorInit(&tmpl->root);
146 PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
150 jsonb_ne(PG_FUNCTION_ARGS)
152 Jsonb *jba = PG_GETARG_JSONB_P(0);
153 Jsonb *jbb = PG_GETARG_JSONB_P(1);
156 res = (compareJsonbContainers(&jba->root, &jbb->root) != 0);
158 PG_FREE_IF_COPY(jba, 0);
159 PG_FREE_IF_COPY(jbb, 1);
164 * B-Tree operator class operators, support function
167 jsonb_lt(PG_FUNCTION_ARGS)
169 Jsonb *jba = PG_GETARG_JSONB_P(0);
170 Jsonb *jbb = PG_GETARG_JSONB_P(1);
173 res = (compareJsonbContainers(&jba->root, &jbb->root) < 0);
175 PG_FREE_IF_COPY(jba, 0);
176 PG_FREE_IF_COPY(jbb, 1);
181 jsonb_gt(PG_FUNCTION_ARGS)
183 Jsonb *jba = PG_GETARG_JSONB_P(0);
184 Jsonb *jbb = PG_GETARG_JSONB_P(1);
187 res = (compareJsonbContainers(&jba->root, &jbb->root) > 0);
189 PG_FREE_IF_COPY(jba, 0);
190 PG_FREE_IF_COPY(jbb, 1);
195 jsonb_le(PG_FUNCTION_ARGS)
197 Jsonb *jba = PG_GETARG_JSONB_P(0);
198 Jsonb *jbb = PG_GETARG_JSONB_P(1);
201 res = (compareJsonbContainers(&jba->root, &jbb->root) <= 0);
203 PG_FREE_IF_COPY(jba, 0);
204 PG_FREE_IF_COPY(jbb, 1);
209 jsonb_ge(PG_FUNCTION_ARGS)
211 Jsonb *jba = PG_GETARG_JSONB_P(0);
212 Jsonb *jbb = PG_GETARG_JSONB_P(1);
215 res = (compareJsonbContainers(&jba->root, &jbb->root) >= 0);
217 PG_FREE_IF_COPY(jba, 0);
218 PG_FREE_IF_COPY(jbb, 1);
223 jsonb_eq(PG_FUNCTION_ARGS)
225 Jsonb *jba = PG_GETARG_JSONB_P(0);
226 Jsonb *jbb = PG_GETARG_JSONB_P(1);
229 res = (compareJsonbContainers(&jba->root, &jbb->root) == 0);
231 PG_FREE_IF_COPY(jba, 0);
232 PG_FREE_IF_COPY(jbb, 1);
237 jsonb_cmp(PG_FUNCTION_ARGS)
239 Jsonb *jba = PG_GETARG_JSONB_P(0);
240 Jsonb *jbb = PG_GETARG_JSONB_P(1);
243 res = compareJsonbContainers(&jba->root, &jbb->root);
245 PG_FREE_IF_COPY(jba, 0);
246 PG_FREE_IF_COPY(jbb, 1);
247 PG_RETURN_INT32(res);
251 * Hash operator class jsonb hashing function
254 jsonb_hash(PG_FUNCTION_ARGS)
256 Jsonb *jb = PG_GETARG_JSONB_P(0);
259 JsonbIteratorToken r;
262 if (JB_ROOT_COUNT(jb) == 0)
265 it = JsonbIteratorInit(&jb->root);
267 while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
271 /* Rotation is left to JsonbHashScalarValue() */
272 case WJB_BEGIN_ARRAY:
275 case WJB_BEGIN_OBJECT:
281 JsonbHashScalarValue(&v, &hash);
287 elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
291 PG_FREE_IF_COPY(jb, 0);
292 PG_RETURN_INT32(hash);
296 jsonb_hash_extended(PG_FUNCTION_ARGS)
298 Jsonb *jb = PG_GETARG_JSONB_P(0);
299 uint64 seed = PG_GETARG_INT64(1);
302 JsonbIteratorToken r;
305 if (JB_ROOT_COUNT(jb) == 0)
306 PG_RETURN_UINT64(seed);
308 it = JsonbIteratorInit(&jb->root);
310 while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
314 /* Rotation is left to JsonbHashScalarValueExtended() */
315 case WJB_BEGIN_ARRAY:
316 hash ^= ((uint64) JB_FARRAY) << 32 | JB_FARRAY;
318 case WJB_BEGIN_OBJECT:
319 hash ^= ((uint64) JB_FOBJECT) << 32 | JB_FOBJECT;
324 JsonbHashScalarValueExtended(&v, &hash, seed);
330 elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
334 PG_FREE_IF_COPY(jb, 0);
335 PG_RETURN_UINT64(hash);