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