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