1 /*-------------------------------------------------------------------------
4 * Special operators for jsonb only, used by various index access methods
6 * Copyright (c) 2014-2024, PostgreSQL Global Development Group
10 * src/backend/utils/adt/jsonb_op.c
12 *-------------------------------------------------------------------------
16 #include "catalog/pg_type.h"
17 #include "utils/fmgrprotos.h"
18 #include "utils/jsonb.h"
21 jsonb_exists(PG_FUNCTION_ARGS
)
23 Jsonb
*jb
= PG_GETARG_JSONB_P(0);
24 text
*key
= PG_GETARG_TEXT_PP(1);
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.
34 kval
.type
= jbvString
;
35 kval
.val
.string
.val
= VARDATA_ANY(key
);
36 kval
.val
.string
.len
= VARSIZE_ANY_EXHDR(key
);
38 v
= findJsonbValueFromContainer(&jb
->root
,
39 JB_FOBJECT
| JB_FARRAY
,
42 PG_RETURN_BOOL(v
!= NULL
);
46 jsonb_exists_any(PG_FUNCTION_ARGS
)
48 Jsonb
*jb
= PG_GETARG_JSONB_P(0);
49 ArrayType
*keys
= PG_GETARG_ARRAYTYPE_P(1);
55 deconstruct_array_builtin(keys
, TEXTOID
, &key_datums
, &key_nulls
, &elem_count
);
57 for (i
= 0; i
< elem_count
; i
++)
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
]);
69 if (findJsonbValueFromContainer(&jb
->root
,
70 JB_FOBJECT
| JB_FARRAY
,
75 PG_RETURN_BOOL(false);
79 jsonb_exists_all(PG_FUNCTION_ARGS
)
81 Jsonb
*jb
= PG_GETARG_JSONB_P(0);
82 ArrayType
*keys
= PG_GETARG_ARRAYTYPE_P(1);
88 deconstruct_array_builtin(keys
, TEXTOID
, &key_datums
, &key_nulls
, &elem_count
);
90 for (i
= 0; i
< elem_count
; i
++)
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
]);
102 if (findJsonbValueFromContainer(&jb
->root
,
103 JB_FOBJECT
| JB_FARRAY
,
105 PG_RETURN_BOOL(false);
108 PG_RETURN_BOOL(true);
112 jsonb_contains(PG_FUNCTION_ARGS
)
114 Jsonb
*val
= PG_GETARG_JSONB_P(0);
115 Jsonb
*tmpl
= PG_GETARG_JSONB_P(1);
120 if (JB_ROOT_IS_OBJECT(val
) != JB_ROOT_IS_OBJECT(tmpl
))
121 PG_RETURN_BOOL(false);
123 it1
= JsonbIteratorInit(&val
->root
);
124 it2
= JsonbIteratorInit(&tmpl
->root
);
126 PG_RETURN_BOOL(JsonbDeepContains(&it1
, &it2
));
130 jsonb_contained(PG_FUNCTION_ARGS
)
132 /* Commutator of "contains" */
133 Jsonb
*tmpl
= PG_GETARG_JSONB_P(0);
134 Jsonb
*val
= PG_GETARG_JSONB_P(1);
139 if (JB_ROOT_IS_OBJECT(val
) != JB_ROOT_IS_OBJECT(tmpl
))
140 PG_RETURN_BOOL(false);
142 it1
= JsonbIteratorInit(&val
->root
);
143 it2
= JsonbIteratorInit(&tmpl
->root
);
145 PG_RETURN_BOOL(JsonbDeepContains(&it1
, &it2
));
149 jsonb_ne(PG_FUNCTION_ARGS
)
151 Jsonb
*jba
= PG_GETARG_JSONB_P(0);
152 Jsonb
*jbb
= PG_GETARG_JSONB_P(1);
155 res
= (compareJsonbContainers(&jba
->root
, &jbb
->root
) != 0);
157 PG_FREE_IF_COPY(jba
, 0);
158 PG_FREE_IF_COPY(jbb
, 1);
163 * B-Tree operator class operators, support function
166 jsonb_lt(PG_FUNCTION_ARGS
)
168 Jsonb
*jba
= PG_GETARG_JSONB_P(0);
169 Jsonb
*jbb
= PG_GETARG_JSONB_P(1);
172 res
= (compareJsonbContainers(&jba
->root
, &jbb
->root
) < 0);
174 PG_FREE_IF_COPY(jba
, 0);
175 PG_FREE_IF_COPY(jbb
, 1);
180 jsonb_gt(PG_FUNCTION_ARGS
)
182 Jsonb
*jba
= PG_GETARG_JSONB_P(0);
183 Jsonb
*jbb
= PG_GETARG_JSONB_P(1);
186 res
= (compareJsonbContainers(&jba
->root
, &jbb
->root
) > 0);
188 PG_FREE_IF_COPY(jba
, 0);
189 PG_FREE_IF_COPY(jbb
, 1);
194 jsonb_le(PG_FUNCTION_ARGS
)
196 Jsonb
*jba
= PG_GETARG_JSONB_P(0);
197 Jsonb
*jbb
= PG_GETARG_JSONB_P(1);
200 res
= (compareJsonbContainers(&jba
->root
, &jbb
->root
) <= 0);
202 PG_FREE_IF_COPY(jba
, 0);
203 PG_FREE_IF_COPY(jbb
, 1);
208 jsonb_ge(PG_FUNCTION_ARGS
)
210 Jsonb
*jba
= PG_GETARG_JSONB_P(0);
211 Jsonb
*jbb
= PG_GETARG_JSONB_P(1);
214 res
= (compareJsonbContainers(&jba
->root
, &jbb
->root
) >= 0);
216 PG_FREE_IF_COPY(jba
, 0);
217 PG_FREE_IF_COPY(jbb
, 1);
222 jsonb_eq(PG_FUNCTION_ARGS
)
224 Jsonb
*jba
= PG_GETARG_JSONB_P(0);
225 Jsonb
*jbb
= PG_GETARG_JSONB_P(1);
228 res
= (compareJsonbContainers(&jba
->root
, &jbb
->root
) == 0);
230 PG_FREE_IF_COPY(jba
, 0);
231 PG_FREE_IF_COPY(jbb
, 1);
236 jsonb_cmp(PG_FUNCTION_ARGS
)
238 Jsonb
*jba
= PG_GETARG_JSONB_P(0);
239 Jsonb
*jbb
= PG_GETARG_JSONB_P(1);
242 res
= compareJsonbContainers(&jba
->root
, &jbb
->root
);
244 PG_FREE_IF_COPY(jba
, 0);
245 PG_FREE_IF_COPY(jbb
, 1);
246 PG_RETURN_INT32(res
);
250 * Hash operator class jsonb hashing function
253 jsonb_hash(PG_FUNCTION_ARGS
)
255 Jsonb
*jb
= PG_GETARG_JSONB_P(0);
258 JsonbIteratorToken r
;
261 if (JB_ROOT_COUNT(jb
) == 0)
264 it
= JsonbIteratorInit(&jb
->root
);
266 while ((r
= JsonbIteratorNext(&it
, &v
, false)) != WJB_DONE
)
270 /* Rotation is left to JsonbHashScalarValue() */
271 case WJB_BEGIN_ARRAY
:
274 case WJB_BEGIN_OBJECT
:
280 JsonbHashScalarValue(&v
, &hash
);
286 elog(ERROR
, "invalid JsonbIteratorNext rc: %d", (int) r
);
290 PG_FREE_IF_COPY(jb
, 0);
291 PG_RETURN_INT32(hash
);
295 jsonb_hash_extended(PG_FUNCTION_ARGS
)
297 Jsonb
*jb
= PG_GETARG_JSONB_P(0);
298 uint64 seed
= PG_GETARG_INT64(1);
301 JsonbIteratorToken r
;
304 if (JB_ROOT_COUNT(jb
) == 0)
305 PG_RETURN_UINT64(seed
);
307 it
= JsonbIteratorInit(&jb
->root
);
309 while ((r
= JsonbIteratorNext(&it
, &v
, false)) != WJB_DONE
)
313 /* Rotation is left to JsonbHashScalarValueExtended() */
314 case WJB_BEGIN_ARRAY
:
315 hash
^= ((uint64
) JB_FARRAY
) << 32 | JB_FARRAY
;
317 case WJB_BEGIN_OBJECT
:
318 hash
^= ((uint64
) JB_FOBJECT
) << 32 | JB_FOBJECT
;
323 JsonbHashScalarValueExtended(&v
, &hash
, seed
);
329 elog(ERROR
, "invalid JsonbIteratorNext rc: %d", (int) r
);
333 PG_FREE_IF_COPY(jb
, 0);
334 PG_RETURN_UINT64(hash
);