Clear padding of PgStat_HashKey when handling pgstats entries
[pgsql.git] / src / backend / utils / adt / jsonb_op.c
blobda0d13992ca0a0d523cd18cf39bbe4e3a4db209b
1 /*-------------------------------------------------------------------------
3 * jsonb_op.c
4 * Special operators for jsonb only, used by various index access methods
6 * Copyright (c) 2014-2024, PostgreSQL Global Development Group
9 * IDENTIFICATION
10 * src/backend/utils/adt/jsonb_op.c
12 *-------------------------------------------------------------------------
14 #include "postgres.h"
16 #include "catalog/pg_type.h"
17 #include "utils/fmgrprotos.h"
18 #include "utils/jsonb.h"
20 Datum
21 jsonb_exists(PG_FUNCTION_ARGS)
23 Jsonb *jb = PG_GETARG_JSONB_P(0);
24 text *key = PG_GETARG_TEXT_PP(1);
25 JsonbValue kval;
26 JsonbValue *v = NULL;
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,
40 &kval);
42 PG_RETURN_BOOL(v != NULL);
45 Datum
46 jsonb_exists_any(PG_FUNCTION_ARGS)
48 Jsonb *jb = PG_GETARG_JSONB_P(0);
49 ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
50 int i;
51 Datum *key_datums;
52 bool *key_nulls;
53 int elem_count;
55 deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
57 for (i = 0; i < elem_count; i++)
59 JsonbValue strVal;
61 if (key_nulls[i])
62 continue;
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,
71 &strVal) != NULL)
72 PG_RETURN_BOOL(true);
75 PG_RETURN_BOOL(false);
78 Datum
79 jsonb_exists_all(PG_FUNCTION_ARGS)
81 Jsonb *jb = PG_GETARG_JSONB_P(0);
82 ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
83 int i;
84 Datum *key_datums;
85 bool *key_nulls;
86 int elem_count;
88 deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
90 for (i = 0; i < elem_count; i++)
92 JsonbValue strVal;
94 if (key_nulls[i])
95 continue;
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,
104 &strVal) == NULL)
105 PG_RETURN_BOOL(false);
108 PG_RETURN_BOOL(true);
111 Datum
112 jsonb_contains(PG_FUNCTION_ARGS)
114 Jsonb *val = PG_GETARG_JSONB_P(0);
115 Jsonb *tmpl = PG_GETARG_JSONB_P(1);
117 JsonbIterator *it1,
118 *it2;
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));
129 Datum
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);
136 JsonbIterator *it1,
137 *it2;
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));
148 Datum
149 jsonb_ne(PG_FUNCTION_ARGS)
151 Jsonb *jba = PG_GETARG_JSONB_P(0);
152 Jsonb *jbb = PG_GETARG_JSONB_P(1);
153 bool res;
155 res = (compareJsonbContainers(&jba->root, &jbb->root) != 0);
157 PG_FREE_IF_COPY(jba, 0);
158 PG_FREE_IF_COPY(jbb, 1);
159 PG_RETURN_BOOL(res);
163 * B-Tree operator class operators, support function
165 Datum
166 jsonb_lt(PG_FUNCTION_ARGS)
168 Jsonb *jba = PG_GETARG_JSONB_P(0);
169 Jsonb *jbb = PG_GETARG_JSONB_P(1);
170 bool res;
172 res = (compareJsonbContainers(&jba->root, &jbb->root) < 0);
174 PG_FREE_IF_COPY(jba, 0);
175 PG_FREE_IF_COPY(jbb, 1);
176 PG_RETURN_BOOL(res);
179 Datum
180 jsonb_gt(PG_FUNCTION_ARGS)
182 Jsonb *jba = PG_GETARG_JSONB_P(0);
183 Jsonb *jbb = PG_GETARG_JSONB_P(1);
184 bool res;
186 res = (compareJsonbContainers(&jba->root, &jbb->root) > 0);
188 PG_FREE_IF_COPY(jba, 0);
189 PG_FREE_IF_COPY(jbb, 1);
190 PG_RETURN_BOOL(res);
193 Datum
194 jsonb_le(PG_FUNCTION_ARGS)
196 Jsonb *jba = PG_GETARG_JSONB_P(0);
197 Jsonb *jbb = PG_GETARG_JSONB_P(1);
198 bool res;
200 res = (compareJsonbContainers(&jba->root, &jbb->root) <= 0);
202 PG_FREE_IF_COPY(jba, 0);
203 PG_FREE_IF_COPY(jbb, 1);
204 PG_RETURN_BOOL(res);
207 Datum
208 jsonb_ge(PG_FUNCTION_ARGS)
210 Jsonb *jba = PG_GETARG_JSONB_P(0);
211 Jsonb *jbb = PG_GETARG_JSONB_P(1);
212 bool res;
214 res = (compareJsonbContainers(&jba->root, &jbb->root) >= 0);
216 PG_FREE_IF_COPY(jba, 0);
217 PG_FREE_IF_COPY(jbb, 1);
218 PG_RETURN_BOOL(res);
221 Datum
222 jsonb_eq(PG_FUNCTION_ARGS)
224 Jsonb *jba = PG_GETARG_JSONB_P(0);
225 Jsonb *jbb = PG_GETARG_JSONB_P(1);
226 bool res;
228 res = (compareJsonbContainers(&jba->root, &jbb->root) == 0);
230 PG_FREE_IF_COPY(jba, 0);
231 PG_FREE_IF_COPY(jbb, 1);
232 PG_RETURN_BOOL(res);
235 Datum
236 jsonb_cmp(PG_FUNCTION_ARGS)
238 Jsonb *jba = PG_GETARG_JSONB_P(0);
239 Jsonb *jbb = PG_GETARG_JSONB_P(1);
240 int res;
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
252 Datum
253 jsonb_hash(PG_FUNCTION_ARGS)
255 Jsonb *jb = PG_GETARG_JSONB_P(0);
256 JsonbIterator *it;
257 JsonbValue v;
258 JsonbIteratorToken r;
259 uint32 hash = 0;
261 if (JB_ROOT_COUNT(jb) == 0)
262 PG_RETURN_INT32(0);
264 it = JsonbIteratorInit(&jb->root);
266 while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
268 switch (r)
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:
280 JsonbHashScalarValue(&v, &hash);
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);
290 PG_FREE_IF_COPY(jb, 0);
291 PG_RETURN_INT32(hash);
294 Datum
295 jsonb_hash_extended(PG_FUNCTION_ARGS)
297 Jsonb *jb = PG_GETARG_JSONB_P(0);
298 uint64 seed = PG_GETARG_INT64(1);
299 JsonbIterator *it;
300 JsonbValue v;
301 JsonbIteratorToken r;
302 uint64 hash = 0;
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)
311 switch (r)
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:
323 JsonbHashScalarValueExtended(&v, &hash, seed);
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);
333 PG_FREE_IF_COPY(jb, 0);
334 PG_RETURN_UINT64(hash);