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