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