1/*-------------------------------------------------------------------------
4 * converting between Jsonb and JsonbValues, and iterating.
6 * Copyright (c) 2014-2025, PostgreSQL Global Development Group
10 * src/backend/utils/adt/jsonb_util.c
12 *-------------------------------------------------------------------------
21#include "utils/fmgrprotos.h"
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.
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.)
36 #define JSONB_MAX_ELEMS (Min(MaxAllocSize / sizeof(JsonbValue), JB_CMASK))
37 #define JSONB_MAX_PAIRS (Min(MaxAllocSize / sizeof(JsonbPair), JB_CMASK))
40 char *base_addr,
uint32 offset,
63 const char *val2,
int len2);
75 val->val.binary.data = &jsonb->
root;
80 * Turn an in-memory JsonbValue into a Jsonb for on-disk storage.
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.
104 scalarArray.
val.array.rawScalar =
true;
105 scalarArray.
val.array.nElems = 1;
122 memcpy(
VARDATA(out),
val->val.binary.data,
val->val.binary.len);
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.
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.
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.
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.
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
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
214 /* Decisively equal */
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
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.
247 if (va.
val.array.rawScalar != vb.
val.array.rawScalar)
248 res = (va.
val.array.rawScalar) ? -1 : 1;
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.
256 if (va.
val.array.nElems != vb.
val.array.nElems)
257 res = (va.
val.array.nElems > vb.
val.array.nElems) ? 1 : -1;
260 if (va.
val.object.nPairs != vb.
val.object.nPairs)
261 res = (va.
val.object.nPairs > vb.
val.object.nPairs) ? 1 : -1;
264 elog(
ERROR,
"unexpected jbvBinary value");
267 elog(
ERROR,
"unexpected jbvDatetime value");
273 /* Type-defined order */
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.
294 /* Type-defined order */
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.
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.
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.)
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.
353 /* Quick out without a palloc cycle if object/array is empty */
360 char *base_addr = (
char *) (children + count);
364 for (
i = 0;
i < count;
i++)
381 /* Object key passed by caller must be a string */
385 key->val.string.len, NULL);
393 * Find value by key in Jsonb object and fetch it into 'res', which is also
396 * 'res' can be passed in as NULL, in which case it's newly palloc'ed here.
400 const char *keyVal,
int keyLen,
JsonbValue *res)
410 /* Quick out without a palloc cycle if object is empty */
415 * Binary search the container. Since we know this is an object, account
416 * for *Pairs* of Jentrys
418 baseAddr = (
char *) (children + count * 2);
421 while (stopLow < stopHigh)
425 const char *candidateVal;
428 stopMiddle = stopLow + (stopHigh - stopLow) / 2;
438 /* Found our key, return corresponding value */
439 int index = stopMiddle + count;
453 stopLow = stopMiddle + 1;
455 stopHigh = stopMiddle;
464 * Get i-th value of a Jsonb array.
466 * Returns palloc()'d copy of the value, or NULL if it does not exist.
479 base_addr = (
char *) &container->
children[nelements];
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.
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().
502 * A nested array or object will be returned as jbvBinary, ie. it won't be
507 char *base_addr,
uint32 offset,
519 result->
val.string.val = base_addr + offset;
531 result->
val.boolean =
true;
536 result->
val.boolean =
false;
542 /* Remove alignment padding from data pointer and length */
550 * Push JsonbValue into JsonbParseState.
552 * Used when parsing JSON tokens to form Jsonb, or when converting an in-memory
553 * JsonbValue to a Jsonb.
555 * Initial state of *JsonbParseState is NULL, since it'll be allocated here
556 * originally (caller will get JsonbParseState back by reference).
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.
563 * Values of type jbvBinary, which are rolled up arrays and objects,
564 * are unpacked before being added to the result.
579 for (
i = 0;
i < jbval->
val.object.nPairs;
i++)
591 for (
i = 0;
i < jbval->
val.array.nElems;
i++)
606 /* unpack the binary and add each piece to the pstate */
609 if ((jbval->
val.binary.data->header &
JB_FSCALAR) && *pstate)
631 v.
val.array.rawScalar) ? &v : NULL);
637 * Do the actual pushing, with only scalar or pseudo-scalar-array values
649 Assert(!scalarVal || scalarVal->
val.array.rawScalar);
651 result = &(*pstate)->contVal;
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)
658 /* Assume that this array is still really a scalar */
660 (*pstate)->size = scalarVal->
val.array.nElems;
672 result = &(*pstate)->contVal;
674 (*pstate)->contVal.val.object.nPairs = 0;
693 (*pstate)->unique_keys,
694 (*pstate)->skip_nulls);
697 /* Steps here common to WJB_END_OBJECT case */
699 result = &(*pstate)->contVal;
702 * Pop stack and push current array/object as value in parent
705 *pstate = (*pstate)->
next;
708 switch ((*pstate)->contVal.type)
717 elog(
ERROR,
"invalid jsonb container type");
722 elog(
ERROR,
"unrecognized jsonb sequential processing token");
729 * pushJsonbValue() worker: Iteration-like forming of Jsonb
744 * pushJsonbValue() worker: Append a pair key to state when generating a Jsonb
756 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
757 errmsg(
"number of jsonb object pairs exceeds the maximum allowed (%zu)",
760 if (object->
val.object.nPairs >= pstate->
size)
763 object->val.object.pairs =
repalloc(object->
val.object.pairs,
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;
772 * pushJsonbValue() worker: Append a pair value to state when generating a
782 object->val.object.pairs[
object->val.object.nPairs++].value = *scalarVal;
786 * pushJsonbValue() worker: Append an element to state when generating a Jsonb
797 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
798 errmsg(
"number of jsonb array elements exceeds the maximum allowed (%zu)",
801 if (array->
val.array.nElems >= pstate->
size)
808 array->
val.array.elems[array->
val.array.nElems++] = *scalarVal;
812 * Given a JsonbContainer, expand to JsonbIterator to iterate over items
813 * fully expanded to in-memory representation for manipulation.
815 * See JsonbIteratorNext() for notes on memory management.
824 * Get next JsonbValue while iterating
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).
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
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
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
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.
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.
871 switch ((*it)->state)
874 /* Set v to array on first array call */
876 val->val.array.nElems = (*it)->nElems;
879 * v->val.array.elems is not actually set, because we aren't doing
882 val->val.array.rawScalar = (*it)->isScalar;
884 (*it)->curDataOffset = 0;
885 (*it)->curValueOffset = 0;
/* not actually used */
886 /* Set state for next call */
891 if ((*it)->curIndex >= (*it)->nElems)
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
905 (*it)->dataProper, (*it)->curDataOffset,
909 (*it)->children[(*it)->curIndex]);
914 /* Recurse into container. */
921 * Scalar item in array, or a container and caller didn't want
922 * us to recurse into it.
928 /* Set v to object on first object call */
930 val->val.object.nPairs = (*it)->nElems;
933 * v->val.object.pairs is not actually set, because we aren't
934 * doing a full conversion
937 (*it)->curDataOffset = 0;
940 /* Set state for next call */
945 if ((*it)->curIndex >= (*it)->nElems)
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
959 /* Return key of a key/value pair. */
961 (*it)->dataProper, (*it)->curDataOffset,
964 elog(
ERROR,
"unexpected jsonb type as object key");
966 /* Set state for next call */
972 /* Set state for next call */
976 (*it)->dataProper, (*it)->curValueOffset,
980 (*it)->children[(*it)->curIndex]);
982 (*it)->children[(*it)->curIndex + (*it)->nElems]);
986 * Value may be a container, in which case we recurse with new,
987 * child iterator (unless the caller asked not to, by passing
999 elog(
ERROR,
"invalid jsonb iterator state");
1000 /* satisfy compilers that don't know that elog(ERROR) doesn't return */
1006 * Initialize an iterator for iterating all elements in a container.
1018 /* Array starts just after header */
1027 /* This is either a "raw scalar", or an array */
1040 elog(
ERROR,
"unknown type of jsonb container");
1047 * JsonbIteratorNext() worker: Return parent, while freeing memory for current
1060 * Worker for "contains" operator's function
1062 * Formally speaking, containment is top-down, unordered subtree isomorphism.
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).
1068 * "val" is lhs Jsonb, and mContained is rhs Jsonb when called from top level.
1069 * We determine if mContained is contained within val.
1080 * Guard against stack overflow due to overly complex Jsonb.
1082 * Functions called here independently take this precaution, but that
1083 * might not be sufficient since this is also a recursive function.
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).
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.
1114 if (vval.
val.object.nPairs < vcontained.
val.object.nPairs)
1117 /* Work through rhs "is it contained within?" object */
1120 JsonbValue *lhsVal;
/* lhsVal is from pair in lhs object */
1126 * When we get through caller's rhs "is it contained within?"
1127 * object without failing to find one of its values, it's
1136 /* First, find value by key... */
1139 vcontained.
val.string.val,
1140 vcontained.
val.string.len,
1146 * ...at this stage it is apparent that there is at least a key
1147 * match for this rhs pair.
1154 * Compare rhs pair's value with lhs pair's value just found using
1157 if (lhsVal->
type != vcontained.
type)
1168 /* Nested container value (object or array) */
1179 * Match "value" side of rhs datum object's pair recursively.
1180 * It's a nested structure.
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").
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
1206 uint32 nLhsElems = vval.
val.array.nElems;
1212 * Handle distinction between "raw scalar" pseudo arrays, and real
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).
1221 if (vval.
val.array.rawScalar && !vcontained.
val.array.rawScalar)
1224 /* Work through rhs "is it contained within?" array */
1230 * When we get through caller's rhs "is it contained within?"
1231 * array without failing to find one of its values, it's
1251 * If this is first container found in rhs array (at this
1252 * depth), initialize temp lhs array of containers
1254 if (lhsConts == NULL)
1258 /* Make room for all possible values */
1261 for (
i = 0;
i < nLhsElems;
i++)
1263 /* Store all lhs elements in temp array */
1268 lhsConts[
j++] = vval;
1271 /* No container elements in temp array, so give up now */
1275 /* We may have only partially filled array */
1279 /* XXX: Nested array containment is O(N^2) */
1280 for (
i = 0;
i < nLhsElems;
i++)
1282 /* Nested container value (object or array) */
1295 pfree(nestContained);
1301 * Report rhs container value is not contained if couldn't
1302 * match rhs container to *some* lhs cont
1311 elog(
ERROR,
"invalid jsonb container type");
1314 elog(
ERROR,
"unexpectedly fell off end of jsonb container");
1319 * Hash a JsonbValue scalar value, mixing the hash value into an existing
1320 * hash provided by the caller.
1322 * Some callers may wish to independently XOR in JB_FOBJECT and JB_FARRAY
1330 /* Compute hash value for scalarVal */
1331 switch (scalarVal->
type)
1338 scalarVal->
val.string.len));
1341 /* Must hash equal numerics to equal hash codes */
1346 tmp = scalarVal->
val.boolean ? 0x02 : 0x04;
1350 elog(
ERROR,
"invalid jsonb scalar type");
1351 tmp = 0;
/* keep compiler quiet */
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.
1365 * Hash a value to a 64-bit value, with a seed. Otherwise, similar to
1366 * JsonbHashScalarValue.
1374 switch (scalarVal->
type)
1381 scalarVal->
val.string.len,
1395 tmp = scalarVal->
val.boolean ? 0x02 : 0x04;
1399 elog(
ERROR,
"invalid jsonb scalar type");
1408 * Are two scalar JsonbValues of the same type a and b equal?
1413 if (
a->type ==
b->type)
1426 return a->val.boolean ==
b->val.boolean;
1429 elog(
ERROR,
"invalid jsonb scalar type");
1432 elog(
ERROR,
"jsonb scalar type mismatch");
1437 * Compare two scalar JsonbValues, returning -1, 0, or 1.
1439 * Strings are compared using the default collation. Used by B-tree
1440 * operators, where a lexical sort order is generally expected.
1445 if (
a->type ==
b->type)
1456 DEFAULT_COLLATION_OID);
1462 if (
a->val.boolean ==
b->val.boolean)
1464 else if (
a->val.boolean >
b->val.boolean)
1469 elog(
ERROR,
"invalid jsonb scalar type");
1472 elog(
ERROR,
"jsonb scalar type mismatch");
1478 * Functions for manipulating the resizable buffer used by convertJsonb and
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().
1492 /* Make more room if needed */
1495 /* remember current offset */
1496 offset = buffer->
len;
1498 /* reserve the space */
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.
1505 buffer->
data[buffer->
len] =
'0円';
1511 * Copy 'len' bytes to a previously reserved area in buffer.
1520 * A shorthand for reserveFromBuffer + copyToBuffer.
1533 * Append padding, so that the length of the StringInfo is int-aligned.
1534 * Returns the number of padding bytes appended.
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円';
1555 * Given a JsonbValue, convert to Jsonb. The result is palloc'd.
1564 /* Should not already have binary representation */
1567 /* Allocate an output buffer. It will be enlarged as needed */
1570 /* Make room for the varlena header */
1576 * Note: the JEntry of the root is discarded. Therefore the root
1577 * JsonbContainer struct must contain enough information to tell what kind
1589 * Subroutine of convertJsonb: serialize a single JsonbValue into buffer.
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.
1596 * If the value is an array or an object, this recurses. 'level' is only used
1597 * for debugging purposes.
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.
1621 elog(
ERROR,
"unknown type of jsonb container to convert");
1632 int nElems =
val->val.array.nElems;
1634 /* Remember where in the buffer this array starts. */
1635 base_offset = buffer->
len;
1637 /* Align to 4-byte boundary (any padding counts as part of my data) */
1641 * Construct the header Jentry and store it in the beginning of the
1642 * variable-length payload.
1645 if (
val->val.array.rawScalar)
1654 /* Reserve space for the JEntries of the elements. */
1658 for (
i = 0;
i < nElems;
i++)
1665 * Convert element, producing a JEntry and appending its
1666 * variable-length data to buffer
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.
1680 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1681 errmsg(
"total size of jsonb array elements exceeds the maximum of %d bytes",
1685 * Convert each JB_OFFSET_STRIDE'th length to an offset.
1691 jentry_offset +=
sizeof(
JEntry);
1694 /* Total data size is everything we've appended to buffer */
1695 totallen = buffer->
len - base_offset;
1697 /* Check length again, since we didn't include the metadata above */
1700 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1701 errmsg(
"total size of jsonb array elements exceeds the maximum of %d bytes",
1704 /* Initialize the header of this node in the container's JEntry array */
1716 int nPairs =
val->val.object.nPairs;
1718 /* Remember where in the buffer this object starts. */
1719 base_offset = buffer->
len;
1721 /* Align to 4-byte boundary (any padding counts as part of my data) */
1725 * Construct the header Jentry and store it in the beginning of the
1726 * variable-length payload.
1731 /* Reserve space for the JEntries of the keys and values. */
1735 * Iterate over the keys, then over the values, since that is the ordering
1736 * we want in the on-disk representation.
1739 for (
i = 0;
i < nPairs;
i++)
1746 * Convert key, producing a JEntry and appending its variable-length
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.
1761 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1762 errmsg(
"total size of jsonb object elements exceeds the maximum of %d bytes",
1766 * Convert each JB_OFFSET_STRIDE'th length to an offset.
1772 jentry_offset +=
sizeof(
JEntry);
1774 for (
i = 0;
i < nPairs;
i++)
1781 * Convert value, producing a JEntry and appending its variable-length
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.
1796 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1797 errmsg(
"total size of jsonb object elements exceeds the maximum of %d bytes",
1801 * Convert each JB_OFFSET_STRIDE'th length to an offset.
1807 jentry_offset +=
sizeof(
JEntry);
1810 /* Total data size is everything we've appended to buffer */
1811 totallen = buffer->
len - base_offset;
1813 /* Check length again, since we didn't include the metadata above */
1816 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1817 errmsg(
"total size of jsonb object elements exceeds the maximum of %d bytes",
1820 /* Initialize the header of this node in the container's JEntry array */
1830 switch (scalarVal->
type)
1839 *header = scalarVal->
val.string.len;
1852 *header = (scalarVal->
val.boolean) ?
1862 scalarVal->
val.datetime.value,
1863 scalarVal->
val.datetime.typid,
1864 &scalarVal->
val.datetime.tz);
1873 elog(
ERROR,
"invalid jsonb scalar type");
1878 * Compare two jbvString JsonbValue values, a and b.
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
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.
1899 vb->
val.string.val, vb->
val.string.len);
1903 * Subroutine for lengthCompareJsonbStringValue
1905 * This is also useful separately to implement binary search on
1912 return memcmp(val1, val2, len1);
1914 return len1 > len2 ? 1 : -1;
1918 * qsort_arg() comparator to compare JsonbPair values.
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.
1924 * N.B: String comparisons here are "length-wise"
1926 * Pairs with equals keys are ordered such that the order field is respected.
1936 if (res == 0 && binequal)
1937 *((
bool *) binequal) =
true;
1940 * Guarantee keeping order of equal pair. Unique algorithm will prefer
1941 * first element as value.
1950 * Sort and unique-ify pairs in JsonbValue object
1955 bool hasNonUniq =
false;
1959 if (object->
val.object.nPairs > 1)
1963 if (hasNonUniq && unique_keys)
1965 errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1966 errmsg(
"duplicate JSON object key value"));
1968 if (hasNonUniq || skip_nulls)
1973 while (skip_nulls && object->
val.object.nPairs > 0 &&
1974 object->
val.object.pairs->value.type ==
jbvNull)
1976 /* If skip_nulls is true, remove leading items with null */
1977 object->val.object.pairs++;
1978 object->val.object.nPairs--;
1981 if (object->
val.object.nPairs > 0)
1983 ptr =
object->val.object.pairs + 1;
1984 res =
object->val.object.pairs;
1986 while (ptr - object->
val.object.pairs < object->
val.object.nPairs)
1988 /* Avoid copying over duplicate or null */
1999 object->val.object.nPairs = res + 1 -
object->val.object.pairs;
Datum hash_numeric(PG_FUNCTION_ARGS)
Datum hash_numeric_extended(PG_FUNCTION_ARGS)
Datum numeric_cmp(PG_FUNCTION_ARGS)
Datum numeric_eq(PG_FUNCTION_ARGS)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define DirectFunctionCall2(func, arg1, arg2)
#define DirectFunctionCall1(func, arg1)
Datum difference(PG_FUNCTION_ARGS)
#define ROTATE_HIGH_AND_LOW_32BITS(v)
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
static Datum hash_any(const unsigned char *k, int keylen)
Assert(PointerIsAligned(start, uint64))
Datum hashcharextended(PG_FUNCTION_ARGS)
if(TABLE==NULL||TABLE_index==NULL)
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
#define JsonContainerIsScalar(jc)
#define JsonContainerIsArray(jc)
#define JsonContainerSize(jc)
#define JBE_ISBOOL_TRUE(je_)
#define IsAJsonbScalar(jsonbval)
#define JENTRY_OFFLENMASK
#define JBE_ISNUMERIC(je_)
#define JBE_ISBOOL_FALSE(je_)
#define JENTRY_ISCONTAINER
#define JBE_ISSTRING(je_)
#define JENTRY_ISBOOL_FALSE
#define JBE_OFFLENFLD(je_)
#define JsonContainerIsObject(jc)
#define JENTRY_ISBOOL_TRUE
#define JBE_ISCONTAINER(je_)
#define JBE_ADVANCE_OFFSET(offset, je)
static int lengthCompareJsonbString(const char *val1, int len1, const char *val2, int len2)
static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
static void convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal)
static void convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
static int lengthCompareJsonbStringValue(const void *a, const void *b)
static JsonbIterator * iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent)
static void fillJsonbValue(JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
static void copyToBuffer(StringInfo buffer, int offset, const void *data, int len)
static void convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
static void appendToBuffer(StringInfo buffer, const void *data, int len)
static void uniqueifyJsonbObject(JsonbValue *object, bool unique_keys, bool skip_nulls)
static void appendValue(JsonbParseState *pstate, JsonbValue *scalarVal)
static JsonbValue * pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *scalarVal)
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
int compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
uint32 getJsonbLength(const JsonbContainer *jc, int index)
static short padBufferToInt(StringInfo buffer)
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
static JsonbParseState * pushState(JsonbParseState **pstate)
void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
static int compareJsonbScalarValue(JsonbValue *a, JsonbValue *b)
static void appendKey(JsonbParseState *pstate, JsonbValue *string)
static bool equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b)
uint32 getJsonbOffset(const JsonbContainer *jc, int index)
void JsonbHashScalarValueExtended(const JsonbValue *scalarVal, uint64 *hash, uint64 seed)
static Jsonb * convertToJsonb(JsonbValue *val)
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Jsonb * JsonbValueToJsonb(JsonbValue *val)
static int lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
bool JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
static JsonbIterator * freeAndGetParent(JsonbIterator *it)
static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
static int reserveFromBuffer(StringInfo buffer, int len)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
struct NumericData * Numeric
static Datum NumericGetDatum(Numeric X)
static uint32 pg_rotate_left32(uint32 word, int n)
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
static uint32 DatumGetUInt32(Datum X)
static uint64 DatumGetUInt64(Datum X)
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
static Datum UInt64GetDatum(uint64 X)
static Datum BoolGetDatum(bool X)
static int32 DatumGetInt32(Datum X)
static unsigned hash(unsigned *uv, int n)
void check_stack_depth(void)
void enlargeStringInfo(StringInfo str, int needed)
void initStringInfo(StringInfo str)
JEntry children[FLEXIBLE_ARRAY_MEMBER]
struct JsonbIterator * parent
JsonbContainer * container
struct JsonbParseState * next
static Size VARSIZE_ANY(const void *PTR)
static Size VARSIZE(const void *PTR)
static char * VARDATA(const void *PTR)
static void SET_VARSIZE(void *PTR, Size len)
int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid)