Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * jsonb_util.c
4 : * converting between Jsonb and JsonbValues, and iterating.
5 : *
6 : * Copyright (c) 2014-2025, PostgreSQL Global Development Group
7 : *
8 : *
9 : * IDENTIFICATION
10 : * src/backend/utils/adt/jsonb_util.c
11 : *
12 : *-------------------------------------------------------------------------
13 : */
14 : #include "postgres.h"
15 :
16 : #include "catalog/pg_collation.h"
17 : #include "common/hashfn.h"
18 : #include "miscadmin.h"
19 : #include "port/pg_bitutils.h"
20 : #include "utils/datetime.h"
21 : #include "utils/fmgrprotos.h"
22 : #include "utils/json.h"
23 : #include "utils/jsonb.h"
24 : #include "utils/memutils.h"
25 : #include "utils/varlena.h"
26 :
27 : /*
28 : * Maximum number of elements in an array (or key/value pairs in an object).
29 : * This is limited by two things: the size of the JEntry array must fit
30 : * in MaxAllocSize, and the number of elements (or pairs) must fit in the bits
31 : * reserved for that in the JsonbContainer.header field.
32 : *
33 : * (The total size of an array's or object's elements is also limited by
34 : * JENTRY_OFFLENMASK, but we're not concerned about that here.)
35 : */
36 : #define JSONB_MAX_ELEMS (Min(MaxAllocSize / sizeof(JsonbValue), JB_CMASK))
37 : #define JSONB_MAX_PAIRS (Min(MaxAllocSize / sizeof(JsonbPair), JB_CMASK))
38 :
39 : static void fillJsonbValue(JsonbContainer *container, int index,
40 : char *base_addr, uint32 offset,
41 : JsonbValue *result);
42 : static bool equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b);
43 : static int compareJsonbScalarValue(JsonbValue *a, JsonbValue *b);
44 : static Jsonb *convertToJsonb(JsonbValue *val);
45 : static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
46 : static void convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
47 : static void convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
48 : static void convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal);
49 :
50 : static int reserveFromBuffer(StringInfo buffer, int len);
51 : static void appendToBuffer(StringInfo buffer, const void *data, int len);
52 : static void copyToBuffer(StringInfo buffer, int offset, const void *data, int len);
53 : static short padBufferToInt(StringInfo buffer);
54 :
55 : static JsonbIterator *iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent);
56 : static JsonbIterator *freeAndGetParent(JsonbIterator *it);
57 : static JsonbParseState *pushState(JsonbParseState **pstate);
58 : static void appendKey(JsonbParseState *pstate, JsonbValue *string);
59 : static void appendValue(JsonbParseState *pstate, JsonbValue *scalarVal);
60 : static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal);
61 : static int lengthCompareJsonbStringValue(const void *a, const void *b);
62 : static int lengthCompareJsonbString(const char *val1, int len1,
63 : const char *val2, int len2);
64 : static int lengthCompareJsonbPair(const void *a, const void *b, void *binequal);
65 : static void uniqueifyJsonbObject(JsonbValue *object, bool unique_keys,
66 : bool skip_nulls);
67 : static JsonbValue *pushJsonbValueScalar(JsonbParseState **pstate,
68 : JsonbIteratorToken seq,
69 : JsonbValue *scalarVal);
70 :
71 : void
72 654 : JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
73 : {
74 654 : val->type = jbvBinary;
75 654 : val->val.binary.data = &jsonb->root;
76 654 : val->val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
77 654 : }
78 :
79 : /*
80 : * Turn an in-memory JsonbValue into a Jsonb for on-disk storage.
81 : *
82 : * Generally we find it more convenient to directly iterate through the Jsonb
83 : * representation and only really convert nested scalar values.
84 : * JsonbIteratorNext() does this, so that clients of the iteration code don't
85 : * have to directly deal with the binary representation (JsonbDeepContains() is
86 : * a notable exception, although all exceptions are internal to this module).
87 : * In general, functions that accept a JsonbValue argument are concerned with
88 : * the manipulation of scalar values, or simple containers of scalar values,
89 : * where it would be inconvenient to deal with a great amount of other state.
90 : */
91 : Jsonb *
92 100620 : JsonbValueToJsonb(JsonbValue *val)
93 : {
94 : Jsonb *out;
95 :
96 100620 : if (IsAJsonbScalar(val))
97 68822 : {
98 : /* Scalar value */
99 68822 : JsonbParseState *pstate = NULL;
100 : JsonbValue *res;
101 : JsonbValue scalarArray;
102 :
103 68822 : scalarArray.type = jbvArray;
104 68822 : scalarArray.val.array.rawScalar = true;
105 68822 : scalarArray.val.array.nElems = 1;
106 :
107 68822 : pushJsonbValue(&pstate, WJB_BEGIN_ARRAY, &scalarArray);
108 68822 : pushJsonbValue(&pstate, WJB_ELEM, val);
109 68822 : res = pushJsonbValue(&pstate, WJB_END_ARRAY, NULL);
110 :
111 68822 : out = convertToJsonb(res);
112 : }
113 31798 : else if (val->type == jbvObject || val->type == jbvArray)
114 : {
115 29742 : out = convertToJsonb(val);
116 : }
117 : else
118 : {
119 : Assert(val->type == jbvBinary);
120 2056 : out = palloc(VARHDRSZ + val->val.binary.len);
121 2056 : SET_VARSIZE(out, VARHDRSZ + val->val.binary.len);
122 2056 : memcpy(VARDATA(out), val->val.binary.data, val->val.binary.len);
123 : }
124 :
125 100620 : return out;
126 : }
127 :
128 : /*
129 : * Get the offset of the variable-length portion of a Jsonb node within
130 : * the variable-length-data part of its container. The node is identified
131 : * by index within the container's JEntry array.
132 : */
133 : uint32
134 1975534 : getJsonbOffset(const JsonbContainer *jc, int index)
135 : {
136 1975534 : uint32 offset = 0;
137 : int i;
138 :
139 : /*
140 : * Start offset of this entry is equal to the end offset of the previous
141 : * entry. Walk backwards to the most recent entry stored as an end
142 : * offset, returning that offset plus any lengths in between.
143 : */
144 5721808 : for (i = index - 1; i >= 0; i--)
145 : {
146 4951160 : offset += JBE_OFFLENFLD(jc->children[i]);
147 4951160 : if (JBE_HAS_OFF(jc->children[i]))
148 1204886 : break;
149 : }
150 :
151 1975534 : return offset;
152 : }
153 :
154 : /*
155 : * Get the length of the variable-length portion of a Jsonb node.
156 : * The node is identified by index within the container's JEntry array.
157 : */
158 : uint32
159 1816106 : getJsonbLength(const JsonbContainer *jc, int index)
160 : {
161 : uint32 off;
162 : uint32 len;
163 :
164 : /*
165 : * If the length is stored directly in the JEntry, just return it.
166 : * Otherwise, get the begin offset of the entry, and subtract that from
167 : * the stored end+1 offset.
168 : */
169 1816106 : if (JBE_HAS_OFF(jc->children[index]))
170 : {
171 611918 : off = getJsonbOffset(jc, index);
172 611918 : len = JBE_OFFLENFLD(jc->children[index]) - off;
173 : }
174 : else
175 1204188 : len = JBE_OFFLENFLD(jc->children[index]);
176 :
177 1816106 : return len;
178 : }
179 :
180 : /*
181 : * BT comparator worker function. Returns an integer less than, equal to, or
182 : * greater than zero, indicating whether a is less than, equal to, or greater
183 : * than b. Consistent with the requirements for a B-Tree operator class
184 : *
185 : * Strings are compared lexically, in contrast with other places where we use a
186 : * much simpler comparator logic for searching through Strings. Since this is
187 : * called from B-Tree support function 1, we're careful about not leaking
188 : * memory here.
189 : */
190 : int
191 268458 : compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
192 : {
193 : JsonbIterator *ita,
194 : *itb;
195 268458 : int res = 0;
196 :
197 268458 : ita = JsonbIteratorInit(a);
198 268458 : itb = JsonbIteratorInit(b);
199 :
200 : do
201 : {
202 : JsonbValue va,
203 : vb;
204 : JsonbIteratorToken ra,
205 : rb;
206 :
207 793780 : ra = JsonbIteratorNext(&ita, &va, false);
208 793780 : rb = JsonbIteratorNext(&itb, &vb, false);
209 :
210 793780 : if (ra == rb)
211 : {
212 793780 : if (ra == WJB_DONE)
213 : {
214 : /* Decisively equal */
215 27670 : break;
216 : }
217 :
218 766110 : if (ra == WJB_END_ARRAY || ra == WJB_END_OBJECT)
219 : {
220 : /*
221 : * There is no array or object to compare at this stage of
222 : * processing. jbvArray/jbvObject values are compared
223 : * initially, at the WJB_BEGIN_ARRAY and WJB_BEGIN_OBJECT
224 : * tokens.
225 : */
226 27822 : continue;
227 : }
228 :
229 738288 : if (va.type == vb.type)
230 : {
231 738288 : switch (va.type)
232 : {
233 469364 : case jbvString:
234 : case jbvNull:
235 : case jbvNumeric:
236 : case jbvBool:
237 469364 : res = compareJsonbScalarValue(&va, &vb);
238 469364 : break;
239 390 : case jbvArray:
240 :
241 : /*
242 : * This could be a "raw scalar" pseudo array. That's
243 : * a special case here though, since we still want the
244 : * general type-based comparisons to apply, and as far
245 : * as we're concerned a pseudo array is just a scalar.
246 : */
247 390 : if (va.val.array.rawScalar != vb.val.array.rawScalar)
248 6 : res = (va.val.array.rawScalar) ? -1 : 1;
249 :
250 : /*
251 : * There should be an "else" here, to prevent us from
252 : * overriding the above, but we can't change the sort
253 : * order now, so there is a mild anomaly that an empty
254 : * top level array sorts less than null.
255 : */
256 390 : if (va.val.array.nElems != vb.val.array.nElems)
257 182 : res = (va.val.array.nElems > vb.val.array.nElems) ? 1 : -1;
258 390 : break;
259 268534 : case jbvObject:
260 268534 : if (va.val.object.nPairs != vb.val.object.nPairs)
261 83010 : res = (va.val.object.nPairs > vb.val.object.nPairs) ? 1 : -1;
262 268534 : break;
263 0 : case jbvBinary:
264 0 : elog(ERROR, "unexpected jbvBinary value");
265 : break;
266 0 : case jbvDatetime:
267 0 : elog(ERROR, "unexpected jbvDatetime value");
268 : break;
269 : }
270 : }
271 : else
272 : {
273 : /* Type-defined order */
274 0 : res = (va.type > vb.type) ? 1 : -1;
275 : }
276 : }
277 : else
278 : {
279 : /*
280 : * It's not possible for one iterator to report end of array or
281 : * object while the other one reports something else, because we
282 : * would have detected a length mismatch when we processed the
283 : * container-start tokens above. Likewise we can't see WJB_DONE
284 : * from one but not the other. So we have two different-type
285 : * containers, or a container and some scalar type, or two
286 : * different scalar types. Sort on the basis of the type code.
287 : */
288 : Assert(ra != WJB_DONE && ra != WJB_END_ARRAY && ra != WJB_END_OBJECT);
289 : Assert(rb != WJB_DONE && rb != WJB_END_ARRAY && rb != WJB_END_OBJECT);
290 :
291 : Assert(va.type != vb.type);
292 : Assert(va.type != jbvBinary);
293 : Assert(vb.type != jbvBinary);
294 : /* Type-defined order */
295 0 : res = (va.type > vb.type) ? 1 : -1;
296 : }
297 : }
298 766110 : while (res == 0);
299 :
300 509560 : while (ita != NULL)
301 : {
302 241102 : JsonbIterator *i = ita->parent;
303 :
304 241102 : pfree(ita);
305 241102 : ita = i;
306 : }
307 509560 : while (itb != NULL)
308 : {
309 241102 : JsonbIterator *i = itb->parent;
310 :
311 241102 : pfree(itb);
312 241102 : itb = i;
313 : }
314 :
315 268458 : return res;
316 : }
317 :
318 : /*
319 : * Find value in object (i.e. the "value" part of some key/value pair in an
320 : * object), or find a matching element if we're looking through an array. Do
321 : * so on the basis of equality of the object keys only, or alternatively
322 : * element values only, with a caller-supplied value "key". The "flags"
323 : * argument allows the caller to specify which container types are of interest.
324 : *
325 : * This exported utility function exists to facilitate various cases concerned
326 : * with "containment". If asked to look through an object, the caller had
327 : * better pass a Jsonb String, because their keys can only be strings.
328 : * Otherwise, for an array, any type of JsonbValue will do.
329 : *
330 : * In order to proceed with the search, it is necessary for callers to have
331 : * both specified an interest in exactly one particular container type with an
332 : * appropriate flag, as well as having the pointed-to Jsonb container be of
333 : * one of those same container types at the top level. (Actually, we just do
334 : * whichever makes sense to save callers the trouble of figuring it out - at
335 : * most one can make sense, because the container either points to an array
336 : * (possibly a "raw scalar" pseudo array) or an object.)
337 : *
338 : * Note that we can return a jbvBinary JsonbValue if this is called on an
339 : * object, but we never do so on an array. If the caller asks to look through
340 : * a container type that is not of the type pointed to by the container,
341 : * immediately fall through and return NULL. If we cannot find the value,
342 : * return NULL. Otherwise, return palloc()'d copy of value.
343 : */
344 : JsonbValue *
345 207538 : findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
346 : JsonbValue *key)
347 : {
348 207538 : JEntry *children = container->children;
349 207538 : int count = JsonContainerSize(container);
350 :
351 : Assert((flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);
352 :
353 : /* Quick out without a palloc cycle if object/array is empty */
354 207538 : if (count <= 0)
355 22074 : return NULL;
356 :
357 185464 : if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
358 96 : {
359 480 : JsonbValue *result = palloc(sizeof(JsonbValue));
360 480 : char *base_addr = (char *) (children + count);
361 480 : uint32 offset = 0;
362 : int i;
363 :
364 894 : for (i = 0; i < count; i++)
365 : {
366 798 : fillJsonbValue(container, i, base_addr, offset, result);
367 :
368 798 : if (key->type == result->type)
369 : {
370 708 : if (equalsJsonbScalarValue(key, result))
371 384 : return result;
372 : }
373 :
374 414 : JBE_ADVANCE_OFFSET(offset, children[i]);
375 : }
376 :
377 96 : pfree(result);
378 : }
379 184984 : else if ((flags & JB_FOBJECT) && JsonContainerIsObject(container))
380 : {
381 : /* Object key passed by caller must be a string */
382 : Assert(key->type == jbvString);
383 :
384 184984 : return getKeyJsonValueFromContainer(container, key->val.string.val,
385 : key->val.string.len, NULL);
386 : }
387 :
388 : /* Not found */
389 96 : return NULL;
390 : }
391 :
392 : /*
393 : * Find value by key in Jsonb object and fetch it into 'res', which is also
394 : * returned.
395 : *
396 : * 'res' can be passed in as NULL, in which case it's newly palloc'ed here.
397 : */
398 : JsonbValue *
399 253468 : getKeyJsonValueFromContainer(JsonbContainer *container,
400 : const char *keyVal, int keyLen, JsonbValue *res)
401 : {
402 253468 : JEntry *children = container->children;
403 253468 : int count = JsonContainerSize(container);
404 : char *baseAddr;
405 : uint32 stopLow,
406 : stopHigh;
407 :
408 : Assert(JsonContainerIsObject(container));
409 :
410 : /* Quick out without a palloc cycle if object is empty */
411 253468 : if (count <= 0)
412 2832 : return NULL;
413 :
414 : /*
415 : * Binary search the container. Since we know this is an object, account
416 : * for *Pairs* of Jentrys
417 : */
418 250636 : baseAddr = (char *) (children + count * 2);
419 250636 : stopLow = 0;
420 250636 : stopHigh = count;
421 804562 : while (stopLow < stopHigh)
422 : {
423 : uint32 stopMiddle;
424 : int difference;
425 : const char *candidateVal;
426 : int candidateLen;
427 :
428 604228 : stopMiddle = stopLow + (stopHigh - stopLow) / 2;
429 :
430 604228 : candidateVal = baseAddr + getJsonbOffset(container, stopMiddle);
431 604228 : candidateLen = getJsonbLength(container, stopMiddle);
432 :
433 604228 : difference = lengthCompareJsonbString(candidateVal, candidateLen,
434 : keyVal, keyLen);
435 :
436 604228 : if (difference == 0)
437 : {
438 : /* Found our key, return corresponding value */
439 50302 : int index = stopMiddle + count;
440 :
441 50302 : if (!res)
442 45448 : res = palloc(sizeof(JsonbValue));
443 :
444 50302 : fillJsonbValue(container, index, baseAddr,
445 : getJsonbOffset(container, index),
446 : res);
447 :
448 50302 : return res;
449 : }
450 : else
451 : {
452 553926 : if (difference < 0)
453 205320 : stopLow = stopMiddle + 1;
454 : else
455 348606 : stopHigh = stopMiddle;
456 : }
457 : }
458 :
459 : /* Not found */
460 200334 : return NULL;
461 : }
462 :
463 : /*
464 : * Get i-th value of a Jsonb array.
465 : *
466 : * Returns palloc()'d copy of the value, or NULL if it does not exist.
467 : */
468 : JsonbValue *
469 990 : getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
470 : {
471 : JsonbValue *result;
472 : char *base_addr;
473 : uint32 nelements;
474 :
475 990 : if (!JsonContainerIsArray(container))
476 0 : elog(ERROR, "not a jsonb array");
477 :
478 990 : nelements = JsonContainerSize(container);
479 990 : base_addr = (char *) &container->children[nelements];
480 :
481 990 : if (i >= nelements)
482 60 : return NULL;
483 :
484 930 : result = palloc(sizeof(JsonbValue));
485 :
486 930 : fillJsonbValue(container, i, base_addr,
487 : getJsonbOffset(container, i),
488 : result);
489 :
490 930 : return result;
491 : }
492 :
493 : /*
494 : * A helper function to fill in a JsonbValue to represent an element of an
495 : * array, or a key or value of an object.
496 : *
497 : * The node's JEntry is at container->children[index], and its variable-length
498 : * data is at base_addr + offset. We make the caller determine the offset
499 : * since in many cases the caller can amortize that work across multiple
500 : * children. When it can't, it can just call getJsonbOffset().
501 : *
502 : * A nested array or object will be returned as jbvBinary, ie. it won't be
503 : * expanded.
504 : */
505 : static void
506 1763606 : fillJsonbValue(JsonbContainer *container, int index,
507 : char *base_addr, uint32 offset,
508 : JsonbValue *result)
509 : {
510 1763606 : JEntry entry = container->children[index];
511 :
512 1763606 : if (JBE_ISNULL(entry))
513 : {
514 7354 : result->type = jbvNull;
515 : }
516 1756252 : else if (JBE_ISSTRING(entry))
517 : {
518 1143716 : result->type = jbvString;
519 1143716 : result->val.string.val = base_addr + offset;
520 1143716 : result->val.string.len = getJsonbLength(container, index);
521 : Assert(result->val.string.len >= 0);
522 : }
523 612536 : else if (JBE_ISNUMERIC(entry))
524 : {
525 389450 : result->type = jbvNumeric;
526 389450 : result->val.numeric = (Numeric) (base_addr + INTALIGN(offset));
527 : }
528 223086 : else if (JBE_ISBOOL_TRUE(entry))
529 : {
530 73776 : result->type = jbvBool;
531 73776 : result->val.boolean = true;
532 : }
533 149310 : else if (JBE_ISBOOL_FALSE(entry))
534 : {
535 81148 : result->type = jbvBool;
536 81148 : result->val.boolean = false;
537 : }
538 : else
539 : {
540 : Assert(JBE_ISCONTAINER(entry));
541 68162 : result->type = jbvBinary;
542 : /* Remove alignment padding from data pointer and length */
543 68162 : result->val.binary.data = (JsonbContainer *) (base_addr + INTALIGN(offset));
544 68162 : result->val.binary.len = getJsonbLength(container, index) -
545 68162 : (INTALIGN(offset) - offset);
546 : }
547 1763606 : }
548 :
549 : /*
550 : * Push JsonbValue into JsonbParseState.
551 : *
552 : * Used when parsing JSON tokens to form Jsonb, or when converting an in-memory
553 : * JsonbValue to a Jsonb.
554 : *
555 : * Initial state of *JsonbParseState is NULL, since it'll be allocated here
556 : * originally (caller will get JsonbParseState back by reference).
557 : *
558 : * Only sequential tokens pertaining to non-container types should pass a
559 : * JsonbValue. There is one exception -- WJB_BEGIN_ARRAY callers may pass a
560 : * "raw scalar" pseudo array to append it - the actual scalar should be passed
561 : * next and it will be added as the only member of the array.
562 : *
563 : * Values of type jbvBinary, which are rolled up arrays and objects,
564 : * are unpacked before being added to the result.
565 : */
566 : JsonbValue *
567 471788 : pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
568 : JsonbValue *jbval)
569 : {
570 : JsonbIterator *it;
571 471788 : JsonbValue *res = NULL;
572 : JsonbValue v;
573 : JsonbIteratorToken tok;
574 : int i;
575 :
576 471788 : if (jbval && (seq == WJB_ELEM || seq == WJB_VALUE) && jbval->type == jbvObject)
577 : {
578 0 : pushJsonbValue(pstate, WJB_BEGIN_OBJECT, NULL);
579 0 : for (i = 0; i < jbval->val.object.nPairs; i++)
580 : {
581 0 : pushJsonbValue(pstate, WJB_KEY, &jbval->val.object.pairs[i].key);
582 0 : pushJsonbValue(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value);
583 : }
584 :
585 0 : return pushJsonbValue(pstate, WJB_END_OBJECT, NULL);
586 : }
587 :
588 471788 : if (jbval && (seq == WJB_ELEM || seq == WJB_VALUE) && jbval->type == jbvArray)
589 : {
590 0 : pushJsonbValue(pstate, WJB_BEGIN_ARRAY, NULL);
591 0 : for (i = 0; i < jbval->val.array.nElems; i++)
592 : {
593 0 : pushJsonbValue(pstate, WJB_ELEM, &jbval->val.array.elems[i]);
594 : }
595 :
596 0 : return pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
597 : }
598 :
599 471788 : if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
600 163192 : jbval->type != jbvBinary)
601 : {
602 : /* drop through */
603 470918 : return pushJsonbValueScalar(pstate, seq, jbval);
604 : }
605 :
606 : /* unpack the binary and add each piece to the pstate */
607 870 : it = JsonbIteratorInit(jbval->val.binary.data);
608 :
609 870 : if ((jbval->val.binary.data->header & JB_FSCALAR) && *pstate)
610 : {
611 342 : tok = JsonbIteratorNext(&it, &v, true);
612 : Assert(tok == WJB_BEGIN_ARRAY);
613 : Assert(v.type == jbvArray && v.val.array.rawScalar);
614 :
615 342 : tok = JsonbIteratorNext(&it, &v, true);
616 : Assert(tok == WJB_ELEM);
617 :
618 342 : res = pushJsonbValueScalar(pstate, seq, &v);
619 :
620 342 : tok = JsonbIteratorNext(&it, &v, true);
621 : Assert(tok == WJB_END_ARRAY);
622 : Assert(it == NULL);
623 :
624 342 : return res;
625 : }
626 :
627 3696 : while ((tok = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
628 4632 : res = pushJsonbValueScalar(pstate, tok,
629 1464 : tok < WJB_BEGIN_ARRAY ||
630 390 : (tok == WJB_BEGIN_ARRAY &&
631 390 : v.val.array.rawScalar) ? &v : NULL);
632 :
633 528 : return res;
634 : }
635 :
636 : /*
637 : * Do the actual pushing, with only scalar or pseudo-scalar-array values
638 : * accepted.
639 : */
640 : static JsonbValue *
641 474428 : pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
642 : JsonbValue *scalarVal)
643 : {
644 474428 : JsonbValue *result = NULL;
645 :
646 474428 : switch (seq)
647 : {
648 93004 : case WJB_BEGIN_ARRAY:
649 : Assert(!scalarVal || scalarVal->val.array.rawScalar);
650 93004 : *pstate = pushState(pstate);
651 93004 : result = &(*pstate)->contVal;
652 93004 : (*pstate)->contVal.type = jbvArray;
653 93004 : (*pstate)->contVal.val.array.nElems = 0;
654 168274 : (*pstate)->contVal.val.array.rawScalar = (scalarVal &&
655 75270 : scalarVal->val.array.rawScalar);
656 93004 : if (scalarVal && scalarVal->val.array.nElems > 0)
657 : {
658 : /* Assume that this array is still really a scalar */
659 : Assert(scalarVal->type == jbvArray);
660 75270 : (*pstate)->size = scalarVal->val.array.nElems;
661 : }
662 : else
663 : {
664 17734 : (*pstate)->size = 4;
665 : }
666 186008 : (*pstate)->contVal.val.array.elems = palloc(sizeof(JsonbValue) *
667 93004 : (*pstate)->size);
668 93004 : break;
669 28414 : case WJB_BEGIN_OBJECT:
670 : Assert(!scalarVal);
671 28414 : *pstate = pushState(pstate);
672 28414 : result = &(*pstate)->contVal;
673 28414 : (*pstate)->contVal.type = jbvObject;
674 28414 : (*pstate)->contVal.val.object.nPairs = 0;
675 28414 : (*pstate)->size = 4;
676 56828 : (*pstate)->contVal.val.object.pairs = palloc(sizeof(JsonbPair) *
677 28414 : (*pstate)->size);
678 28414 : break;
679 75944 : case WJB_KEY:
680 : Assert(scalarVal->type == jbvString);
681 75944 : appendKey(*pstate, scalarVal);
682 75944 : break;
683 64446 : case WJB_VALUE:
684 : Assert(IsAJsonbScalar(scalarVal));
685 64446 : appendValue(*pstate, scalarVal);
686 64446 : break;
687 99286 : case WJB_ELEM:
688 : Assert(IsAJsonbScalar(scalarVal));
689 99286 : appendElement(*pstate, scalarVal);
690 99286 : break;
691 24656 : case WJB_END_OBJECT:
692 24656 : uniqueifyJsonbObject(&(*pstate)->contVal,
693 24656 : (*pstate)->unique_keys,
694 24656 : (*pstate)->skip_nulls);
695 : /* fall through! */
696 113304 : case WJB_END_ARRAY:
697 : /* Steps here common to WJB_END_OBJECT case */
698 : Assert(!scalarVal);
699 113304 : result = &(*pstate)->contVal;
700 :
701 : /*
702 : * Pop stack and push current array/object as value in parent
703 : * array/object
704 : */
705 113304 : *pstate = (*pstate)->next;
706 113304 : if (*pstate)
707 : {
708 14740 : switch ((*pstate)->contVal.type)
709 : {
710 6784 : case jbvArray:
711 6784 : appendElement(*pstate, result);
712 6784 : break;
713 7956 : case jbvObject:
714 7956 : appendValue(*pstate, result);
715 7956 : break;
716 0 : default:
717 0 : elog(ERROR, "invalid jsonb container type");
718 : }
719 : }
720 113304 : break;
721 0 : default:
722 0 : elog(ERROR, "unrecognized jsonb sequential processing token");
723 : }
724 :
725 474398 : return result;
726 : }
727 :
728 : /*
729 : * pushJsonbValue() worker: Iteration-like forming of Jsonb
730 : */
731 : static JsonbParseState *
732 121418 : pushState(JsonbParseState **pstate)
733 : {
734 121418 : JsonbParseState *ns = palloc(sizeof(JsonbParseState));
735 :
736 121418 : ns->next = *pstate;
737 121418 : ns->unique_keys = false;
738 121418 : ns->skip_nulls = false;
739 :
740 121418 : return ns;
741 : }
742 :
743 : /*
744 : * pushJsonbValue() worker: Append a pair key to state when generating a Jsonb
745 : */
746 : static void
747 75944 : appendKey(JsonbParseState *pstate, JsonbValue *string)
748 : {
749 75944 : JsonbValue *object = &pstate->contVal;
750 :
751 : Assert(object->type == jbvObject);
752 : Assert(string->type == jbvString);
753 :
754 75944 : if (object->val.object.nPairs >= JSONB_MAX_PAIRS)
755 0 : ereport(ERROR,
756 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
757 : errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
758 : JSONB_MAX_PAIRS)));
759 :
760 75944 : if (object->val.object.nPairs >= pstate->size)
761 : {
762 7096 : pstate->size *= 2;
763 7096 : object->val.object.pairs = repalloc(object->val.object.pairs,
764 7096 : sizeof(JsonbPair) * pstate->size);
765 : }
766 :
767 75944 : object->val.object.pairs[object->val.object.nPairs].key = *string;
768 75944 : object->val.object.pairs[object->val.object.nPairs].order = object->val.object.nPairs;
769 75944 : }
770 :
771 : /*
772 : * pushJsonbValue() worker: Append a pair value to state when generating a
773 : * Jsonb
774 : */
775 : static void
776 72402 : appendValue(JsonbParseState *pstate, JsonbValue *scalarVal)
777 : {
778 72402 : JsonbValue *object = &pstate->contVal;
779 :
780 : Assert(object->type == jbvObject);
781 :
782 72402 : object->val.object.pairs[object->val.object.nPairs++].value = *scalarVal;
783 72402 : }
784 :
785 : /*
786 : * pushJsonbValue() worker: Append an element to state when generating a Jsonb
787 : */
788 : static void
789 106070 : appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
790 : {
791 106070 : JsonbValue *array = &pstate->contVal;
792 :
793 : Assert(array->type == jbvArray);
794 :
795 106070 : if (array->val.array.nElems >= JSONB_MAX_ELEMS)
796 0 : ereport(ERROR,
797 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
798 : errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
799 : JSONB_MAX_ELEMS)));
800 :
801 106070 : if (array->val.array.nElems >= pstate->size)
802 : {
803 1730 : pstate->size *= 2;
804 1730 : array->val.array.elems = repalloc(array->val.array.elems,
805 1730 : sizeof(JsonbValue) * pstate->size);
806 : }
807 :
808 106070 : array->val.array.elems[array->val.array.nElems++] = *scalarVal;
809 106070 : }
810 :
811 : /*
812 : * Given a JsonbContainer, expand to JsonbIterator to iterate over items
813 : * fully expanded to in-memory representation for manipulation.
814 : *
815 : * See JsonbIteratorNext() for notes on memory management.
816 : */
817 : JsonbIterator *
818 724990 : JsonbIteratorInit(JsonbContainer *container)
819 : {
820 724990 : return iteratorFromContainer(container, NULL);
821 : }
822 :
823 : /*
824 : * Get next JsonbValue while iterating
825 : *
826 : * Caller should initially pass their own, original iterator. They may get
827 : * back a child iterator palloc()'d here instead. The function can be relied
828 : * on to free those child iterators, lest the memory allocated for highly
829 : * nested objects become unreasonable, but only if callers don't end iteration
830 : * early (by breaking upon having found something in a search, for example).
831 : *
832 : * Callers in such a scenario, that are particularly sensitive to leaking
833 : * memory in a long-lived context may walk the ancestral tree from the final
834 : * iterator we left them with to its oldest ancestor, pfree()ing as they go.
835 : * They do not have to free any other memory previously allocated for iterators
836 : * but not accessible as direct ancestors of the iterator they're last passed
837 : * back.
838 : *
839 : * Returns "Jsonb sequential processing" token value. Iterator "state"
840 : * reflects the current stage of the process in a less granular fashion, and is
841 : * mostly used here to track things internally with respect to particular
842 : * iterators.
843 : *
844 : * Clients of this function should not have to handle any jbvBinary values
845 : * (since recursive calls will deal with this), provided skipNested is false.
846 : * It is our job to expand the jbvBinary representation without bothering them
847 : * with it. However, clients should not take it upon themselves to touch array
848 : * or Object element/pair buffers, since their element/pair pointers are
849 : * garbage.
850 : *
851 : * *val is not meaningful when the result is WJB_DONE, WJB_END_ARRAY or
852 : * WJB_END_OBJECT. However, we set val->type = jbvNull in those cases,
853 : * so that callers may assume that val->type is always well-defined.
854 : */
855 : JsonbIteratorToken
856 2817788 : JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
857 : {
858 2817788 : if (*it == NULL)
859 : {
860 153756 : val->type = jbvNull;
861 153756 : return WJB_DONE;
862 : }
863 :
864 : /*
865 : * When stepping into a nested container, we jump back here to start
866 : * processing the child. We will not recurse further in one call, because
867 : * processing the child will always begin in JBI_ARRAY_START or
868 : * JBI_OBJECT_START state.
869 : */
870 2724186 : recurse:
871 2724186 : switch ((*it)->state)
872 : {
873 76988 : case JBI_ARRAY_START:
874 : /* Set v to array on first array call */
875 76988 : val->type = jbvArray;
876 76988 : val->val.array.nElems = (*it)->nElems;
877 :
878 : /*
879 : * v->val.array.elems is not actually set, because we aren't doing
880 : * a full conversion
881 : */
882 76988 : val->val.array.rawScalar = (*it)->isScalar;
883 76988 : (*it)->curIndex = 0;
884 76988 : (*it)->curDataOffset = 0;
885 76988 : (*it)->curValueOffset = 0; /* not actually used */
886 : /* Set state for next call */
887 76988 : (*it)->state = JBI_ARRAY_ELEM;
888 76988 : return WJB_BEGIN_ARRAY;
889 :
890 218216 : case JBI_ARRAY_ELEM:
891 218216 : if ((*it)->curIndex >= (*it)->nElems)
892 : {
893 : /*
894 : * All elements within array already processed. Report this
895 : * to caller, and give it back original parent iterator (which
896 : * independently tracks iteration progress at its level of
897 : * nesting).
898 : */
899 75024 : *it = freeAndGetParent(*it);
900 75024 : val->type = jbvNull;
901 75024 : return WJB_END_ARRAY;
902 : }
903 :
904 143192 : fillJsonbValue((*it)->container, (*it)->curIndex,
905 143192 : (*it)->dataProper, (*it)->curDataOffset,
906 : val);
907 :
908 143192 : JBE_ADVANCE_OFFSET((*it)->curDataOffset,
909 : (*it)->children[(*it)->curIndex]);
910 143192 : (*it)->curIndex++;
911 :
912 143192 : if (!IsAJsonbScalar(val) && !skipNested)
913 : {
914 : /* Recurse into container. */
915 44626 : *it = iteratorFromContainer(val->val.binary.data, *it);
916 44626 : goto recurse;
917 : }
918 : else
919 : {
920 : /*
921 : * Scalar item in array, or a container and caller didn't want
922 : * us to recurse into it.
923 : */
924 98566 : return WJB_ELEM;
925 : }
926 :
927 708156 : case JBI_OBJECT_START:
928 : /* Set v to object on first object call */
929 708156 : val->type = jbvObject;
930 708156 : val->val.object.nPairs = (*it)->nElems;
931 :
932 : /*
933 : * v->val.object.pairs is not actually set, because we aren't
934 : * doing a full conversion
935 : */
936 708156 : (*it)->curIndex = 0;
937 708156 : (*it)->curDataOffset = 0;
938 1416312 : (*it)->curValueOffset = getJsonbOffset((*it)->container,
939 708156 : (*it)->nElems);
940 : /* Set state for next call */
941 708156 : (*it)->state = JBI_OBJECT_KEY;
942 708156 : return WJB_BEGIN_OBJECT;
943 :
944 1010654 : case JBI_OBJECT_KEY:
945 1010654 : if ((*it)->curIndex >= (*it)->nElems)
946 : {
947 : /*
948 : * All pairs within object already processed. Report this to
949 : * caller, and give it back original containing iterator
950 : * (which independently tracks iteration progress at its level
951 : * of nesting).
952 : */
953 152442 : *it = freeAndGetParent(*it);
954 152442 : val->type = jbvNull;
955 152442 : return WJB_END_OBJECT;
956 : }
957 : else
958 : {
959 : /* Return key of a key/value pair. */
960 858212 : fillJsonbValue((*it)->container, (*it)->curIndex,
961 858212 : (*it)->dataProper, (*it)->curDataOffset,
962 : val);
963 858212 : if (val->type != jbvString)
964 0 : elog(ERROR, "unexpected jsonb type as object key");
965 :
966 : /* Set state for next call */
967 858212 : (*it)->state = JBI_OBJECT_VALUE;
968 858212 : return WJB_KEY;
969 : }
970 :
971 710172 : case JBI_OBJECT_VALUE:
972 : /* Set state for next call */
973 710172 : (*it)->state = JBI_OBJECT_KEY;
974 :
975 710172 : fillJsonbValue((*it)->container, (*it)->curIndex + (*it)->nElems,
976 710172 : (*it)->dataProper, (*it)->curValueOffset,
977 : val);
978 :
979 710172 : JBE_ADVANCE_OFFSET((*it)->curDataOffset,
980 : (*it)->children[(*it)->curIndex]);
981 710172 : JBE_ADVANCE_OFFSET((*it)->curValueOffset,
982 : (*it)->children[(*it)->curIndex + (*it)->nElems]);
983 710172 : (*it)->curIndex++;
984 :
985 : /*
986 : * Value may be a container, in which case we recurse with new,
987 : * child iterator (unless the caller asked not to, by passing
988 : * skipNested).
989 : */
990 710172 : if (!IsAJsonbScalar(val) && !skipNested)
991 : {
992 15528 : *it = iteratorFromContainer(val->val.binary.data, *it);
993 15528 : goto recurse;
994 : }
995 : else
996 694644 : return WJB_VALUE;
997 : }
998 :
999 0 : elog(ERROR, "invalid jsonb iterator state");
1000 : /* satisfy compilers that don't know that elog(ERROR) doesn't return */
1001 : val->type = jbvNull;
1002 : return WJB_DONE;
1003 : }
1004 :
1005 : /*
1006 : * Initialize an iterator for iterating all elements in a container.
1007 : */
1008 : static JsonbIterator *
1009 785144 : iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent)
1010 : {
1011 : JsonbIterator *it;
1012 :
1013 785144 : it = palloc0(sizeof(JsonbIterator));
1014 785144 : it->container = container;
1015 785144 : it->parent = parent;
1016 785144 : it->nElems = JsonContainerSize(container);
1017 :
1018 : /* Array starts just after header */
1019 785144 : it->children = container->children;
1020 :
1021 785144 : switch (container->header & (JB_FARRAY | JB_FOBJECT))
1022 : {
1023 76988 : case JB_FARRAY:
1024 76988 : it->dataProper =
1025 76988 : (char *) it->children + it->nElems * sizeof(JEntry);
1026 76988 : it->isScalar = JsonContainerIsScalar(container);
1027 : /* This is either a "raw scalar", or an array */
1028 : Assert(!it->isScalar || it->nElems == 1);
1029 :
1030 76988 : it->state = JBI_ARRAY_START;
1031 76988 : break;
1032 :
1033 708156 : case JB_FOBJECT:
1034 708156 : it->dataProper =
1035 708156 : (char *) it->children + it->nElems * sizeof(JEntry) * 2;
1036 708156 : it->state = JBI_OBJECT_START;
1037 708156 : break;
1038 :
1039 0 : default:
1040 0 : elog(ERROR, "unknown type of jsonb container");
1041 : }
1042 :
1043 785144 : return it;
1044 : }
1045 :
1046 : /*
1047 : * JsonbIteratorNext() worker: Return parent, while freeing memory for current
1048 : * iterator
1049 : */
1050 : static JsonbIterator *
1051 227466 : freeAndGetParent(JsonbIterator *it)
1052 : {
1053 227466 : JsonbIterator *v = it->parent;
1054 :
1055 227466 : pfree(it);
1056 227466 : return v;
1057 : }
1058 :
1059 : /*
1060 : * Worker for "contains" operator's function
1061 : *
1062 : * Formally speaking, containment is top-down, unordered subtree isomorphism.
1063 : *
1064 : * Takes iterators that belong to some container type. These iterators
1065 : * "belong" to those values in the sense that they've just been initialized in
1066 : * respect of them by the caller (perhaps in a nested fashion).
1067 : *
1068 : * "val" is lhs Jsonb, and mContained is rhs Jsonb when called from top level.
1069 : * We determine if mContained is contained within val.
1070 : */
1071 : bool
1072 43620 : JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
1073 : {
1074 : JsonbValue vval,
1075 : vcontained;
1076 : JsonbIteratorToken rval,
1077 : rcont;
1078 :
1079 : /*
1080 : * Guard against stack overflow due to overly complex Jsonb.
1081 : *
1082 : * Functions called here independently take this precaution, but that
1083 : * might not be sufficient since this is also a recursive function.
1084 : */
1085 43620 : check_stack_depth();
1086 :
1087 43620 : rval = JsonbIteratorNext(val, &vval, false);
1088 43620 : rcont = JsonbIteratorNext(mContained, &vcontained, false);
1089 :
1090 43620 : if (rval != rcont)
1091 : {
1092 : /*
1093 : * The differing return values can immediately be taken as indicating
1094 : * two differing container types at this nesting level, which is
1095 : * sufficient reason to give up entirely (but it should be the case
1096 : * that they're both some container type).
1097 : */
1098 : Assert(rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY);
1099 : Assert(rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY);
1100 12 : return false;
1101 : }
1102 43608 : else if (rcont == WJB_BEGIN_OBJECT)
1103 : {
1104 : Assert(vval.type == jbvObject);
1105 : Assert(vcontained.type == jbvObject);
1106 :
1107 : /*
1108 : * If the lhs has fewer pairs than the rhs, it can't possibly contain
1109 : * the rhs. (This conclusion is safe only because we de-duplicate
1110 : * keys in all Jsonb objects; thus there can be no corresponding
1111 : * optimization in the array case.) The case probably won't arise
1112 : * often, but since it's such a cheap check we may as well make it.
1113 : */
1114 43248 : if (vval.val.object.nPairs < vcontained.val.object.nPairs)
1115 3600 : return false;
1116 :
1117 : /* Work through rhs "is it contained within?" object */
1118 : for (;;)
1119 810 : {
1120 : JsonbValue *lhsVal; /* lhsVal is from pair in lhs object */
1121 : JsonbValue lhsValBuf;
1122 :
1123 40458 : rcont = JsonbIteratorNext(mContained, &vcontained, false);
1124 :
1125 : /*
1126 : * When we get through caller's rhs "is it contained within?"
1127 : * object without failing to find one of its values, it's
1128 : * contained.
1129 : */
1130 40458 : if (rcont == WJB_END_OBJECT)
1131 39648 : return true;
1132 :
1133 : Assert(rcont == WJB_KEY);
1134 : Assert(vcontained.type == jbvString);
1135 :
1136 : /* First, find value by key... */
1137 : lhsVal =
1138 27696 : getKeyJsonValueFromContainer((*val)->container,
1139 27696 : vcontained.val.string.val,
1140 : vcontained.val.string.len,
1141 : &lhsValBuf);
1142 27696 : if (!lhsVal)
1143 23436 : return false;
1144 :
1145 : /*
1146 : * ...at this stage it is apparent that there is at least a key
1147 : * match for this rhs pair.
1148 : */
1149 4260 : rcont = JsonbIteratorNext(mContained, &vcontained, true);
1150 :
1151 : Assert(rcont == WJB_VALUE);
1152 :
1153 : /*
1154 : * Compare rhs pair's value with lhs pair's value just found using
1155 : * key
1156 : */
1157 4260 : if (lhsVal->type != vcontained.type)
1158 : {
1159 1170 : return false;
1160 : }
1161 3090 : else if (IsAJsonbScalar(lhsVal))
1162 : {
1163 2958 : if (!equalsJsonbScalarValue(lhsVal, &vcontained))
1164 2244 : return false;
1165 : }
1166 : else
1167 : {
1168 : /* Nested container value (object or array) */
1169 : JsonbIterator *nestval,
1170 : *nestContained;
1171 :
1172 : Assert(lhsVal->type == jbvBinary);
1173 : Assert(vcontained.type == jbvBinary);
1174 :
1175 132 : nestval = JsonbIteratorInit(lhsVal->val.binary.data);
1176 132 : nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1177 :
1178 : /*
1179 : * Match "value" side of rhs datum object's pair recursively.
1180 : * It's a nested structure.
1181 : *
1182 : * Note that nesting still has to "match up" at the right
1183 : * nesting sub-levels. However, there need only be zero or
1184 : * more matching pairs (or elements) at each nesting level
1185 : * (provided the *rhs* pairs/elements *all* match on each
1186 : * level), which enables searching nested structures for a
1187 : * single String or other primitive type sub-datum quite
1188 : * effectively (provided the user constructed the rhs nested
1189 : * structure such that we "know where to look").
1190 : *
1191 : * In other words, the mapping of container nodes in the rhs
1192 : * "vcontained" Jsonb to internal nodes on the lhs is
1193 : * injective, and parent-child edges on the rhs must be mapped
1194 : * to parent-child edges on the lhs to satisfy the condition
1195 : * of containment (plus of course the mapped nodes must be
1196 : * equal).
1197 : */
1198 132 : if (!JsonbDeepContains(&nestval, &nestContained))
1199 36 : return false;
1200 : }
1201 : }
1202 : }
1203 360 : else if (rcont == WJB_BEGIN_ARRAY)
1204 : {
1205 360 : JsonbValue *lhsConts = NULL;
1206 360 : uint32 nLhsElems = vval.val.array.nElems;
1207 :
1208 : Assert(vval.type == jbvArray);
1209 : Assert(vcontained.type == jbvArray);
1210 :
1211 : /*
1212 : * Handle distinction between "raw scalar" pseudo arrays, and real
1213 : * arrays.
1214 : *
1215 : * A raw scalar may contain another raw scalar, and an array may
1216 : * contain a raw scalar, but a raw scalar may not contain an array. We
1217 : * don't do something like this for the object case, since objects can
1218 : * only contain pairs, never raw scalars (a pair is represented by an
1219 : * rhs object argument with a single contained pair).
1220 : */
1221 360 : if (vval.val.array.rawScalar && !vcontained.val.array.rawScalar)
1222 6 : return false;
1223 :
1224 : /* Work through rhs "is it contained within?" array */
1225 : for (;;)
1226 : {
1227 816 : rcont = JsonbIteratorNext(mContained, &vcontained, true);
1228 :
1229 : /*
1230 : * When we get through caller's rhs "is it contained within?"
1231 : * array without failing to find one of its values, it's
1232 : * contained.
1233 : */
1234 816 : if (rcont == WJB_END_ARRAY)
1235 288 : return true;
1236 :
1237 : Assert(rcont == WJB_ELEM);
1238 :
1239 528 : if (IsAJsonbScalar(&vcontained))
1240 : {
1241 402 : if (!findJsonbValueFromContainer((*val)->container,
1242 : JB_FARRAY,
1243 : &vcontained))
1244 54 : return false;
1245 : }
1246 : else
1247 : {
1248 : uint32 i;
1249 :
1250 : /*
1251 : * If this is first container found in rhs array (at this
1252 : * depth), initialize temp lhs array of containers
1253 : */
1254 126 : if (lhsConts == NULL)
1255 : {
1256 120 : uint32 j = 0;
1257 :
1258 : /* Make room for all possible values */
1259 120 : lhsConts = palloc(sizeof(JsonbValue) * nLhsElems);
1260 :
1261 396 : for (i = 0; i < nLhsElems; i++)
1262 : {
1263 : /* Store all lhs elements in temp array */
1264 276 : rcont = JsonbIteratorNext(val, &vval, true);
1265 : Assert(rcont == WJB_ELEM);
1266 :
1267 276 : if (vval.type == jbvBinary)
1268 138 : lhsConts[j++] = vval;
1269 : }
1270 :
1271 : /* No container elements in temp array, so give up now */
1272 120 : if (j == 0)
1273 0 : return false;
1274 :
1275 : /* We may have only partially filled array */
1276 120 : nLhsElems = j;
1277 : }
1278 :
1279 : /* XXX: Nested array containment is O(N^2) */
1280 156 : for (i = 0; i < nLhsElems; i++)
1281 : {
1282 : /* Nested container value (object or array) */
1283 : JsonbIterator *nestval,
1284 : *nestContained;
1285 : bool contains;
1286 :
1287 144 : nestval = JsonbIteratorInit(lhsConts[i].val.binary.data);
1288 144 : nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1289 :
1290 144 : contains = JsonbDeepContains(&nestval, &nestContained);
1291 :
1292 144 : if (nestval)
1293 144 : pfree(nestval);
1294 144 : if (nestContained)
1295 30 : pfree(nestContained);
1296 144 : if (contains)
1297 114 : break;
1298 : }
1299 :
1300 : /*
1301 : * Report rhs container value is not contained if couldn't
1302 : * match rhs container to *some* lhs cont
1303 : */
1304 126 : if (i == nLhsElems)
1305 12 : return false;
1306 : }
1307 : }
1308 : }
1309 : else
1310 : {
1311 0 : elog(ERROR, "invalid jsonb container type");
1312 : }
1313 :
1314 : elog(ERROR, "unexpectedly fell off end of jsonb container");
1315 : return false;
1316 : }
1317 :
1318 : /*
1319 : * Hash a JsonbValue scalar value, mixing the hash value into an existing
1320 : * hash provided by the caller.
1321 : *
1322 : * Some callers may wish to independently XOR in JB_FOBJECT and JB_FARRAY
1323 : * flags.
1324 : */
1325 : void
1326 173798 : JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
1327 : {
1328 : uint32 tmp;
1329 :
1330 : /* Compute hash value for scalarVal */
1331 173798 : switch (scalarVal->type)
1332 : {
1333 96 : case jbvNull:
1334 96 : tmp = 0x01;
1335 96 : break;
1336 127212 : case jbvString:
1337 127212 : tmp = DatumGetUInt32(hash_any((const unsigned char *) scalarVal->val.string.val,
1338 127212 : scalarVal->val.string.len));
1339 127212 : break;
1340 29846 : case jbvNumeric:
1341 : /* Must hash equal numerics to equal hash codes */
1342 29846 : tmp = DatumGetUInt32(DirectFunctionCall1(hash_numeric,
1343 : NumericGetDatum(scalarVal->val.numeric)));
1344 29846 : break;
1345 16644 : case jbvBool:
1346 16644 : tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1347 :
1348 16644 : break;
1349 0 : default:
1350 0 : elog(ERROR, "invalid jsonb scalar type");
1351 : tmp = 0; /* keep compiler quiet */
1352 : break;
1353 : }
1354 :
1355 : /*
1356 : * Combine hash values of successive keys, values and elements by rotating
1357 : * the previous value left 1 bit, then XOR'ing in the new
1358 : * key/value/element's hash value.
1359 : */
1360 173798 : *hash = pg_rotate_left32(*hash, 1);
1361 173798 : *hash ^= tmp;
1362 173798 : }
1363 :
1364 : /*
1365 : * Hash a value to a 64-bit value, with a seed. Otherwise, similar to
1366 : * JsonbHashScalarValue.
1367 : */
1368 : void
1369 216 : JsonbHashScalarValueExtended(const JsonbValue *scalarVal, uint64 *hash,
1370 : uint64 seed)
1371 : {
1372 : uint64 tmp;
1373 :
1374 216 : switch (scalarVal->type)
1375 : {
1376 12 : case jbvNull:
1377 12 : tmp = seed + 0x01;
1378 12 : break;
1379 180 : case jbvString:
1380 180 : tmp = DatumGetUInt64(hash_any_extended((const unsigned char *) scalarVal->val.string.val,
1381 180 : scalarVal->val.string.len,
1382 : seed));
1383 180 : break;
1384 12 : case jbvNumeric:
1385 12 : tmp = DatumGetUInt64(DirectFunctionCall2(hash_numeric_extended,
1386 : NumericGetDatum(scalarVal->val.numeric),
1387 : UInt64GetDatum(seed)));
1388 12 : break;
1389 12 : case jbvBool:
1390 12 : if (seed)
1391 6 : tmp = DatumGetUInt64(DirectFunctionCall2(hashcharextended,
1392 : BoolGetDatum(scalarVal->val.boolean),
1393 : UInt64GetDatum(seed)));
1394 : else
1395 6 : tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1396 :
1397 12 : break;
1398 0 : default:
1399 0 : elog(ERROR, "invalid jsonb scalar type");
1400 : break;
1401 : }
1402 :
1403 216 : *hash = ROTATE_HIGH_AND_LOW_32BITS(*hash);
1404 216 : *hash ^= tmp;
1405 216 : }
1406 :
1407 : /*
1408 : * Are two scalar JsonbValues of the same type a and b equal?
1409 : */
1410 : static bool
1411 3666 : equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b)
1412 : {
1413 3666 : if (a->type == b->type)
1414 : {
1415 3666 : switch (a->type)
1416 : {
1417 42 : case jbvNull:
1418 42 : return true;
1419 3048 : case jbvString:
1420 3048 : return lengthCompareJsonbStringValue(a, b) == 0;
1421 522 : case jbvNumeric:
1422 522 : return DatumGetBool(DirectFunctionCall2(numeric_eq,
1423 : PointerGetDatum(a->val.numeric),
1424 : PointerGetDatum(b->val.numeric)));
1425 54 : case jbvBool:
1426 54 : return a->val.boolean == b->val.boolean;
1427 :
1428 0 : default:
1429 0 : elog(ERROR, "invalid jsonb scalar type");
1430 : }
1431 : }
1432 0 : elog(ERROR, "jsonb scalar type mismatch");
1433 : return false;
1434 : }
1435 :
1436 : /*
1437 : * Compare two scalar JsonbValues, returning -1, 0, or 1.
1438 : *
1439 : * Strings are compared using the default collation. Used by B-tree
1440 : * operators, where a lexical sort order is generally expected.
1441 : */
1442 : static int
1443 469364 : compareJsonbScalarValue(JsonbValue *a, JsonbValue *b)
1444 : {
1445 469364 : if (a->type == b->type)
1446 : {
1447 469364 : switch (a->type)
1448 : {
1449 22 : case jbvNull:
1450 22 : return 0;
1451 319718 : case jbvString:
1452 319718 : return varstr_cmp(a->val.string.val,
1453 : a->val.string.len,
1454 319718 : b->val.string.val,
1455 : b->val.string.len,
1456 : DEFAULT_COLLATION_OID);
1457 111018 : case jbvNumeric:
1458 111018 : return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
1459 : PointerGetDatum(a->val.numeric),
1460 : PointerGetDatum(b->val.numeric)));
1461 38606 : case jbvBool:
1462 38606 : if (a->val.boolean == b->val.boolean)
1463 33670 : return 0;
1464 4936 : else if (a->val.boolean > b->val.boolean)
1465 2632 : return 1;
1466 : else
1467 2304 : return -1;
1468 0 : default:
1469 0 : elog(ERROR, "invalid jsonb scalar type");
1470 : }
1471 : }
1472 0 : elog(ERROR, "jsonb scalar type mismatch");
1473 : return -1;
1474 : }
1475 :
1476 :
1477 : /*
1478 : * Functions for manipulating the resizable buffer used by convertJsonb and
1479 : * its subroutines.
1480 : */
1481 :
1482 : /*
1483 : * Reserve 'len' bytes, at the end of the buffer, enlarging it if necessary.
1484 : * Returns the offset to the reserved area. The caller is expected to fill
1485 : * the reserved area later with copyToBuffer().
1486 : */
1487 : static int
1488 707390 : reserveFromBuffer(StringInfo buffer, int len)
1489 : {
1490 : int offset;
1491 :
1492 : /* Make more room if needed */
1493 707390 : enlargeStringInfo(buffer, len);
1494 :
1495 : /* remember current offset */
1496 707390 : offset = buffer->len;
1497 :
1498 : /* reserve the space */
1499 707390 : buffer->len += len;
1500 :
1501 : /*
1502 : * Keep a trailing null in place, even though it's not useful for us; it
1503 : * seems best to preserve the invariants of StringInfos.
1504 : */
1505 707390 : buffer->data[buffer->len] = '\0';
1506 :
1507 707390 : return offset;
1508 : }
1509 :
1510 : /*
1511 : * Copy 'len' bytes to a previously reserved area in buffer.
1512 : */
1513 : static void
1514 568200 : copyToBuffer(StringInfo buffer, int offset, const void *data, int len)
1515 : {
1516 568200 : memcpy(buffer->data + offset, data, len);
1517 568200 : }
1518 :
1519 : /*
1520 : * A shorthand for reserveFromBuffer + copyToBuffer.
1521 : */
1522 : static void
1523 318172 : appendToBuffer(StringInfo buffer, const void *data, int len)
1524 : {
1525 : int offset;
1526 :
1527 318172 : offset = reserveFromBuffer(buffer, len);
1528 318172 : copyToBuffer(buffer, offset, data, len);
1529 318172 : }
1530 :
1531 :
1532 : /*
1533 : * Append padding, so that the length of the StringInfo is int-aligned.
1534 : * Returns the number of padding bytes appended.
1535 : */
1536 : static short
1537 177380 : padBufferToInt(StringInfo buffer)
1538 : {
1539 : int padlen,
1540 : p,
1541 : offset;
1542 :
1543 177380 : padlen = INTALIGN(buffer->len) - buffer->len;
1544 :
1545 177380 : offset = reserveFromBuffer(buffer, padlen);
1546 :
1547 : /* padlen must be small, so this is probably faster than a memset */
1548 233294 : for (p = 0; p < padlen; p++)
1549 55914 : buffer->data[offset + p] = '\0';
1550 :
1551 177380 : return padlen;
1552 : }
1553 :
1554 : /*
1555 : * Given a JsonbValue, convert to Jsonb. The result is palloc'd.
1556 : */
1557 : static Jsonb *
1558 98564 : convertToJsonb(JsonbValue *val)
1559 : {
1560 : StringInfoData buffer;
1561 : JEntry jentry;
1562 : Jsonb *res;
1563 :
1564 : /* Should not already have binary representation */
1565 : Assert(val->type != jbvBinary);
1566 :
1567 : /* Allocate an output buffer. It will be enlarged as needed */
1568 98564 : initStringInfo(&buffer);
1569 :
1570 : /* Make room for the varlena header */
1571 98564 : reserveFromBuffer(&buffer, VARHDRSZ);
1572 :
1573 98564 : convertJsonbValue(&buffer, &jentry, val, 0);
1574 :
1575 : /*
1576 : * Note: the JEntry of the root is discarded. Therefore the root
1577 : * JsonbContainer struct must contain enough information to tell what kind
1578 : * of value it is.
1579 : */
1580 :
1581 98564 : res = (Jsonb *) buffer.data;
1582 :
1583 98564 : SET_VARSIZE(res, buffer.len);
1584 :
1585 98564 : return res;
1586 : }
1587 :
1588 : /*
1589 : * Subroutine of convertJsonb: serialize a single JsonbValue into buffer.
1590 : *
1591 : * The JEntry header for this node is returned in *header. It is filled in
1592 : * with the length of this value and appropriate type bits. If we wish to
1593 : * store an end offset rather than a length, it is the caller's responsibility
1594 : * to adjust for that.
1595 : *
1596 : * If the value is an array or an object, this recurses. 'level' is only used
1597 : * for debugging purposes.
1598 : */
1599 : static void
1600 276574 : convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
1601 : {
1602 276574 : check_stack_depth();
1603 :
1604 276574 : if (!val)
1605 0 : return;
1606 :
1607 : /*
1608 : * A JsonbValue passed as val should never have a type of jbvBinary, and
1609 : * neither should any of its sub-components. Those values will be produced
1610 : * by convertJsonbArray and convertJsonbObject, the results of which will
1611 : * not be passed back to this function as an argument.
1612 : */
1613 :
1614 276574 : if (IsAJsonbScalar(val))
1615 163300 : convertJsonbScalar(buffer, header, val);
1616 113274 : else if (val->type == jbvArray)
1617 88654 : convertJsonbArray(buffer, header, val, level);
1618 24620 : else if (val->type == jbvObject)
1619 24620 : convertJsonbObject(buffer, header, val, level);
1620 : else
1621 0 : elog(ERROR, "unknown type of jsonb container to convert");
1622 : }
1623 :
1624 : static void
1625 88654 : convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
1626 : {
1627 : int base_offset;
1628 : int jentry_offset;
1629 : int i;
1630 : int totallen;
1631 : uint32 containerhead;
1632 88654 : int nElems = val->val.array.nElems;
1633 :
1634 : /* Remember where in the buffer this array starts. */
1635 88654 : base_offset = buffer->len;
1636 :
1637 : /* Align to 4-byte boundary (any padding counts as part of my data) */
1638 88654 : padBufferToInt(buffer);
1639 :
1640 : /*
1641 : * Construct the header Jentry and store it in the beginning of the
1642 : * variable-length payload.
1643 : */
1644 88654 : containerhead = nElems | JB_FARRAY;
1645 88654 : if (val->val.array.rawScalar)
1646 : {
1647 : Assert(nElems == 1);
1648 : Assert(level == 0);
1649 75264 : containerhead |= JB_FSCALAR;
1650 : }
1651 :
1652 88654 : appendToBuffer(buffer, &containerhead, sizeof(uint32));
1653 :
1654 : /* Reserve space for the JEntries of the elements. */
1655 88654 : jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nElems);
1656 :
1657 88654 : totallen = 0;
1658 194646 : for (i = 0; i < nElems; i++)
1659 : {
1660 105992 : JsonbValue *elem = &val->val.array.elems[i];
1661 : int len;
1662 : JEntry meta;
1663 :
1664 : /*
1665 : * Convert element, producing a JEntry and appending its
1666 : * variable-length data to buffer
1667 : */
1668 105992 : convertJsonbValue(buffer, &meta, elem, level + 1);
1669 :
1670 105992 : len = JBE_OFFLENFLD(meta);
1671 105992 : totallen += len;
1672 :
1673 : /*
1674 : * Bail out if total variable-length data exceeds what will fit in a
1675 : * JEntry length field. We check this in each iteration, not just
1676 : * once at the end, to forestall possible integer overflow.
1677 : */
1678 105992 : if (totallen > JENTRY_OFFLENMASK)
1679 0 : ereport(ERROR,
1680 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1681 : errmsg("total size of jsonb array elements exceeds the maximum of %d bytes",
1682 : JENTRY_OFFLENMASK)));
1683 :
1684 : /*
1685 : * Convert each JB_OFFSET_STRIDE'th length to an offset.
1686 : */
1687 105992 : if ((i % JB_OFFSET_STRIDE) == 0)
1688 86960 : meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1689 :
1690 105992 : copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1691 105992 : jentry_offset += sizeof(JEntry);
1692 : }
1693 :
1694 : /* Total data size is everything we've appended to buffer */
1695 88654 : totallen = buffer->len - base_offset;
1696 :
1697 : /* Check length again, since we didn't include the metadata above */
1698 88654 : if (totallen > JENTRY_OFFLENMASK)
1699 0 : ereport(ERROR,
1700 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1701 : errmsg("total size of jsonb array elements exceeds the maximum of %d bytes",
1702 : JENTRY_OFFLENMASK)));
1703 :
1704 : /* Initialize the header of this node in the container's JEntry array */
1705 88654 : *header = JENTRY_ISCONTAINER | totallen;
1706 88654 : }
1707 :
1708 : static void
1709 24620 : convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
1710 : {
1711 : int base_offset;
1712 : int jentry_offset;
1713 : int i;
1714 : int totallen;
1715 : uint32 containerheader;
1716 24620 : int nPairs = val->val.object.nPairs;
1717 :
1718 : /* Remember where in the buffer this object starts. */
1719 24620 : base_offset = buffer->len;
1720 :
1721 : /* Align to 4-byte boundary (any padding counts as part of my data) */
1722 24620 : padBufferToInt(buffer);
1723 :
1724 : /*
1725 : * Construct the header Jentry and store it in the beginning of the
1726 : * variable-length payload.
1727 : */
1728 24620 : containerheader = nPairs | JB_FOBJECT;
1729 24620 : appendToBuffer(buffer, &containerheader, sizeof(uint32));
1730 :
1731 : /* Reserve space for the JEntries of the keys and values. */
1732 24620 : jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nPairs * 2);
1733 :
1734 : /*
1735 : * Iterate over the keys, then over the values, since that is the ordering
1736 : * we want in the on-disk representation.
1737 : */
1738 24620 : totallen = 0;
1739 96638 : for (i = 0; i < nPairs; i++)
1740 : {
1741 72018 : JsonbPair *pair = &val->val.object.pairs[i];
1742 : int len;
1743 : JEntry meta;
1744 :
1745 : /*
1746 : * Convert key, producing a JEntry and appending its variable-length
1747 : * data to buffer
1748 : */
1749 72018 : convertJsonbScalar(buffer, &meta, &pair->key);
1750 :
1751 72018 : len = JBE_OFFLENFLD(meta);
1752 72018 : totallen += len;
1753 :
1754 : /*
1755 : * Bail out if total variable-length data exceeds what will fit in a
1756 : * JEntry length field. We check this in each iteration, not just
1757 : * once at the end, to forestall possible integer overflow.
1758 : */
1759 72018 : if (totallen > JENTRY_OFFLENMASK)
1760 0 : ereport(ERROR,
1761 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1762 : errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1763 : JENTRY_OFFLENMASK)));
1764 :
1765 : /*
1766 : * Convert each JB_OFFSET_STRIDE'th length to an offset.
1767 : */
1768 72018 : if ((i % JB_OFFSET_STRIDE) == 0)
1769 21790 : meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1770 :
1771 72018 : copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1772 72018 : jentry_offset += sizeof(JEntry);
1773 : }
1774 96638 : for (i = 0; i < nPairs; i++)
1775 : {
1776 72018 : JsonbPair *pair = &val->val.object.pairs[i];
1777 : int len;
1778 : JEntry meta;
1779 :
1780 : /*
1781 : * Convert value, producing a JEntry and appending its variable-length
1782 : * data to buffer
1783 : */
1784 72018 : convertJsonbValue(buffer, &meta, &pair->value, level + 1);
1785 :
1786 72018 : len = JBE_OFFLENFLD(meta);
1787 72018 : totallen += len;
1788 :
1789 : /*
1790 : * Bail out if total variable-length data exceeds what will fit in a
1791 : * JEntry length field. We check this in each iteration, not just
1792 : * once at the end, to forestall possible integer overflow.
1793 : */
1794 72018 : if (totallen > JENTRY_OFFLENMASK)
1795 0 : ereport(ERROR,
1796 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1797 : errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1798 : JENTRY_OFFLENMASK)));
1799 :
1800 : /*
1801 : * Convert each JB_OFFSET_STRIDE'th length to an offset.
1802 : */
1803 72018 : if (((i + nPairs) % JB_OFFSET_STRIDE) == 0)
1804 138 : meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1805 :
1806 72018 : copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1807 72018 : jentry_offset += sizeof(JEntry);
1808 : }
1809 :
1810 : /* Total data size is everything we've appended to buffer */
1811 24620 : totallen = buffer->len - base_offset;
1812 :
1813 : /* Check length again, since we didn't include the metadata above */
1814 24620 : if (totallen > JENTRY_OFFLENMASK)
1815 0 : ereport(ERROR,
1816 : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1817 : errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1818 : JENTRY_OFFLENMASK)));
1819 :
1820 : /* Initialize the header of this node in the container's JEntry array */
1821 24620 : *header = JENTRY_ISCONTAINER | totallen;
1822 24620 : }
1823 :
1824 : static void
1825 235318 : convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal)
1826 : {
1827 : int numlen;
1828 : short padlen;
1829 :
1830 235318 : switch (scalarVal->type)
1831 : {
1832 3764 : case jbvNull:
1833 3764 : *header = JENTRY_ISNULL;
1834 3764 : break;
1835 :
1836 139256 : case jbvString:
1837 139256 : appendToBuffer(buffer, scalarVal->val.string.val, scalarVal->val.string.len);
1838 :
1839 139256 : *header = scalarVal->val.string.len;
1840 139256 : break;
1841 :
1842 64106 : case jbvNumeric:
1843 64106 : numlen = VARSIZE_ANY(scalarVal->val.numeric);
1844 64106 : padlen = padBufferToInt(buffer);
1845 :
1846 64106 : appendToBuffer(buffer, scalarVal->val.numeric, numlen);
1847 :
1848 64106 : *header = JENTRY_ISNUMERIC | (padlen + numlen);
1849 64106 : break;
1850 :
1851 26656 : case jbvBool:
1852 53312 : *header = (scalarVal->val.boolean) ?
1853 26656 : JENTRY_ISBOOL_TRUE : JENTRY_ISBOOL_FALSE;
1854 26656 : break;
1855 :
1856 1536 : case jbvDatetime:
1857 : {
1858 : char buf[MAXDATELEN + 1];
1859 : size_t len;
1860 :
1861 1536 : JsonEncodeDateTime(buf,
1862 : scalarVal->val.datetime.value,
1863 : scalarVal->val.datetime.typid,
1864 1536 : &scalarVal->val.datetime.tz);
1865 1536 : len = strlen(buf);
1866 1536 : appendToBuffer(buffer, buf, len);
1867 :
1868 1536 : *header = len;
1869 : }
1870 1536 : break;
1871 :
1872 0 : default:
1873 0 : elog(ERROR, "invalid jsonb scalar type");
1874 : }
1875 235318 : }
1876 :
1877 : /*
1878 : * Compare two jbvString JsonbValue values, a and b.
1879 : *
1880 : * This is a special qsort() comparator used to sort strings in certain
1881 : * internal contexts where it is sufficient to have a well-defined sort order.
1882 : * In particular, object pair keys are sorted according to this criteria to
1883 : * facilitate cheap binary searches where we don't care about lexical sort
1884 : * order.
1885 : *
1886 : * a and b are first sorted based on their length. If a tie-breaker is
1887 : * required, only then do we consider string binary equality.
1888 : */
1889 : static int
1890 94356 : lengthCompareJsonbStringValue(const void *a, const void *b)
1891 : {
1892 94356 : const JsonbValue *va = (const JsonbValue *) a;
1893 94356 : const JsonbValue *vb = (const JsonbValue *) b;
1894 :
1895 : Assert(va->type == jbvString);
1896 : Assert(vb->type == jbvString);
1897 :
1898 188712 : return lengthCompareJsonbString(va->val.string.val, va->val.string.len,
1899 94356 : vb->val.string.val, vb->val.string.len);
1900 : }
1901 :
1902 : /*
1903 : * Subroutine for lengthCompareJsonbStringValue
1904 : *
1905 : * This is also useful separately to implement binary search on
1906 : * JsonbContainers.
1907 : */
1908 : static int
1909 698584 : lengthCompareJsonbString(const char *val1, int len1, const char *val2, int len2)
1910 : {
1911 698584 : if (len1 == len2)
1912 219786 : return memcmp(val1, val2, len1);
1913 : else
1914 478798 : return len1 > len2 ? 1 : -1;
1915 : }
1916 :
1917 : /*
1918 : * qsort_arg() comparator to compare JsonbPair values.
1919 : *
1920 : * Third argument 'binequal' may point to a bool. If it's set, *binequal is set
1921 : * to true iff a and b have full binary equality, since some callers have an
1922 : * interest in whether the two values are equal or merely equivalent.
1923 : *
1924 : * N.B: String comparisons here are "length-wise"
1925 : *
1926 : * Pairs with equals keys are ordered such that the order field is respected.
1927 : */
1928 : static int
1929 91008 : lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
1930 : {
1931 91008 : const JsonbPair *pa = (const JsonbPair *) a;
1932 91008 : const JsonbPair *pb = (const JsonbPair *) b;
1933 : int res;
1934 :
1935 91008 : res = lengthCompareJsonbStringValue(&pa->key, &pb->key);
1936 91008 : if (res == 0 && binequal)
1937 174 : *((bool *) binequal) = true;
1938 :
1939 : /*
1940 : * Guarantee keeping order of equal pair. Unique algorithm will prefer
1941 : * first element as value.
1942 : */
1943 91008 : if (res == 0)
1944 174 : res = (pa->order > pb->order) ? -1 : 1;
1945 :
1946 91008 : return res;
1947 : }
1948 :
1949 : /*
1950 : * Sort and unique-ify pairs in JsonbValue object
1951 : */
1952 : static void
1953 24656 : uniqueifyJsonbObject(JsonbValue *object, bool unique_keys, bool skip_nulls)
1954 : {
1955 24656 : bool hasNonUniq = false;
1956 :
1957 : Assert(object->type == jbvObject);
1958 :
1959 24656 : if (object->val.object.nPairs > 1)
1960 14006 : qsort_arg(object->val.object.pairs, object->val.object.nPairs, sizeof(JsonbPair),
1961 : lengthCompareJsonbPair, &hasNonUniq);
1962 :
1963 24656 : if (hasNonUniq && unique_keys)
1964 30 : ereport(ERROR,
1965 : errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1966 : errmsg("duplicate JSON object key value"));
1967 :
1968 24626 : if (hasNonUniq || skip_nulls)
1969 : {
1970 : JsonbPair *ptr,
1971 : *res;
1972 :
1973 166 : while (skip_nulls && object->val.object.nPairs > 0 &&
1974 34 : object->val.object.pairs->value.type == jbvNull)
1975 : {
1976 : /* If skip_nulls is true, remove leading items with null */
1977 6 : object->val.object.pairs++;
1978 6 : object->val.object.nPairs--;
1979 : }
1980 :
1981 160 : if (object->val.object.nPairs > 0)
1982 : {
1983 160 : ptr = object->val.object.pairs + 1;
1984 160 : res = object->val.object.pairs;
1985 :
1986 460 : while (ptr - object->val.object.pairs < object->val.object.nPairs)
1987 : {
1988 : /* Avoid copying over duplicate or null */
1989 300 : if (lengthCompareJsonbStringValue(ptr, res) != 0 &&
1990 156 : (!skip_nulls || ptr->value.type != jbvNull))
1991 : {
1992 126 : res++;
1993 126 : if (ptr != res)
1994 108 : memcpy(res, ptr, sizeof(JsonbPair));
1995 : }
1996 300 : ptr++;
1997 : }
1998 :
1999 160 : object->val.object.nPairs = res + 1 - object->val.object.pairs;
2000 : }
2001 : }
2002 24626 : }
|