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