TLA Line data Source code
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
22 CBC 6859 : jsonb_exists(PG_FUNCTION_ARGS)
23 : {
24 6859 : Jsonb *jb = PG_GETARG_JSONB_P(0);
25 6859 : text *key = PG_GETARG_TEXT_PP(1);
26 : JsonbValue kval;
27 6859 : 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 6859 : kval.type = jbvString;
36 6859 : kval.val.string.val = VARDATA_ANY(key);
37 6859 : kval.val.string.len = VARSIZE_ANY_EXHDR(key);
38 :
39 6859 : v = findJsonbValueFromContainer(&jb->root,
40 : JB_FOBJECT | JB_FARRAY,
41 : &kval);
42 :
43 6859 : PG_RETURN_BOOL(v != NULL);
44 : }
45 :
46 : Datum
47 4077 : jsonb_exists_any(PG_FUNCTION_ARGS)
48 : {
49 4077 : Jsonb *jb = PG_GETARG_JSONB_P(0);
50 4077 : ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
51 : int i;
52 : Datum *key_datums;
53 : bool *key_nulls;
54 : int elem_count;
55 :
56 GNC 4077 : deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
57 ECB :
58 GIC 9003 : for (i = 0; i < elem_count; i++)
59 : {
60 : JsonbValue strVal;
61 ECB :
62 GBC 6966 : if (key_nulls[i])
63 UIC 0 : continue;
64 ECB :
65 GIC 6966 : strVal.type = jbvString;
66 ECB : /* We rely on the array elements not being toasted */
67 CBC 6966 : strVal.val.string.val = VARDATA_ANY(key_datums[i]);
68 GIC 6966 : strVal.val.string.len = VARSIZE_ANY_EXHDR(key_datums[i]);
69 ECB :
70 GIC 6966 : if (findJsonbValueFromContainer(&jb->root,
71 : JB_FOBJECT | JB_FARRAY,
72 ECB : &strVal) != NULL)
73 GIC 2040 : PG_RETURN_BOOL(true);
74 : }
75 ECB :
76 GIC 2037 : PG_RETURN_BOOL(false);
77 : }
78 :
79 ECB : Datum
80 GIC 3195 : jsonb_exists_all(PG_FUNCTION_ARGS)
81 ECB : {
82 CBC 3195 : Jsonb *jb = PG_GETARG_JSONB_P(0);
83 GIC 3195 : ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
84 : int i;
85 : Datum *key_datums;
86 : bool *key_nulls;
87 : int elem_count;
88 ECB :
89 GNC 3195 : deconstruct_array_builtin(keys, TEXTOID, &key_datums, &key_nulls, &elem_count);
90 :
91 GIC 4194 : for (i = 0; i < elem_count; i++)
92 : {
93 ECB : JsonbValue strVal;
94 EUB :
95 GIC 3921 : if (key_nulls[i])
96 LBC 0 : continue;
97 :
98 CBC 3921 : strVal.type = jbvString;
99 ECB : /* We rely on the array elements not being toasted */
100 GIC 3921 : strVal.val.string.val = VARDATA_ANY(key_datums[i]);
101 CBC 3921 : strVal.val.string.len = VARSIZE_ANY_EXHDR(key_datums[i]);
102 :
103 GIC 3921 : if (findJsonbValueFromContainer(&jb->root,
104 ECB : JB_FOBJECT | JB_FARRAY,
105 : &strVal) == NULL)
106 GIC 2922 : PG_RETURN_BOOL(false);
107 ECB : }
108 :
109 GIC 273 : PG_RETURN_BOOL(true);
110 : }
111 ECB :
112 : Datum
113 CBC 21636 : jsonb_contains(PG_FUNCTION_ARGS)
114 ECB : {
115 GIC 21636 : Jsonb *val = PG_GETARG_JSONB_P(0);
116 21636 : Jsonb *tmpl = PG_GETARG_JSONB_P(1);
117 :
118 : JsonbIterator *it1,
119 ECB : *it2;
120 :
121 GIC 21636 : if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
122 CBC 15 : PG_RETURN_BOOL(false);
123 ECB :
124 GIC 21621 : it1 = JsonbIteratorInit(&val->root);
125 CBC 21621 : it2 = JsonbIteratorInit(&tmpl->root);
126 :
127 GIC 21621 : PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
128 : }
129 ECB :
130 : Datum
131 GIC 51 : jsonb_contained(PG_FUNCTION_ARGS)
132 ECB : {
133 : /* Commutator of "contains" */
134 GIC 51 : Jsonb *tmpl = PG_GETARG_JSONB_P(0);
135 51 : Jsonb *val = PG_GETARG_JSONB_P(1);
136 :
137 : JsonbIterator *it1,
138 ECB : *it2;
139 EUB :
140 GIC 51 : if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
141 LBC 0 : PG_RETURN_BOOL(false);
142 ECB :
143 GIC 51 : it1 = JsonbIteratorInit(&val->root);
144 CBC 51 : it2 = JsonbIteratorInit(&tmpl->root);
145 :
146 GIC 51 : PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
147 : }
148 ECB :
149 : Datum
150 CBC 6 : jsonb_ne(PG_FUNCTION_ARGS)
151 ECB : {
152 GIC 6 : Jsonb *jba = PG_GETARG_JSONB_P(0);
153 6 : Jsonb *jbb = PG_GETARG_JSONB_P(1);
154 ECB : bool res;
155 :
156 CBC 6 : res = (compareJsonbContainers(&jba->root, &jbb->root) != 0);
157 ECB :
158 CBC 6 : PG_FREE_IF_COPY(jba, 0);
159 GIC 6 : PG_FREE_IF_COPY(jbb, 1);
160 6 : PG_RETURN_BOOL(res);
161 : }
162 :
163 : /*
164 : * B-Tree operator class operators, support function
165 EUB : */
166 : Datum
167 UBC 0 : jsonb_lt(PG_FUNCTION_ARGS)
168 EUB : {
169 UIC 0 : Jsonb *jba = PG_GETARG_JSONB_P(0);
170 0 : Jsonb *jbb = PG_GETARG_JSONB_P(1);
171 EUB : bool res;
172 :
173 UBC 0 : res = (compareJsonbContainers(&jba->root, &jbb->root) < 0);
174 EUB :
175 UBC 0 : PG_FREE_IF_COPY(jba, 0);
176 UIC 0 : PG_FREE_IF_COPY(jbb, 1);
177 0 : PG_RETURN_BOOL(res);
178 : }
179 ECB :
180 : Datum
181 CBC 2694 : jsonb_gt(PG_FUNCTION_ARGS)
182 ECB : {
183 GIC 2694 : Jsonb *jba = PG_GETARG_JSONB_P(0);
184 2694 : Jsonb *jbb = PG_GETARG_JSONB_P(1);
185 ECB : bool res;
186 :
187 CBC 2694 : res = (compareJsonbContainers(&jba->root, &jbb->root) > 0);
188 ECB :
189 CBC 2694 : PG_FREE_IF_COPY(jba, 0);
190 GIC 2694 : PG_FREE_IF_COPY(jbb, 1);
191 2694 : PG_RETURN_BOOL(res);
192 : }
193 EUB :
194 : Datum
195 UBC 0 : jsonb_le(PG_FUNCTION_ARGS)
196 EUB : {
197 UIC 0 : Jsonb *jba = PG_GETARG_JSONB_P(0);
198 0 : Jsonb *jbb = PG_GETARG_JSONB_P(1);
199 EUB : bool res;
200 :
201 UBC 0 : res = (compareJsonbContainers(&jba->root, &jbb->root) <= 0);
202 EUB :
203 UBC 0 : PG_FREE_IF_COPY(jba, 0);
204 UIC 0 : PG_FREE_IF_COPY(jbb, 1);
205 0 : PG_RETURN_BOOL(res);
206 : }
207 EUB :
208 : Datum
209 UBC 0 : jsonb_ge(PG_FUNCTION_ARGS)
210 EUB : {
211 UIC 0 : Jsonb *jba = PG_GETARG_JSONB_P(0);
212 0 : Jsonb *jbb = PG_GETARG_JSONB_P(1);
213 EUB : bool res;
214 :
215 UBC 0 : res = (compareJsonbContainers(&jba->root, &jbb->root) >= 0);
216 EUB :
217 UBC 0 : PG_FREE_IF_COPY(jba, 0);
218 UIC 0 : PG_FREE_IF_COPY(jbb, 1);
219 0 : PG_RETURN_BOOL(res);
220 : }
221 ECB :
222 : Datum
223 CBC 12512 : jsonb_eq(PG_FUNCTION_ARGS)
224 ECB : {
225 GIC 12512 : Jsonb *jba = PG_GETARG_JSONB_P(0);
226 12512 : Jsonb *jbb = PG_GETARG_JSONB_P(1);
227 ECB : bool res;
228 :
229 CBC 12512 : res = (compareJsonbContainers(&jba->root, &jbb->root) == 0);
230 ECB :
231 CBC 12512 : PG_FREE_IF_COPY(jba, 0);
232 GIC 12512 : PG_FREE_IF_COPY(jbb, 1);
233 12512 : PG_RETURN_BOOL(res);
234 : }
235 ECB :
236 : Datum
237 CBC 121360 : jsonb_cmp(PG_FUNCTION_ARGS)
238 ECB : {
239 GIC 121360 : Jsonb *jba = PG_GETARG_JSONB_P(0);
240 121360 : Jsonb *jbb = PG_GETARG_JSONB_P(1);
241 ECB : int res;
242 :
243 CBC 121360 : res = compareJsonbContainers(&jba->root, &jbb->root);
244 ECB :
245 CBC 121360 : PG_FREE_IF_COPY(jba, 0);
246 GIC 121360 : PG_FREE_IF_COPY(jbb, 1);
247 121360 : PG_RETURN_INT32(res);
248 : }
249 :
250 : /*
251 : * Hash operator class jsonb hashing function
252 ECB : */
253 : Datum
254 CBC 6090 : jsonb_hash(PG_FUNCTION_ARGS)
255 : {
256 GIC 6090 : Jsonb *jb = PG_GETARG_JSONB_P(0);
257 : JsonbIterator *it;
258 ECB : JsonbValue v;
259 : JsonbIteratorToken r;
260 CBC 6090 : uint32 hash = 0;
261 ECB :
262 GIC 6090 : if (JB_ROOT_COUNT(jb) == 0)
263 CBC 708 : PG_RETURN_INT32(0);
264 :
265 5382 : it = JsonbIteratorInit(&jb->root);
266 :
267 73956 : while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
268 : {
269 GIC 68574 : switch (r)
270 ECB : {
271 : /* Rotation is left to JsonbHashScalarValue() */
272 CBC 42 : case WJB_BEGIN_ARRAY:
273 42 : hash ^= JB_FARRAY;
274 42 : break;
275 5418 : case WJB_BEGIN_OBJECT:
276 5418 : hash ^= JB_FOBJECT;
277 GIC 5418 : break;
278 57654 : case WJB_KEY:
279 ECB : case WJB_VALUE:
280 : case WJB_ELEM:
281 CBC 57654 : JsonbHashScalarValue(&v, &hash);
282 GIC 57654 : break;
283 CBC 5460 : case WJB_END_ARRAY:
284 EUB : case WJB_END_OBJECT:
285 GBC 5460 : break;
286 UIC 0 : default:
287 0 : elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
288 : }
289 ECB : }
290 :
291 GIC 5382 : PG_FREE_IF_COPY(jb, 0);
292 5382 : PG_RETURN_INT32(hash);
293 : }
294 ECB :
295 : Datum
296 CBC 18 : jsonb_hash_extended(PG_FUNCTION_ARGS)
297 ECB : {
298 GIC 18 : Jsonb *jb = PG_GETARG_JSONB_P(0);
299 18 : uint64 seed = PG_GETARG_INT64(1);
300 : JsonbIterator *it;
301 ECB : JsonbValue v;
302 : JsonbIteratorToken r;
303 CBC 18 : uint64 hash = 0;
304 EUB :
305 GIC 18 : if (JB_ROOT_COUNT(jb) == 0)
306 LBC 0 : PG_RETURN_UINT64(seed);
307 :
308 CBC 18 : it = JsonbIteratorInit(&jb->root);
309 :
310 222 : while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
311 : {
312 GIC 204 : switch (r)
313 ECB : {
314 : /* Rotation is left to JsonbHashScalarValueExtended() */
315 CBC 12 : case WJB_BEGIN_ARRAY:
316 12 : hash ^= ((uint64) JB_FARRAY) << 32 | JB_FARRAY;
317 12 : break;
318 36 : case WJB_BEGIN_OBJECT:
319 36 : hash ^= ((uint64) JB_FOBJECT) << 32 | JB_FOBJECT;
320 GIC 36 : break;
321 108 : case WJB_KEY:
322 ECB : case WJB_VALUE:
323 : case WJB_ELEM:
324 CBC 108 : JsonbHashScalarValueExtended(&v, &hash, seed);
325 GIC 108 : break;
326 CBC 48 : case WJB_END_ARRAY:
327 EUB : case WJB_END_OBJECT:
328 GBC 48 : break;
329 UIC 0 : default:
330 0 : elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
331 : }
332 ECB : }
333 :
334 GIC 18 : PG_FREE_IF_COPY(jb, 0);
335 18 : PG_RETURN_UINT64(hash);
336 : }
|