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