PostgreSQL Source Code git master
jsonb_util.c
Go to the documentation of this file.
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
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
42static void fillJsonbValue(JsonbContainer *container, int index,
43 char *base_addr, uint32 offset,
44 JsonbValue *result);
48static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
49static void convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
50static void convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
51static void convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal);
52
53static int reserveFromBuffer(StringInfo buffer, int len);
54static void appendToBuffer(StringInfo buffer, const void *data, int len);
55static void copyToBuffer(StringInfo buffer, int offset, const void *data, int len);
56static short padBufferToInt(StringInfo buffer);
57
61static void appendKey(JsonbInState *pstate, JsonbValue *string, bool needCopy);
62static void appendValue(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy);
63static void appendElement(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy);
64static void copyScalarSubstructure(JsonbValue *v, MemoryContext outcontext);
65static int lengthCompareJsonbStringValue(const void *a, const void *b);
66static int lengthCompareJsonbString(const char *val1, int len1,
67 const char *val2, int len2);
68static int lengthCompareJsonbPair(const void *a, const void *b, void *binequal);
69static void uniqueifyJsonbObject(JsonbValue *object, bool unique_keys,
70 bool skip_nulls);
71static void pushJsonbValueScalar(JsonbInState *pstate,
73 JsonbValue *scalarVal);
74
75void
77{
78 val->type = jbvBinary;
79 val->val.binary.data = &jsonb->root;
80 val->val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
81}
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 */
95Jsonb *
97{
98 Jsonb *out;
99
100 if (IsAJsonbScalar(val))
101 {
102 /* Scalar value, so wrap it in an array */
103 JsonbInState pstate = {0};
104 JsonbValue scalarArray;
105
106 scalarArray.type = jbvArray;
107 scalarArray.val.array.rawScalar = true;
108 scalarArray.val.array.nElems = 1;
109
110 pushJsonbValue(&pstate, WJB_BEGIN_ARRAY, &scalarArray);
111 pushJsonbValue(&pstate, WJB_ELEM, val);
112 pushJsonbValue(&pstate, WJB_END_ARRAY, NULL);
113
114 out = convertToJsonb(pstate.result);
115 }
116 else if (val->type == jbvObject || val->type == jbvArray)
117 {
118 out = convertToJsonb(val);
119 }
120 else
121 {
122 Assert(val->type == jbvBinary);
123 out = palloc(VARHDRSZ + val->val.binary.len);
124 SET_VARSIZE(out, VARHDRSZ + val->val.binary.len);
125 memcpy(VARDATA(out), val->val.binary.data, val->val.binary.len);
126 }
127
128 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 */
136uint32
138{
139 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 for (i = index - 1; i >= 0; i--)
148 {
149 offset += JBE_OFFLENFLD(jc->children[i]);
150 if (JBE_HAS_OFF(jc->children[i]))
151 break;
152 }
153
154 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 */
161uint32
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 if (JBE_HAS_OFF(jc->children[index]))
173 {
174 off = getJsonbOffset(jc, index);
175 len = JBE_OFFLENFLD(jc->children[index]) - off;
176 }
177 else
179
180 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 */
193int
195{
196 JsonbIterator *ita,
197 *itb;
198 int res = 0;
199
200 ita = JsonbIteratorInit(a);
201 itb = JsonbIteratorInit(b);
202
203 do
204 {
205 JsonbValue va,
206 vb;
208 rb;
209
210 ra = JsonbIteratorNext(&ita, &va, false);
211 rb = JsonbIteratorNext(&itb, &vb, false);
212
213 if (ra == rb)
214 {
215 if (ra == WJB_DONE)
216 {
217 /* Decisively equal */
218 break;
219 }
220
221 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 continue;
230 }
231
232 if (va.type == vb.type)
233 {
234 switch (va.type)
235 {
236 case jbvString:
237 case jbvNull:
238 case jbvNumeric:
239 case jbvBool:
240 res = compareJsonbScalarValue(&va, &vb);
241 break;
242 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 if (va.val.array.rawScalar != vb.val.array.rawScalar)
251 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 if (va.val.array.nElems != vb.val.array.nElems)
260 res = (va.val.array.nElems > vb.val.array.nElems) ? 1 : -1;
261 break;
262 case jbvObject:
263 if (va.val.object.nPairs != vb.val.object.nPairs)
264 res = (va.val.object.nPairs > vb.val.object.nPairs) ? 1 : -1;
265 break;
266 case jbvBinary:
267 elog(ERROR, "unexpected jbvBinary value");
268 break;
269 case jbvDatetime:
270 elog(ERROR, "unexpected jbvDatetime value");
271 break;
272 }
273 }
274 else
275 {
276 /* Type-defined order */
277 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 res = (va.type > vb.type) ? 1 : -1;
299 }
300 }
301 while (res == 0);
302
303 while (ita != NULL)
304 {
305 JsonbIterator *i = ita->parent;
306
307 pfree(ita);
308 ita = i;
309 }
310 while (itb != NULL)
311 {
312 JsonbIterator *i = itb->parent;
313
314 pfree(itb);
315 itb = i;
316 }
317
318 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 */
350{
351 JEntry *children = container->children;
352 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 if (count <= 0)
358 return NULL;
359
360 if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
361 {
363 char *base_addr = (char *) (children + count);
364 uint32 offset = 0;
365 int i;
366
367 for (i = 0; i < count; i++)
368 {
369 fillJsonbValue(container, i, base_addr, offset, result);
370
371 if (key->type == result->type)
372 {
373 if (equalsJsonbScalarValue(key, result))
374 return result;
375 }
376
377 JBE_ADVANCE_OFFSET(offset, children[i]);
378 }
379
380 pfree(result);
381 }
382 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 return getKeyJsonValueFromContainer(container, key->val.string.val,
388 key->val.string.len, NULL);
389 }
390
391 /* Not found */
392 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 */
403 const char *keyVal, int keyLen, JsonbValue *res)
404{
405 JEntry *children = container->children;
406 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 if (count <= 0)
415 return NULL;
416
417 /*
418 * Binary search the container. Since we know this is an object, account
419 * for *Pairs* of Jentrys
420 */
421 baseAddr = (char *) (children + count * 2);
422 stopLow = 0;
423 stopHigh = count;
424 while (stopLow < stopHigh)
425 {
426 uint32 stopMiddle;
427 int difference;
428 const char *candidateVal;
429 int candidateLen;
430
431 stopMiddle = stopLow + (stopHigh - stopLow) / 2;
432
433 candidateVal = baseAddr + getJsonbOffset(container, stopMiddle);
434 candidateLen = getJsonbLength(container, stopMiddle);
435
436 difference = lengthCompareJsonbString(candidateVal, candidateLen,
437 keyVal, keyLen);
438
439 if (difference == 0)
440 {
441 /* Found our key, return corresponding value */
442 int index = stopMiddle + count;
443
444 if (!res)
446
447 fillJsonbValue(container, index, baseAddr,
448 getJsonbOffset(container, index),
449 res);
450
451 return res;
452 }
453 else
454 {
455 if (difference < 0)
456 stopLow = stopMiddle + 1;
457 else
458 stopHigh = stopMiddle;
459 }
460 }
461
462 /* Not found */
463 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 */
473{
474 JsonbValue *result;
475 char *base_addr;
476 uint32 nelements;
477
478 if (!JsonContainerIsArray(container))
479 elog(ERROR, "not a jsonb array");
480
481 nelements = JsonContainerSize(container);
482 base_addr = (char *) &container->children[nelements];
483
484 if (i >= nelements)
485 return NULL;
486
487 result = palloc_object(JsonbValue);
488
489 fillJsonbValue(container, i, base_addr,
490 getJsonbOffset(container, i),
491 result);
492
493 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 */
508static void
510 char *base_addr, uint32 offset,
511 JsonbValue *result)
512{
513 JEntry entry = container->children[index];
514
515 if (JBE_ISNULL(entry))
516 {
517 result->type = jbvNull;
518 }
519 else if (JBE_ISSTRING(entry))
520 {
521 result->type = jbvString;
522 result->val.string.val = base_addr + offset;
523 result->val.string.len = getJsonbLength(container, index);
524 Assert(result->val.string.len >= 0);
525 }
526 else if (JBE_ISNUMERIC(entry))
527 {
528 result->type = jbvNumeric;
529 result->val.numeric = (Numeric) (base_addr + INTALIGN(offset));
530 }
531 else if (JBE_ISBOOL_TRUE(entry))
532 {
533 result->type = jbvBool;
534 result->val.boolean = true;
535 }
536 else if (JBE_ISBOOL_FALSE(entry))
537 {
538 result->type = jbvBool;
539 result->val.boolean = false;
540 }
541 else
542 {
543 Assert(JBE_ISCONTAINER(entry));
544 result->type = jbvBinary;
545 /* Remove alignment padding from data pointer and length */
546 result->val.binary.data = (JsonbContainer *) (base_addr + INTALIGN(offset));
547 result->val.binary.len = getJsonbLength(container, index) -
548 (INTALIGN(offset) - offset);
549 }
550}
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 */
582void
584 JsonbValue *jbval)
585{
586 JsonbIterator *it;
587 JsonbValue v;
589 int i;
590
591 /*
592 * pushJsonbValueScalar handles all cases not involving pushing a
593 * container object as an ELEM or VALUE.
594 */
595 if (!jbval || IsAJsonbScalar(jbval) ||
596 (seq != WJB_ELEM && seq != WJB_VALUE))
597 {
598 pushJsonbValueScalar(pstate, seq, jbval);
599 return;
600 }
601
602 /* If an object or array is pushed, recursively push its contents */
603 if (jbval->type == jbvObject)
604 {
605 pushJsonbValue(pstate, WJB_BEGIN_OBJECT, NULL);
606 for (i = 0; i < jbval->val.object.nPairs; i++)
607 {
608 pushJsonbValue(pstate, WJB_KEY, &jbval->val.object.pairs[i].key);
609 pushJsonbValue(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value);
610 }
611 pushJsonbValue(pstate, WJB_END_OBJECT, NULL);
612 return;
613 }
614
615 if (jbval->type == jbvArray)
616 {
617 pushJsonbValue(pstate, WJB_BEGIN_ARRAY, NULL);
618 for (i = 0; i < jbval->val.array.nElems; i++)
619 {
620 pushJsonbValue(pstate, WJB_ELEM, &jbval->val.array.elems[i]);
621 }
622 pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
623 return;
624 }
625
626 /* Else it must be a jbvBinary value; push its contents */
627 Assert(jbval->type == jbvBinary);
628
629 it = JsonbIteratorInit(jbval->val.binary.data);
630
631 /* ... with a special case for pushing a raw scalar */
632 if ((jbval->val.binary.data->header & JB_FSCALAR) &&
633 pstate->parseState != NULL)
634 {
635 tok = JsonbIteratorNext(&it, &v, true);
636 Assert(tok == WJB_BEGIN_ARRAY);
637 Assert(v.type == jbvArray && v.val.array.rawScalar);
638
639 tok = JsonbIteratorNext(&it, &v, true);
640 Assert(tok == WJB_ELEM);
641
642 pushJsonbValueScalar(pstate, seq, &v);
643
644 tok = JsonbIteratorNext(&it, &v, true);
645 Assert(tok == WJB_END_ARRAY);
646 Assert(it == NULL);
647
648 return;
649 }
650
651 while ((tok = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
652 pushJsonbValueScalar(pstate, tok,
653 tok < WJB_BEGIN_ARRAY ||
654 (tok == WJB_BEGIN_ARRAY &&
655 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 */
662static void
664 JsonbValue *scalarVal)
665{
666 JsonbParseState *ppstate;
668 MemoryContext outcontext;
669
670 switch (seq)
671 {
672 case WJB_BEGIN_ARRAY:
673 Assert(!scalarVal || scalarVal->val.array.rawScalar);
674 ppstate = pushState(pstate);
675 val = &ppstate->contVal;
676 val->type = jbvArray;
677 val->val.array.nElems = 0;
678 val->val.array.rawScalar = (scalarVal &&
679 scalarVal->val.array.rawScalar);
680 if (scalarVal && scalarVal->val.array.nElems > 0)
681 {
682 /* Assume that this array is still really a scalar */
683 Assert(scalarVal->type == jbvArray);
684 ppstate->size = scalarVal->val.array.nElems;
685 }
686 else
687 {
688 ppstate->size = 4; /* initial guess at array size */
689 }
690 outcontext = pstate->outcontext ? pstate->outcontext : CurrentMemoryContext;
691 val->val.array.elems = MemoryContextAlloc(outcontext,
692 sizeof(JsonbValue) *
693 ppstate->size);
694 break;
695 case WJB_BEGIN_OBJECT:
696 Assert(!scalarVal);
697 ppstate = pushState(pstate);
698 val = &ppstate->contVal;
699 val->type = jbvObject;
700 val->val.object.nPairs = 0;
701 ppstate->size = 4; /* initial guess at object size */
702 outcontext = pstate->outcontext ? pstate->outcontext : CurrentMemoryContext;
703 val->val.object.pairs = MemoryContextAlloc(outcontext,
704 sizeof(JsonbPair) *
705 ppstate->size);
706 break;
707 case WJB_KEY:
708 Assert(scalarVal->type == jbvString);
709 appendKey(pstate, scalarVal, true);
710 break;
711 case WJB_VALUE:
712 Assert(IsAJsonbScalar(scalarVal));
713 appendValue(pstate, scalarVal, true);
714 break;
715 case WJB_ELEM:
716 Assert(IsAJsonbScalar(scalarVal));
717 appendElement(pstate, scalarVal, true);
718 break;
719 case WJB_END_OBJECT:
720 ppstate = pstate->parseState;
722 ppstate->unique_keys,
723 ppstate->skip_nulls);
724 /* fall through! */
725 case WJB_END_ARRAY:
726 /* Steps here common to WJB_END_OBJECT case */
727 Assert(!scalarVal);
728 ppstate = pstate->parseState;
729 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 pstate->parseState = ppstate = ppstate->next;
737 if (ppstate)
738 {
739 switch (ppstate->contVal.type)
740 {
741 case jbvArray:
742 appendElement(pstate, val, false);
743 break;
744 case jbvObject:
745 appendValue(pstate, val, false);
746 break;
747 default:
748 elog(ERROR, "invalid jsonb container type");
749 }
750 }
751 else
752 pstate->result = val;
753 break;
754 default:
755 elog(ERROR, "unrecognized jsonb sequential processing token");
756 }
757}
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 */
765static JsonbParseState *
767{
768 MemoryContext outcontext = pstate->outcontext ? pstate->outcontext : CurrentMemoryContext;
769 JsonbParseState *ns = MemoryContextAlloc(outcontext,
770 sizeof(JsonbParseState));
771
772 ns->next = pstate->parseState;
773 /* This module never changes these fields, but callers can: */
774 ns->unique_keys = false;
775 ns->skip_nulls = false;
776
777 pstate->parseState = ns;
778 return ns;
779}
780
781/*
782 * pushJsonbValue() worker: Append a pair key to pstate
783 */
784static void
785appendKey(JsonbInState *pstate, JsonbValue *string, bool needCopy)
786{
787 JsonbParseState *ppstate = pstate->parseState;
788 JsonbValue *object = &ppstate->contVal;
789 JsonbPair *pair;
790
791 Assert(object->type == jbvObject);
792 Assert(string->type == jbvString);
793
794 if (object->val.object.nPairs >= ppstate->size)
795 {
796 if (unlikely(object->val.object.nPairs >= JSONB_MAX_PAIRS))
798 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
799 errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
801 ppstate->size = Min(ppstate->size * 2, JSONB_MAX_PAIRS);
802 object->val.object.pairs = repalloc(object->val.object.pairs,
803 sizeof(JsonbPair) * ppstate->size);
804 }
805
806 pair = &object->val.object.pairs[object->val.object.nPairs];
807 pair->key = *string;
808 pair->order = object->val.object.nPairs;
809
810 if (needCopy)
811 copyScalarSubstructure(&pair->key, pstate->outcontext);
812}
813
814/*
815 * pushJsonbValue() worker: Append a pair value to pstate
816 */
817static void
818appendValue(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy)
819{
820 JsonbValue *object = &pstate->parseState->contVal;
821 JsonbPair *pair;
822
823 Assert(object->type == jbvObject);
824
825 pair = &object->val.object.pairs[object->val.object.nPairs];
826 pair->value = *scalarVal;
827 object->val.object.nPairs++;
828
829 if (needCopy)
830 copyScalarSubstructure(&pair->value, pstate->outcontext);
831}
832
833/*
834 * pushJsonbValue() worker: Append an array element to pstate
835 */
836static void
837appendElement(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy)
838{
839 JsonbParseState *ppstate = pstate->parseState;
840 JsonbValue *array = &ppstate->contVal;
841 JsonbValue *elem;
842
843 Assert(array->type == jbvArray);
844
845 if (array->val.array.nElems >= ppstate->size)
846 {
847 if (unlikely(array->val.array.nElems >= JSONB_MAX_ELEMS))
849 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
850 errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
852 ppstate->size = Min(ppstate->size * 2, JSONB_MAX_ELEMS);
853 array->val.array.elems = repalloc(array->val.array.elems,
854 sizeof(JsonbValue) * ppstate->size);
855 }
856
857 elem = &array->val.array.elems[array->val.array.nElems];
858 *elem = *scalarVal;
859 array->val.array.nElems++;
860
861 if (needCopy)
862 copyScalarSubstructure(elem, pstate->outcontext);
863}
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 */
872static void
874{
875 MemoryContext oldcontext;
876
877 /* Nothing to do if caller did not specify an outcontext */
878 if (outcontext == NULL)
879 return;
880 switch (v->type)
881 {
882 case jbvNull:
883 case jbvBool:
884 /* pass-by-value, nothing to do */
885 break;
886 case jbvString:
887 {
888 char *buf = MemoryContextAlloc(outcontext,
889 v->val.string.len);
890
891 memcpy(buf, v->val.string.val, v->val.string.len);
892 v->val.string.val = buf;
893 }
894 break;
895 case jbvNumeric:
896 oldcontext = MemoryContextSwitchTo(outcontext);
897 v->val.numeric =
899 false, -1));
900 MemoryContextSwitchTo(oldcontext);
901 break;
902 case jbvDatetime:
903 switch (v->val.datetime.typid)
904 {
905 case DATEOID:
906 case TIMEOID:
907 case TIMESTAMPOID:
908 case TIMESTAMPTZOID:
909 /* pass-by-value, nothing to do */
910 break;
911 case TIMETZOID:
912 /* pass-by-reference */
913 oldcontext = MemoryContextSwitchTo(outcontext);
914 v->val.datetime.value = datumCopy(v->val.datetime.value,
915 false, TIMETZ_TYPLEN);
916 MemoryContextSwitchTo(oldcontext);
917 break;
918 default:
919 elog(ERROR, "unexpected jsonb datetime type oid %u",
920 v->val.datetime.typid);
921 }
922 break;
923 default:
924 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 */
936{
937 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 */
974{
975 if (*it == NULL)
976 {
977 val->type = jbvNull;
978 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 */
987recurse:
988 switch ((*it)->state)
989 {
990 case JBI_ARRAY_START:
991 /* Set v to array on first array call */
992 val->type = jbvArray;
993 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 val->val.array.rawScalar = (*it)->isScalar;
1000 (*it)->curIndex = 0;
1001 (*it)->curDataOffset = 0;
1002 (*it)->curValueOffset = 0; /* not actually used */
1003 /* Set state for next call */
1004 (*it)->state = JBI_ARRAY_ELEM;
1005 return WJB_BEGIN_ARRAY;
1006
1007 case JBI_ARRAY_ELEM:
1008 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 *it = freeAndGetParent(*it);
1017 val->type = jbvNull;
1018 return WJB_END_ARRAY;
1019 }
1020
1021 fillJsonbValue((*it)->container, (*it)->curIndex,
1022 (*it)->dataProper, (*it)->curDataOffset,
1023 val);
1024
1025 JBE_ADVANCE_OFFSET((*it)->curDataOffset,
1026 (*it)->children[(*it)->curIndex]);
1027 (*it)->curIndex++;
1028
1029 if (!IsAJsonbScalar(val) && !skipNested)
1030 {
1031 /* Recurse into container. */
1032 *it = iteratorFromContainer(val->val.binary.data, *it);
1033 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 return WJB_ELEM;
1042 }
1043
1044 case JBI_OBJECT_START:
1045 /* Set v to object on first object call */
1046 val->type = jbvObject;
1047 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 (*it)->curIndex = 0;
1054 (*it)->curDataOffset = 0;
1055 (*it)->curValueOffset = getJsonbOffset((*it)->container,
1056 (*it)->nElems);
1057 /* Set state for next call */
1058 (*it)->state = JBI_OBJECT_KEY;
1059 return WJB_BEGIN_OBJECT;
1060
1061 case JBI_OBJECT_KEY:
1062 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 *it = freeAndGetParent(*it);
1071 val->type = jbvNull;
1072 return WJB_END_OBJECT;
1073 }
1074 else
1075 {
1076 /* Return key of a key/value pair. */
1077 fillJsonbValue((*it)->container, (*it)->curIndex,
1078 (*it)->dataProper, (*it)->curDataOffset,
1079 val);
1080 if (val->type != jbvString)
1081 elog(ERROR, "unexpected jsonb type as object key");
1082
1083 /* Set state for next call */
1084 (*it)->state = JBI_OBJECT_VALUE;
1085 return WJB_KEY;
1086 }
1087
1088 case JBI_OBJECT_VALUE:
1089 /* Set state for next call */
1090 (*it)->state = JBI_OBJECT_KEY;
1091
1092 fillJsonbValue((*it)->container, (*it)->curIndex + (*it)->nElems,
1093 (*it)->dataProper, (*it)->curValueOffset,
1094 val);
1095
1096 JBE_ADVANCE_OFFSET((*it)->curDataOffset,
1097 (*it)->children[(*it)->curIndex]);
1098 JBE_ADVANCE_OFFSET((*it)->curValueOffset,
1099 (*it)->children[(*it)->curIndex + (*it)->nElems]);
1100 (*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 if (!IsAJsonbScalar(val) && !skipNested)
1108 {
1109 *it = iteratorFromContainer(val->val.binary.data, *it);
1110 goto recurse;
1111 }
1112 else
1113 return WJB_VALUE;
1114 }
1115
1116 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 */
1125static JsonbIterator *
1127{
1128 JsonbIterator *it;
1129
1131 it->container = container;
1132 it->parent = parent;
1133 it->nElems = JsonContainerSize(container);
1134
1135 /* Array starts just after header */
1136 it->children = container->children;
1137
1138 switch (container->header & (JB_FARRAY | JB_FOBJECT))
1139 {
1140 case JB_FARRAY:
1141 it->dataProper =
1142 (char *) it->children + it->nElems * sizeof(JEntry);
1143 it->isScalar = JsonContainerIsScalar(container);
1144 /* This is either a "raw scalar", or an array */
1145 Assert(!it->isScalar || it->nElems == 1);
1146
1147 it->state = JBI_ARRAY_START;
1148 break;
1149
1150 case JB_FOBJECT:
1151 it->dataProper =
1152 (char *) it->children + it->nElems * sizeof(JEntry) * 2;
1153 it->state = JBI_OBJECT_START;
1154 break;
1155
1156 default:
1157 elog(ERROR, "unknown type of jsonb container");
1158 }
1159
1160 return it;
1161}
1162
1163/*
1164 * JsonbIteratorNext() worker: Return parent, while freeing memory for current
1165 * iterator
1166 */
1167static JsonbIterator *
1169{
1170 JsonbIterator *v = it->parent;
1171
1172 pfree(it);
1173 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 */
1188bool
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 */
1203
1204 rval = JsonbIteratorNext(val, &vval, false);
1205 rcont = JsonbIteratorNext(mContained, &vcontained, false);
1206
1207 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 return false;
1218 }
1219 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 if (vval.val.object.nPairs < vcontained.val.object.nPairs)
1232 return false;
1233
1234 /* Work through rhs "is it contained within?" object */
1235 for (;;)
1236 {
1237 JsonbValue *lhsVal; /* lhsVal is from pair in lhs object */
1238 JsonbValue lhsValBuf;
1239
1240 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 if (rcont == WJB_END_OBJECT)
1248 return true;
1249
1250 Assert(rcont == WJB_KEY);
1251 Assert(vcontained.type == jbvString);
1252
1253 /* First, find value by key... */
1254 lhsVal =
1255 getKeyJsonValueFromContainer((*val)->container,
1256 vcontained.val.string.val,
1257 vcontained.val.string.len,
1258 &lhsValBuf);
1259 if (!lhsVal)
1260 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 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 if (lhsVal->type != vcontained.type)
1275 {
1276 return false;
1277 }
1278 else if (IsAJsonbScalar(lhsVal))
1279 {
1280 if (!equalsJsonbScalarValue(lhsVal, &vcontained))
1281 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 nestval = JsonbIteratorInit(lhsVal->val.binary.data);
1293 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 if (!JsonbDeepContains(&nestval, &nestContained))
1316 return false;
1317 }
1318 }
1319 }
1320 else if (rcont == WJB_BEGIN_ARRAY)
1321 {
1322 JsonbValue *lhsConts = NULL;
1323 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 if (vval.val.array.rawScalar && !vcontained.val.array.rawScalar)
1339 return false;
1340
1341 /* Work through rhs "is it contained within?" array */
1342 for (;;)
1343 {
1344 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 if (rcont == WJB_END_ARRAY)
1352 return true;
1353
1354 Assert(rcont == WJB_ELEM);
1355
1356 if (IsAJsonbScalar(&vcontained))
1357 {
1358 if (!findJsonbValueFromContainer((*val)->container,
1359 JB_FARRAY,
1360 &vcontained))
1361 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 if (lhsConts == NULL)
1372 {
1373 uint32 j = 0;
1374
1375 /* Make room for all possible values */
1376 lhsConts = palloc_array(JsonbValue, nLhsElems);
1377
1378 for (i = 0; i < nLhsElems; i++)
1379 {
1380 /* Store all lhs elements in temp array */
1381 rcont = JsonbIteratorNext(val, &vval, true);
1382 Assert(rcont == WJB_ELEM);
1383
1384 if (vval.type == jbvBinary)
1385 lhsConts[j++] = vval;
1386 }
1387
1388 /* No container elements in temp array, so give up now */
1389 if (j == 0)
1390 return false;
1391
1392 /* We may have only partially filled array */
1393 nLhsElems = j;
1394 }
1395
1396 /* XXX: Nested array containment is O(N^2) */
1397 for (i = 0; i < nLhsElems; i++)
1398 {
1399 /* Nested container value (object or array) */
1400 JsonbIterator *nestval,
1401 *nestContained;
1402 bool contains;
1403
1404 nestval = JsonbIteratorInit(lhsConts[i].val.binary.data);
1405 nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1406
1407 contains = JsonbDeepContains(&nestval, &nestContained);
1408
1409 if (nestval)
1410 pfree(nestval);
1411 if (nestContained)
1412 pfree(nestContained);
1413 if (contains)
1414 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 if (i == nLhsElems)
1422 return false;
1423 }
1424 }
1425 }
1426 else
1427 {
1428 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 */
1442void
1444{
1445 uint32 tmp;
1446
1447 /* Compute hash value for scalarVal */
1448 switch (scalarVal->type)
1449 {
1450 case jbvNull:
1451 tmp = 0x01;
1452 break;
1453 case jbvString:
1454 tmp = DatumGetUInt32(hash_any((const unsigned char *) scalarVal->val.string.val,
1455 scalarVal->val.string.len));
1456 break;
1457 case jbvNumeric:
1458 /* Must hash equal numerics to equal hash codes */
1460 NumericGetDatum(scalarVal->val.numeric)));
1461 break;
1462 case jbvBool:
1463 tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1464
1465 break;
1466 default:
1467 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 *hash = pg_rotate_left32(*hash, 1);
1478 *hash ^= tmp;
1479}
1480
1481/*
1482 * Hash a value to a 64-bit value, with a seed. Otherwise, similar to
1483 * JsonbHashScalarValue.
1484 */
1485void
1487 uint64 seed)
1488{
1489 uint64 tmp;
1490
1491 switch (scalarVal->type)
1492 {
1493 case jbvNull:
1494 tmp = seed + 0x01;
1495 break;
1496 case jbvString:
1497 tmp = DatumGetUInt64(hash_any_extended((const unsigned char *) scalarVal->val.string.val,
1498 scalarVal->val.string.len,
1499 seed));
1500 break;
1501 case jbvNumeric:
1503 NumericGetDatum(scalarVal->val.numeric),
1504 UInt64GetDatum(seed)));
1505 break;
1506 case jbvBool:
1507 if (seed)
1509 BoolGetDatum(scalarVal->val.boolean),
1510 UInt64GetDatum(seed)));
1511 else
1512 tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1513
1514 break;
1515 default:
1516 elog(ERROR, "invalid jsonb scalar type");
1517 break;
1518 }
1519
1521 *hash ^= tmp;
1522}
1523
1524/*
1525 * Are two scalar JsonbValues of the same type a and b equal?
1526 */
1527static bool
1529{
1530 if (a->type == b->type)
1531 {
1532 switch (a->type)
1533 {
1534 case jbvNull:
1535 return true;
1536 case jbvString:
1537 return lengthCompareJsonbStringValue(a, b) == 0;
1538 case jbvNumeric:
1540 PointerGetDatum(a->val.numeric),
1541 PointerGetDatum(b->val.numeric)));
1542 case jbvBool:
1543 return a->val.boolean == b->val.boolean;
1544
1545 default:
1546 elog(ERROR, "invalid jsonb scalar type");
1547 }
1548 }
1549 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 */
1559static int
1561{
1562 if (a->type == b->type)
1563 {
1564 switch (a->type)
1565 {
1566 case jbvNull:
1567 return 0;
1568 case jbvString:
1569 return varstr_cmp(a->val.string.val,
1570 a->val.string.len,
1571 b->val.string.val,
1572 b->val.string.len,
1573 DEFAULT_COLLATION_OID);
1574 case jbvNumeric:
1576 PointerGetDatum(a->val.numeric),
1577 PointerGetDatum(b->val.numeric)));
1578 case jbvBool:
1579 if (a->val.boolean == b->val.boolean)
1580 return 0;
1581 else if (a->val.boolean > b->val.boolean)
1582 return 1;
1583 else
1584 return -1;
1585 default:
1586 elog(ERROR, "invalid jsonb scalar type");
1587 }
1588 }
1589 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 */
1604static int
1606{
1607 int offset;
1608
1609 /* Make more room if needed */
1610 enlargeStringInfo(buffer, len);
1611
1612 /* remember current offset */
1613 offset = buffer->len;
1614
1615 /* reserve the space */
1616 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 buffer->data[buffer->len] = '\0';
1623
1624 return offset;
1625}
1626
1627/*
1628 * Copy 'len' bytes to a previously reserved area in buffer.
1629 */
1630static void
1631copyToBuffer(StringInfo buffer, int offset, const void *data, int len)
1632{
1633 memcpy(buffer->data + offset, data, len);
1634}
1635
1636/*
1637 * A shorthand for reserveFromBuffer + copyToBuffer.
1638 */
1639static void
1640appendToBuffer(StringInfo buffer, const void *data, int len)
1641{
1642 int offset;
1643
1644 offset = reserveFromBuffer(buffer, len);
1645 copyToBuffer(buffer, offset, data, len);
1646}
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 */
1653static short
1655{
1656 int padlen,
1657 p,
1658 offset;
1659
1660 padlen = INTALIGN(buffer->len) - buffer->len;
1661
1662 offset = reserveFromBuffer(buffer, padlen);
1663
1664 /* padlen must be small, so this is probably faster than a memset */
1665 for (p = 0; p < padlen; p++)
1666 buffer->data[offset + p] = '\0';
1667
1668 return padlen;
1669}
1670
1671/*
1672 * Given a JsonbValue, convert to Jsonb. The result is palloc'd.
1673 */
1674static Jsonb *
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 initStringInfo(&buffer);
1686
1687 /* Make room for the varlena header */
1688 reserveFromBuffer(&buffer, VARHDRSZ);
1689
1690 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 res = (Jsonb *) buffer.data;
1699
1700 SET_VARSIZE(res, buffer.len);
1701
1702 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 */
1716static void
1717convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
1718{
1720
1721 if (!val)
1722 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 if (IsAJsonbScalar(val))
1732 convertJsonbScalar(buffer, header, val);
1733 else if (val->type == jbvArray)
1734 convertJsonbArray(buffer, header, val, level);
1735 else if (val->type == jbvObject)
1736 convertJsonbObject(buffer, header, val, level);
1737 else
1738 elog(ERROR, "unknown type of jsonb container to convert");
1739}
1740
1741static void
1742convertJsonbArray(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 int nElems = val->val.array.nElems;
1750
1751 /* Remember where in the buffer this array starts. */
1752 base_offset = buffer->len;
1753
1754 /* Align to 4-byte boundary (any padding counts as part of my data) */
1755 padBufferToInt(buffer);
1756
1757 /*
1758 * Construct the header Jentry and store it in the beginning of the
1759 * variable-length payload.
1760 */
1761 containerhead = nElems | JB_FARRAY;
1762 if (val->val.array.rawScalar)
1763 {
1764 Assert(nElems == 1);
1765 Assert(level == 0);
1766 containerhead |= JB_FSCALAR;
1767 }
1768
1769 appendToBuffer(buffer, &containerhead, sizeof(uint32));
1770
1771 /* Reserve space for the JEntries of the elements. */
1772 jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nElems);
1773
1774 totallen = 0;
1775 for (i = 0; i < nElems; i++)
1776 {
1777 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 convertJsonbValue(buffer, &meta, elem, level + 1);
1786
1787 len = JBE_OFFLENFLD(meta);
1788 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 if (totallen > JENTRY_OFFLENMASK)
1796 ereport(ERROR,
1797 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1798 errmsg("total size of jsonb array elements exceeds the maximum of %d bytes",
1800
1801 /*
1802 * Convert each JB_OFFSET_STRIDE'th length to an offset.
1803 */
1804 if ((i % JB_OFFSET_STRIDE) == 0)
1805 meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1806
1807 copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1808 jentry_offset += sizeof(JEntry);
1809 }
1810
1811 /* Total data size is everything we've appended to buffer */
1812 totallen = buffer->len - base_offset;
1813
1814 /* Check length again, since we didn't include the metadata above */
1815 if (totallen > JENTRY_OFFLENMASK)
1816 ereport(ERROR,
1817 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1818 errmsg("total size of jsonb array elements exceeds the maximum of %d bytes",
1820
1821 /* Initialize the header of this node in the container's JEntry array */
1822 *header = JENTRY_ISCONTAINER | totallen;
1823}
1824
1825static void
1827{
1828 int base_offset;
1829 int jentry_offset;
1830 int i;
1831 int totallen;
1832 uint32 containerheader;
1833 int nPairs = val->val.object.nPairs;
1834
1835 /* Remember where in the buffer this object starts. */
1836 base_offset = buffer->len;
1837
1838 /* Align to 4-byte boundary (any padding counts as part of my data) */
1839 padBufferToInt(buffer);
1840
1841 /*
1842 * Construct the header Jentry and store it in the beginning of the
1843 * variable-length payload.
1844 */
1845 containerheader = nPairs | JB_FOBJECT;
1846 appendToBuffer(buffer, &containerheader, sizeof(uint32));
1847
1848 /* Reserve space for the JEntries of the keys and values. */
1849 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 totallen = 0;
1856 for (i = 0; i < nPairs; i++)
1857 {
1858 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 convertJsonbScalar(buffer, &meta, &pair->key);
1867
1868 len = JBE_OFFLENFLD(meta);
1869 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 if (totallen > JENTRY_OFFLENMASK)
1877 ereport(ERROR,
1878 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1879 errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1881
1882 /*
1883 * Convert each JB_OFFSET_STRIDE'th length to an offset.
1884 */
1885 if ((i % JB_OFFSET_STRIDE) == 0)
1886 meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1887
1888 copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1889 jentry_offset += sizeof(JEntry);
1890 }
1891 for (i = 0; i < nPairs; i++)
1892 {
1893 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 convertJsonbValue(buffer, &meta, &pair->value, level + 1);
1902
1903 len = JBE_OFFLENFLD(meta);
1904 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 if (totallen > JENTRY_OFFLENMASK)
1912 ereport(ERROR,
1913 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1914 errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1916
1917 /*
1918 * Convert each JB_OFFSET_STRIDE'th length to an offset.
1919 */
1920 if (((i + nPairs) % JB_OFFSET_STRIDE) == 0)
1921 meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1922
1923 copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1924 jentry_offset += sizeof(JEntry);
1925 }
1926
1927 /* Total data size is everything we've appended to buffer */
1928 totallen = buffer->len - base_offset;
1929
1930 /* Check length again, since we didn't include the metadata above */
1931 if (totallen > JENTRY_OFFLENMASK)
1932 ereport(ERROR,
1933 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1934 errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1936
1937 /* Initialize the header of this node in the container's JEntry array */
1938 *header = JENTRY_ISCONTAINER | totallen;
1939}
1940
1941static void
1943{
1944 int numlen;
1945 short padlen;
1946
1947 switch (scalarVal->type)
1948 {
1949 case jbvNull:
1950 *header = JENTRY_ISNULL;
1951 break;
1952
1953 case jbvString:
1954 appendToBuffer(buffer, scalarVal->val.string.val, scalarVal->val.string.len);
1955
1956 *header = scalarVal->val.string.len;
1957 break;
1958
1959 case jbvNumeric:
1960 numlen = VARSIZE_ANY(scalarVal->val.numeric);
1961 padlen = padBufferToInt(buffer);
1962
1963 appendToBuffer(buffer, scalarVal->val.numeric, numlen);
1964
1965 *header = JENTRY_ISNUMERIC | (padlen + numlen);
1966 break;
1967
1968 case jbvBool:
1969 *header = (scalarVal->val.boolean) ?
1971 break;
1972
1973 case jbvDatetime:
1974 {
1975 char buf[MAXDATELEN + 1];
1976 size_t len;
1977
1979 scalarVal->val.datetime.value,
1980 scalarVal->val.datetime.typid,
1981 &scalarVal->val.datetime.tz);
1982 len = strlen(buf);
1983 appendToBuffer(buffer, buf, len);
1984
1985 *header = len;
1986 }
1987 break;
1988
1989 default:
1990 elog(ERROR, "invalid jsonb scalar type");
1991 }
1992}
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 */
2006static int
2007lengthCompareJsonbStringValue(const void *a, const void *b)
2008{
2009 const JsonbValue *va = (const JsonbValue *) a;
2010 const JsonbValue *vb = (const JsonbValue *) b;
2011
2012 Assert(va->type == jbvString);
2013 Assert(vb->type == jbvString);
2014
2015 return lengthCompareJsonbString(va->val.string.val, va->val.string.len,
2016 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 */
2025static int
2026lengthCompareJsonbString(const char *val1, int len1, const char *val2, int len2)
2027{
2028 if (len1 == len2)
2029 return memcmp(val1, val2, len1);
2030 else
2031 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 */
2045static int
2046lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
2047{
2048 const JsonbPair *pa = (const JsonbPair *) a;
2049 const JsonbPair *pb = (const JsonbPair *) b;
2050 int res;
2051
2052 res = lengthCompareJsonbStringValue(&pa->key, &pb->key);
2053 if (res == 0 && binequal)
2054 *((bool *) binequal) = true;
2055
2056 /*
2057 * Guarantee keeping order of equal pair. Unique algorithm will prefer
2058 * first element as value.
2059 */
2060 if (res == 0)
2061 res = (pa->order > pb->order) ? -1 : 1;
2062
2063 return res;
2064}
2065
2066/*
2067 * Sort and unique-ify pairs in JsonbValue object
2068 */
2069static void
2070uniqueifyJsonbObject(JsonbValue *object, bool unique_keys, bool skip_nulls)
2071{
2072 bool hasNonUniq = false;
2073
2074 Assert(object->type == jbvObject);
2075
2076 if (object->val.object.nPairs > 1)
2077 qsort_arg(object->val.object.pairs, object->val.object.nPairs, sizeof(JsonbPair),
2078 lengthCompareJsonbPair, &hasNonUniq);
2079
2080 if (hasNonUniq && unique_keys)
2081 ereport(ERROR,
2082 errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
2083 errmsg("duplicate JSON object key value"));
2084
2085 if (hasNonUniq || skip_nulls)
2086 {
2087 JsonbPair *ptr,
2088 *res;
2089
2090 while (skip_nulls && object->val.object.nPairs > 0 &&
2091 object->val.object.pairs->value.type == jbvNull)
2092 {
2093 /* If skip_nulls is true, remove leading items with null */
2094 object->val.object.pairs++;
2095 object->val.object.nPairs--;
2096 }
2097
2098 if (object->val.object.nPairs > 0)
2099 {
2100 ptr = object->val.object.pairs + 1;
2101 res = object->val.object.pairs;
2102
2103 while (ptr - object->val.object.pairs < object->val.object.nPairs)
2104 {
2105 /* Avoid copying over duplicate or null */
2106 if (lengthCompareJsonbStringValue(ptr, res) != 0 &&
2107 (!skip_nulls || ptr->value.type != jbvNull))
2108 {
2109 res++;
2110 if (ptr != res)
2111 memcpy(res, ptr, sizeof(JsonbPair));
2112 }
2113 ptr++;
2114 }
2115
2116 object->val.object.nPairs = res + 1 - object->val.object.pairs;
2117 }
2118 }
2119}
Datum hash_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2713
Datum hash_numeric_extended(PG_FUNCTION_ARGS)
Definition: numeric.c:2793
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2415
Datum numeric_eq(PG_FUNCTION_ARGS)
Definition: numeric.c:2431
#define Min(x, y)
Definition: c.h:1016
#define INTALIGN(LEN)
Definition: c.h:821
#define VARHDRSZ
Definition: c.h:711
uint64_t uint64
Definition: c.h:553
#define unlikely(x)
Definition: c.h:418
uint32_t uint32
Definition: c.h:552
#define TIMETZ_TYPLEN
Definition: date.h:39
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
#define palloc_object(type)
Definition: fe_memutils.h:74
#define palloc_array(type, count)
Definition: fe_memutils.h:76
#define palloc0_object(type)
Definition: fe_memutils.h:75
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:684
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
Datum difference(PG_FUNCTION_ARGS)
#define ROTATE_HIGH_AND_LOW_32BITS(v)
Definition: hashfn.h:18
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
Assert(PointerIsAligned(start, uint64))
Datum hashcharextended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:53
#define MAXDATELEN
Definition: datetime.h:200
long val
Definition: informix.c:689
int b
Definition: isn.c:74
int a
Definition: isn.c:73
int j
Definition: isn.c:78
int i
Definition: isn.c:77
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:311
@ jbvObject
Definition: jsonb.h:236
@ jbvNumeric
Definition: jsonb.h:232
@ jbvBool
Definition: jsonb.h:233
@ jbvArray
Definition: jsonb.h:235
@ jbvBinary
Definition: jsonb.h:238
@ jbvNull
Definition: jsonb.h:230
@ jbvDatetime
Definition: jsonb.h:246
@ jbvString
Definition: jsonb.h:231
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:209
#define JBE_ISNULL(je_)
Definition: jsonb.h:158
#define JsonContainerIsArray(jc)
Definition: jsonb.h:211
@ JBI_OBJECT_VALUE
Definition: jsonb.h:365
@ JBI_ARRAY_START
Definition: jsonb.h:361
@ JBI_ARRAY_ELEM
Definition: jsonb.h:362
@ JBI_OBJECT_START
Definition: jsonb.h:363
@ JBI_OBJECT_KEY
Definition: jsonb.h:364
#define JsonContainerSize(jc)
Definition: jsonb.h:208
#define JB_FSCALAR
Definition: jsonb.h:203
#define JB_OFFSET_STRIDE
Definition: jsonb.h:180
#define JENTRY_ISNUMERIC
Definition: jsonb.h:146
#define JBE_ISBOOL_TRUE(je_)
Definition: jsonb.h:159
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:299
#define JENTRY_OFFLENMASK
Definition: jsonb.h:140
#define JBE_ISNUMERIC(je_)
Definition: jsonb.h:156
#define JBE_ISBOOL_FALSE(je_)
Definition: jsonb.h:160
#define JENTRY_ISCONTAINER
Definition: jsonb.h:150
#define JENTRY_TYPEMASK
Definition: jsonb.h:141
#define JBE_HAS_OFF(je_)
Definition: jsonb.h:154
#define JENTRY_ISNULL
Definition: jsonb.h:149
#define JBE_ISSTRING(je_)
Definition: jsonb.h:155
#define JENTRY_ISBOOL_FALSE
Definition: jsonb.h:147
#define JBE_OFFLENFLD(je_)
Definition: jsonb.h:153
#define JsonContainerIsObject(jc)
Definition: jsonb.h:210
#define JENTRY_HAS_OFF
Definition: jsonb.h:142
#define JB_FARRAY
Definition: jsonb.h:205
uint32 JEntry
Definition: jsonb.h:138
JsonbIteratorToken
Definition: jsonb.h:21
@ WJB_KEY
Definition: jsonb.h:23
@ WJB_DONE
Definition: jsonb.h:22
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_VALUE
Definition: jsonb.h:24
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_ELEM
Definition: jsonb.h:25
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
#define JENTRY_ISBOOL_TRUE
Definition: jsonb.h:148
#define JBE_ISCONTAINER(je_)
Definition: jsonb.h:157
#define JB_FOBJECT
Definition: jsonb.h:204
#define JBE_ADVANCE_OFFSET(offset, je)
Definition: jsonb.h:164
static void appendKey(JsonbInState *pstate, JsonbValue *string, bool needCopy)
Definition: jsonb_util.c:785
static int lengthCompareJsonbString(const char *val1, int len1, const char *val2, int len2)
Definition: jsonb_util.c:2026
static void convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal)
Definition: jsonb_util.c:1942
static void convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1826
static int lengthCompareJsonbStringValue(const void *a, const void *b)
Definition: jsonb_util.c:2007
void pushJsonbValue(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:583
static void appendElement(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy)
Definition: jsonb_util.c:837
static JsonbIterator * iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent)
Definition: jsonb_util.c:1126
static void fillJsonbValue(JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
Definition: jsonb_util.c:509
static void copyToBuffer(StringInfo buffer, int offset, const void *data, int len)
Definition: jsonb_util.c:1631
static void convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1742
#define JSONB_MAX_PAIRS
Definition: jsonb_util.c:40
static void appendToBuffer(StringInfo buffer, const void *data, int len)
Definition: jsonb_util.c:1640
static void uniqueifyJsonbObject(JsonbValue *object, bool unique_keys, bool skip_nulls)
Definition: jsonb_util.c:2070
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:402
int compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
Definition: jsonb_util.c:194
#define JSONB_MAX_ELEMS
Definition: jsonb_util.c:39
uint32 getJsonbLength(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:162
static short padBufferToInt(StringInfo buffer)
Definition: jsonb_util.c:1654
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:935
static void pushJsonbValueScalar(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *scalarVal)
Definition: jsonb_util.c:663
void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
Definition: jsonb_util.c:1443
void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
Definition: jsonb_util.c:76
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:348
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:973
static int compareJsonbScalarValue(JsonbValue *a, JsonbValue *b)
Definition: jsonb_util.c:1560
static bool equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b)
Definition: jsonb_util.c:1528
uint32 getJsonbOffset(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:137
void JsonbHashScalarValueExtended(const JsonbValue *scalarVal, uint64 *hash, uint64 seed)
Definition: jsonb_util.c:1486
static Jsonb * convertToJsonb(JsonbValue *val)
Definition: jsonb_util.c:1675
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:472
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:96
static int lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
Definition: jsonb_util.c:2046
bool JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
Definition: jsonb_util.c:1189
static void appendValue(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy)
Definition: jsonb_util.c:818
static void copyScalarSubstructure(JsonbValue *v, MemoryContext outcontext)
Definition: jsonb_util.c:873
static JsonbParseState * pushState(JsonbInState *pstate)
Definition: jsonb_util.c:766
static JsonbIterator * freeAndGetParent(JsonbIterator *it)
Definition: jsonb_util.c:1168
static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1717
static int reserveFromBuffer(StringInfo buffer, int len)
Definition: jsonb_util.c:1605
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc(Size size)
Definition: mcxt.c:1365
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:64
struct NumericData * Numeric
Definition: numeric.h:57
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:76
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:428
const void size_t len
const void * data
static char buf[DEFAULT_XLOG_SEG_SIZE]
Definition: pg_test_fsync.c:71
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:232
static uint64 DatumGetUInt64(Datum X)
Definition: postgres.h:413
static bool DatumGetBool(Datum X)
Definition: postgres.h:100
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
static Datum UInt64GetDatum(uint64 X)
Definition: postgres.h:423
static Datum BoolGetDatum(bool X)
Definition: postgres.h:112
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:212
char string[11]
Definition: preproc-type.c:52
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715
void check_stack_depth(void)
Definition: stack_depth.c:95
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:337
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
JEntry children[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb.h:196
uint32 header
Definition: jsonb.h:194
MemoryContext outcontext
Definition: jsonb.h:334
JsonbValue * result
Definition: jsonb.h:333
JsonbParseState * parseState
Definition: jsonb.h:337
JsonbIterState state
Definition: jsonb.h:393
JEntry * children
Definition: jsonb.h:375
uint32 nElems
Definition: jsonb.h:372
struct JsonbIterator * parent
Definition: jsonb.h:395
JsonbContainer * container
Definition: jsonb.h:371
bool isScalar
Definition: jsonb.h:374
char * dataProper
Definition: jsonb.h:377
uint32 order
Definition: jsonb.h:317
JsonbValue key
Definition: jsonb.h:315
JsonbValue value
Definition: jsonb.h:316
bool unique_keys
Definition: jsonb.h:351
JsonbParseState * next
Definition: jsonb.h:350
bool skip_nulls
Definition: jsonb.h:352
JsonbValue contVal
Definition: jsonb.h:348
enum jbvType type
Definition: jsonb.h:257
char * val
Definition: jsonb.h:266
Definition: jsonb.h:215
JsonbContainer root
Definition: jsonb.h:217
Definition: type.h:96
static Size VARSIZE_ANY(const void *PTR)
Definition: varatt.h:460
static Size VARSIZE(const void *PTR)
Definition: varatt.h:298
static char * VARDATA(const void *PTR)
Definition: varatt.h:305
static void SET_VARSIZE(void *PTR, Size len)
Definition: varatt.h:432
int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid)
Definition: varlena.c:1308