Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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