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