PostgreSQL Source Code git master
jsonb_util.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "miscadmin.h"
#include "port/pg_bitutils.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/datum.h"
#include "utils/fmgrprotos.h"
#include "utils/json.h"
#include "utils/jsonb.h"
#include "utils/memutils.h"
#include "utils/varlena.h"
Include dependency graph for jsonb_util.c:

Go to the source code of this file.

Macros

#define JSONB_MAX_ELEMS   (Min(MaxAllocSize / sizeof(JsonbValue), JB_CMASK))
 
#define JSONB_MAX_PAIRS   (Min(MaxAllocSize / sizeof(JsonbPair), JB_CMASK))
 

Functions

static void fillJsonbValue (JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
 
static bool equalsJsonbScalarValue (JsonbValue *a, JsonbValue *b)
 
static int compareJsonbScalarValue (JsonbValue *a, JsonbValue *b)
 
static JsonbconvertToJsonb (JsonbValue *val)
 
static void convertJsonbValue (StringInfo buffer, JEntry *header, JsonbValue *val, int level)
 
static void convertJsonbArray (StringInfo buffer, JEntry *header, JsonbValue *val, int level)
 
static void convertJsonbObject (StringInfo buffer, JEntry *header, JsonbValue *val, int level)
 
static void convertJsonbScalar (StringInfo buffer, JEntry *header, JsonbValue *scalarVal)
 
static int reserveFromBuffer (StringInfo buffer, int len)
 
static void appendToBuffer (StringInfo buffer, const void *data, int len)
 
static void copyToBuffer (StringInfo buffer, int offset, const void *data, int len)
 
static short padBufferToInt (StringInfo buffer)
 
static JsonbIteratoriteratorFromContainer (JsonbContainer *container, JsonbIterator *parent)
 
static JsonbIteratorfreeAndGetParent (JsonbIterator *it)
 
static JsonbParseStatepushState (JsonbInState *pstate)
 
static void appendKey (JsonbInState *pstate, JsonbValue *string, bool needCopy)
 
static void appendValue (JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy)
 
static void appendElement (JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy)
 
static void copyScalarSubstructure (JsonbValue *v, MemoryContext outcontext)
 
static int lengthCompareJsonbStringValue (const void *a, const void *b)
 
static int lengthCompareJsonbString (const char *val1, int len1, const char *val2, int len2)
 
static int lengthCompareJsonbPair (const void *a, const void *b, void *binequal)
 
static void uniqueifyJsonbObject (JsonbValue *object, bool unique_keys, bool skip_nulls)
 
static void pushJsonbValueScalar (JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *scalarVal)
 
void JsonbToJsonbValue (Jsonb *jsonb, JsonbValue *val)
 
JsonbJsonbValueToJsonb (JsonbValue *val)
 
uint32 getJsonbOffset (const JsonbContainer *jc, int index)
 
uint32 getJsonbLength (const JsonbContainer *jc, int index)
 
int compareJsonbContainers (JsonbContainer *a, JsonbContainer *b)
 
JsonbValuefindJsonbValueFromContainer (JsonbContainer *container, uint32 flags, JsonbValue *key)
 
JsonbValuegetKeyJsonValueFromContainer (JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
 
JsonbValuegetIthJsonbValueFromContainer (JsonbContainer *container, uint32 i)
 
void pushJsonbValue (JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)
 
JsonbIteratorJsonbIteratorInit (JsonbContainer *container)
 
JsonbIteratorToken JsonbIteratorNext (JsonbIterator **it, JsonbValue *val, bool skipNested)
 
bool JsonbDeepContains (JsonbIterator **val, JsonbIterator **mContained)
 
void JsonbHashScalarValue (const JsonbValue *scalarVal, uint32 *hash)
 
void JsonbHashScalarValueExtended (const JsonbValue *scalarVal, uint64 *hash, uint64 seed)
 

Macro Definition Documentation

◆ JSONB_MAX_ELEMS

#define JSONB_MAX_ELEMS   (Min(MaxAllocSize / sizeof(JsonbValue), JB_CMASK))

Definition at line 39 of file jsonb_util.c.

◆ JSONB_MAX_PAIRS

#define JSONB_MAX_PAIRS   (Min(MaxAllocSize / sizeof(JsonbPair), JB_CMASK))

Definition at line 40 of file jsonb_util.c.

Function Documentation

◆ appendElement()

static void appendElement ( JsonbInState pstate,
JsonbValue scalarVal,
bool  needCopy 
)
static

Definition at line 837 of file jsonb_util.c.

838{
839 JsonbParseState *ppstate = pstate->parseState;
840 JsonbValue *array = &ppstate->contVal;
841 JsonbValue *elem;
842
843 Assert(array->type == jbvArray);
844
845 if (array->val.array.nElems >= ppstate->size)
846 {
847 if (unlikely(array->val.array.nElems >= JSONB_MAX_ELEMS))
849 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
850 errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
852 ppstate->size = Min(ppstate->size * 2, JSONB_MAX_ELEMS);
853 array->val.array.elems = repalloc(array->val.array.elems,
854 sizeof(JsonbValue) * ppstate->size);
855 }
856
857 elem = &array->val.array.elems[array->val.array.nElems];
858 *elem = *scalarVal;
859 array->val.array.nElems++;
860
861 if (needCopy)
862 copyScalarSubstructure(elem, pstate->outcontext);
863}
#define Min(x, y)
Definition: c.h:1016
#define unlikely(x)
Definition: c.h:418
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
Assert(PointerIsAligned(start, uint64))
@ jbvArray
Definition: jsonb.h:235
#define JSONB_MAX_ELEMS
Definition: jsonb_util.c:39
static void copyScalarSubstructure(JsonbValue *v, MemoryContext outcontext)
Definition: jsonb_util.c:873
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
MemoryContext outcontext
Definition: jsonb.h:334
JsonbParseState * parseState
Definition: jsonb.h:337
JsonbValue contVal
Definition: jsonb.h:348
enum jbvType type
Definition: jsonb.h:257
char * val
Definition: jsonb.h:266

References Assert(), JsonbParseState::contVal, copyScalarSubstructure(), ereport, errcode(), errmsg(), ERROR, jbvArray, JSONB_MAX_ELEMS, Min, JsonbInState::outcontext, JsonbInState::parseState, repalloc(), JsonbParseState::size, JsonbValue::type, unlikely, and JsonbValue::val.

Referenced by pushJsonbValueScalar().

◆ appendKey()

static void appendKey ( JsonbInState pstate,
JsonbValue string,
bool  needCopy 
)
static

Definition at line 785 of file jsonb_util.c.

786{
787 JsonbParseState *ppstate = pstate->parseState;
788 JsonbValue *object = &ppstate->contVal;
789 JsonbPair *pair;
790
791 Assert(object->type == jbvObject);
792 Assert(string->type == jbvString);
793
794 if (object->val.object.nPairs >= ppstate->size)
795 {
796 if (unlikely(object->val.object.nPairs >= JSONB_MAX_PAIRS))
798 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
799 errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
801 ppstate->size = Min(ppstate->size * 2, JSONB_MAX_PAIRS);
802 object->val.object.pairs = repalloc(object->val.object.pairs,
803 sizeof(JsonbPair) * ppstate->size);
804 }
805
806 pair = &object->val.object.pairs[object->val.object.nPairs];
807 pair->key = *string;
808 pair->order = object->val.object.nPairs;
809
810 if (needCopy)
811 copyScalarSubstructure(&pair->key, pstate->outcontext);
812}
@ jbvObject
Definition: jsonb.h:236
@ jbvString
Definition: jsonb.h:231
#define JSONB_MAX_PAIRS
Definition: jsonb_util.c:40
char string[11]
Definition: preproc-type.c:52
uint32 order
Definition: jsonb.h:317
JsonbValue key
Definition: jsonb.h:315

References Assert(), JsonbParseState::contVal, copyScalarSubstructure(), ereport, errcode(), errmsg(), ERROR, jbvObject, jbvString, JSONB_MAX_PAIRS, JsonbPair::key, Min, JsonbPair::order, JsonbInState::outcontext, JsonbInState::parseState, repalloc(), JsonbParseState::size, JsonbValue::type, unlikely, and JsonbValue::val.

Referenced by pushJsonbValueScalar().

◆ appendToBuffer()

static void appendToBuffer ( StringInfo  buffer,
const void *  data,
int  len 
)
static

Definition at line 1640 of file jsonb_util.c.

1641{
1642 int offset;
1643
1644 offset = reserveFromBuffer(buffer, len);
1645 copyToBuffer(buffer, offset, data, len);
1646}
static void copyToBuffer(StringInfo buffer, int offset, const void *data, int len)
Definition: jsonb_util.c:1631
static int reserveFromBuffer(StringInfo buffer, int len)
Definition: jsonb_util.c:1605
const void size_t len
const void * data

References copyToBuffer(), data, len, and reserveFromBuffer().

Referenced by convertJsonbArray(), convertJsonbObject(), and convertJsonbScalar().

◆ appendValue()

static void appendValue ( JsonbInState pstate,
JsonbValue scalarVal,
bool  needCopy 
)
static

Definition at line 818 of file jsonb_util.c.

819{
820 JsonbValue *object = &pstate->parseState->contVal;
821 JsonbPair *pair;
822
823 Assert(object->type == jbvObject);
824
825 pair = &object->val.object.pairs[object->val.object.nPairs];
826 pair->value = *scalarVal;
827 object->val.object.nPairs++;
828
829 if (needCopy)
830 copyScalarSubstructure(&pair->value, pstate->outcontext);
831}
JsonbValue value
Definition: jsonb.h:316

References Assert(), JsonbParseState::contVal, copyScalarSubstructure(), jbvObject, JsonbInState::outcontext, JsonbInState::parseState, JsonbValue::type, JsonbValue::val, and JsonbPair::value.

Referenced by pushJsonbValueScalar().

◆ compareJsonbContainers()

int compareJsonbContainers ( JsonbContainer a,
JsonbContainer b 
)

Definition at line 194 of file jsonb_util.c.

195{
196 JsonbIterator *ita,
197 *itb;
198 int res = 0;
199
200 ita = JsonbIteratorInit(a);
201 itb = JsonbIteratorInit(b);
202
203 do
204 {
205 JsonbValue va,
206 vb;
208 rb;
209
210 ra = JsonbIteratorNext(&ita, &va, false);
211 rb = JsonbIteratorNext(&itb, &vb, false);
212
213 if (ra == rb)
214 {
215 if (ra == WJB_DONE)
216 {
217 /* Decisively equal */
218 break;
219 }
220
221 if (ra == WJB_END_ARRAY || ra == WJB_END_OBJECT)
222 {
223 /*
224 * There is no array or object to compare at this stage of
225 * processing. jbvArray/jbvObject values are compared
226 * initially, at the WJB_BEGIN_ARRAY and WJB_BEGIN_OBJECT
227 * tokens.
228 */
229 continue;
230 }
231
232 if (va.type == vb.type)
233 {
234 switch (va.type)
235 {
236 case jbvString:
237 case jbvNull:
238 case jbvNumeric:
239 case jbvBool:
240 res = compareJsonbScalarValue(&va, &vb);
241 break;
242 case jbvArray:
243
244 /*
245 * This could be a "raw scalar" pseudo array. That's
246 * a special case here though, since we still want the
247 * general type-based comparisons to apply, and as far
248 * as we're concerned a pseudo array is just a scalar.
249 */
250 if (va.val.array.rawScalar != vb.val.array.rawScalar)
251 res = (va.val.array.rawScalar) ? -1 : 1;
252
253 /*
254 * There should be an "else" here, to prevent us from
255 * overriding the above, but we can't change the sort
256 * order now, so there is a mild anomaly that an empty
257 * top level array sorts less than null.
258 */
259 if (va.val.array.nElems != vb.val.array.nElems)
260 res = (va.val.array.nElems > vb.val.array.nElems) ? 1 : -1;
261 break;
262 case jbvObject:
263 if (va.val.object.nPairs != vb.val.object.nPairs)
264 res = (va.val.object.nPairs > vb.val.object.nPairs) ? 1 : -1;
265 break;
266 case jbvBinary:
267 elog(ERROR, "unexpected jbvBinary value");
268 break;
269 case jbvDatetime:
270 elog(ERROR, "unexpected jbvDatetime value");
271 break;
272 }
273 }
274 else
275 {
276 /* Type-defined order */
277 res = (va.type > vb.type) ? 1 : -1;
278 }
279 }
280 else
281 {
282 /*
283 * It's not possible for one iterator to report end of array or
284 * object while the other one reports something else, because we
285 * would have detected a length mismatch when we processed the
286 * container-start tokens above. Likewise we can't see WJB_DONE
287 * from one but not the other. So we have two different-type
288 * containers, or a container and some scalar type, or two
289 * different scalar types. Sort on the basis of the type code.
290 */
291 Assert(ra != WJB_DONE && ra != WJB_END_ARRAY && ra != WJB_END_OBJECT);
292 Assert(rb != WJB_DONE && rb != WJB_END_ARRAY && rb != WJB_END_OBJECT);
293
294 Assert(va.type != vb.type);
295 Assert(va.type != jbvBinary);
296 Assert(vb.type != jbvBinary);
297 /* Type-defined order */
298 res = (va.type > vb.type) ? 1 : -1;
299 }
300 }
301 while (res == 0);
302
303 while (ita != NULL)
304 {
305 JsonbIterator *i = ita->parent;
306
307 pfree(ita);
308 ita = i;
309 }
310 while (itb != NULL)
311 {
312 JsonbIterator *i = itb->parent;
313
314 pfree(itb);
315 itb = i;
316 }
317
318 return res;
319}
#define elog(elevel,...)
Definition: elog.h:226
int b
Definition: isn.c:74
int a
Definition: isn.c:73
int i
Definition: isn.c:77
@ jbvNumeric
Definition: jsonb.h:232
@ jbvBool
Definition: jsonb.h:233
@ jbvBinary
Definition: jsonb.h:238
@ jbvNull
Definition: jsonb.h:230
@ jbvDatetime
Definition: jsonb.h:246
JsonbIteratorToken
Definition: jsonb.h:21
@ WJB_DONE
Definition: jsonb.h:22
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_END_OBJECT
Definition: jsonb.h:29
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:935
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:973
static int compareJsonbScalarValue(JsonbValue *a, JsonbValue *b)
Definition: jsonb_util.c:1560
void pfree(void *pointer)
Definition: mcxt.c:1594
struct JsonbIterator * parent
Definition: jsonb.h:395

References a, Assert(), b, compareJsonbScalarValue(), elog, ERROR, i, jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbIterator::parent, pfree(), JsonbValue::type, JsonbValue::val, WJB_DONE, WJB_END_ARRAY, and WJB_END_OBJECT.

Referenced by jsonb_cmp(), jsonb_eq(), jsonb_ge(), jsonb_gt(), jsonb_le(), jsonb_lt(), and jsonb_ne().

◆ compareJsonbScalarValue()

static int compareJsonbScalarValue ( JsonbValue a,
JsonbValue b 
)
static

Definition at line 1560 of file jsonb_util.c.

1561{
1562 if (a->type == b->type)
1563 {
1564 switch (a->type)
1565 {
1566 case jbvNull:
1567 return 0;
1568 case jbvString:
1569 return varstr_cmp(a->val.string.val,
1570 a->val.string.len,
1571 b->val.string.val,
1572 b->val.string.len,
1573 DEFAULT_COLLATION_OID);
1574 case jbvNumeric:
1576 PointerGetDatum(a->val.numeric),
1577 PointerGetDatum(b->val.numeric)));
1578 case jbvBool:
1579 if (a->val.boolean == b->val.boolean)
1580 return 0;
1581 else if (a->val.boolean > b->val.boolean)
1582 return 1;
1583 else
1584 return -1;
1585 default:
1586 elog(ERROR, "invalid jsonb scalar type");
1587 }
1588 }
1589 elog(ERROR, "jsonb scalar type mismatch");
1590 return -1;
1591}
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2415
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:684
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:212
int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid)
Definition: varlena.c:1308

References a, b, DatumGetInt32(), DirectFunctionCall2, elog, ERROR, jbvBool, jbvNull, jbvNumeric, jbvString, numeric_cmp(), PointerGetDatum(), and varstr_cmp().

Referenced by compareJsonbContainers().

◆ convertJsonbArray()

static void convertJsonbArray ( StringInfo  buffer,
JEntry header,
JsonbValue val,
int  level 
)
static

Definition at line 1742 of file jsonb_util.c.

1743{
1744 int base_offset;
1745 int jentry_offset;
1746 int i;
1747 int totallen;
1748 uint32 containerhead;
1749 int nElems = val->val.array.nElems;
1750
1751 /* Remember where in the buffer this array starts. */
1752 base_offset = buffer->len;
1753
1754 /* Align to 4-byte boundary (any padding counts as part of my data) */
1755 padBufferToInt(buffer);
1756
1757 /*
1758 * Construct the header Jentry and store it in the beginning of the
1759 * variable-length payload.
1760 */
1761 containerhead = nElems | JB_FARRAY;
1762 if (val->val.array.rawScalar)
1763 {
1764 Assert(nElems == 1);
1765 Assert(level == 0);
1766 containerhead |= JB_FSCALAR;
1767 }
1768
1769 appendToBuffer(buffer, &containerhead, sizeof(uint32));
1770
1771 /* Reserve space for the JEntries of the elements. */
1772 jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nElems);
1773
1774 totallen = 0;
1775 for (i = 0; i < nElems; i++)
1776 {
1777 JsonbValue *elem = &val->val.array.elems[i];
1778 int len;
1779 JEntry meta;
1780
1781 /*
1782 * Convert element, producing a JEntry and appending its
1783 * variable-length data to buffer
1784 */
1785 convertJsonbValue(buffer, &meta, elem, level + 1);
1786
1787 len = JBE_OFFLENFLD(meta);
1788 totallen += len;
1789
1790 /*
1791 * Bail out if total variable-length data exceeds what will fit in a
1792 * JEntry length field. We check this in each iteration, not just
1793 * once at the end, to forestall possible integer overflow.
1794 */
1795 if (totallen > JENTRY_OFFLENMASK)
1796 ereport(ERROR,
1797 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1798 errmsg("total size of jsonb array elements exceeds the maximum of %d bytes",
1800
1801 /*
1802 * Convert each JB_OFFSET_STRIDE'th length to an offset.
1803 */
1804 if ((i % JB_OFFSET_STRIDE) == 0)
1805 meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1806
1807 copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1808 jentry_offset += sizeof(JEntry);
1809 }
1810
1811 /* Total data size is everything we've appended to buffer */
1812 totallen = buffer->len - base_offset;
1813
1814 /* Check length again, since we didn't include the metadata above */
1815 if (totallen > JENTRY_OFFLENMASK)
1816 ereport(ERROR,
1817 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1818 errmsg("total size of jsonb array elements exceeds the maximum of %d bytes",
1820
1821 /* Initialize the header of this node in the container's JEntry array */
1822 *header = JENTRY_ISCONTAINER | totallen;
1823}
uint32_t uint32
Definition: c.h:552
long val
Definition: informix.c:689
#define JB_FSCALAR
Definition: jsonb.h:203
#define JB_OFFSET_STRIDE
Definition: jsonb.h:180
#define JENTRY_OFFLENMASK
Definition: jsonb.h:140
#define JENTRY_ISCONTAINER
Definition: jsonb.h:150
#define JENTRY_TYPEMASK
Definition: jsonb.h:141
#define JBE_OFFLENFLD(je_)
Definition: jsonb.h:153
#define JENTRY_HAS_OFF
Definition: jsonb.h:142
#define JB_FARRAY
Definition: jsonb.h:205
uint32 JEntry
Definition: jsonb.h:138
static void appendToBuffer(StringInfo buffer, const void *data, int len)
Definition: jsonb_util.c:1640
static short padBufferToInt(StringInfo buffer)
Definition: jsonb_util.c:1654
static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1717

References appendToBuffer(), Assert(), convertJsonbValue(), copyToBuffer(), ereport, errcode(), errmsg(), ERROR, i, JB_FARRAY, JB_FSCALAR, JB_OFFSET_STRIDE, JBE_OFFLENFLD, JENTRY_HAS_OFF, JENTRY_ISCONTAINER, JENTRY_OFFLENMASK, JENTRY_TYPEMASK, StringInfoData::len, len, padBufferToInt(), reserveFromBuffer(), and val.

Referenced by convertJsonbValue().

◆ convertJsonbObject()

static void convertJsonbObject ( StringInfo  buffer,
JEntry header,
JsonbValue val,
int  level 
)
static

Definition at line 1826 of file jsonb_util.c.

1827{
1828 int base_offset;
1829 int jentry_offset;
1830 int i;
1831 int totallen;
1832 uint32 containerheader;
1833 int nPairs = val->val.object.nPairs;
1834
1835 /* Remember where in the buffer this object starts. */
1836 base_offset = buffer->len;
1837
1838 /* Align to 4-byte boundary (any padding counts as part of my data) */
1839 padBufferToInt(buffer);
1840
1841 /*
1842 * Construct the header Jentry and store it in the beginning of the
1843 * variable-length payload.
1844 */
1845 containerheader = nPairs | JB_FOBJECT;
1846 appendToBuffer(buffer, &containerheader, sizeof(uint32));
1847
1848 /* Reserve space for the JEntries of the keys and values. */
1849 jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nPairs * 2);
1850
1851 /*
1852 * Iterate over the keys, then over the values, since that is the ordering
1853 * we want in the on-disk representation.
1854 */
1855 totallen = 0;
1856 for (i = 0; i < nPairs; i++)
1857 {
1858 JsonbPair *pair = &val->val.object.pairs[i];
1859 int len;
1860 JEntry meta;
1861
1862 /*
1863 * Convert key, producing a JEntry and appending its variable-length
1864 * data to buffer
1865 */
1866 convertJsonbScalar(buffer, &meta, &pair->key);
1867
1868 len = JBE_OFFLENFLD(meta);
1869 totallen += len;
1870
1871 /*
1872 * Bail out if total variable-length data exceeds what will fit in a
1873 * JEntry length field. We check this in each iteration, not just
1874 * once at the end, to forestall possible integer overflow.
1875 */
1876 if (totallen > JENTRY_OFFLENMASK)
1877 ereport(ERROR,
1878 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1879 errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1881
1882 /*
1883 * Convert each JB_OFFSET_STRIDE'th length to an offset.
1884 */
1885 if ((i % JB_OFFSET_STRIDE) == 0)
1886 meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1887
1888 copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1889 jentry_offset += sizeof(JEntry);
1890 }
1891 for (i = 0; i < nPairs; i++)
1892 {
1893 JsonbPair *pair = &val->val.object.pairs[i];
1894 int len;
1895 JEntry meta;
1896
1897 /*
1898 * Convert value, producing a JEntry and appending its variable-length
1899 * data to buffer
1900 */
1901 convertJsonbValue(buffer, &meta, &pair->value, level + 1);
1902
1903 len = JBE_OFFLENFLD(meta);
1904 totallen += len;
1905
1906 /*
1907 * Bail out if total variable-length data exceeds what will fit in a
1908 * JEntry length field. We check this in each iteration, not just
1909 * once at the end, to forestall possible integer overflow.
1910 */
1911 if (totallen > JENTRY_OFFLENMASK)
1912 ereport(ERROR,
1913 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1914 errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1916
1917 /*
1918 * Convert each JB_OFFSET_STRIDE'th length to an offset.
1919 */
1920 if (((i + nPairs) % JB_OFFSET_STRIDE) == 0)
1921 meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1922
1923 copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry));
1924 jentry_offset += sizeof(JEntry);
1925 }
1926
1927 /* Total data size is everything we've appended to buffer */
1928 totallen = buffer->len - base_offset;
1929
1930 /* Check length again, since we didn't include the metadata above */
1931 if (totallen > JENTRY_OFFLENMASK)
1932 ereport(ERROR,
1933 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1934 errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1936
1937 /* Initialize the header of this node in the container's JEntry array */
1938 *header = JENTRY_ISCONTAINER | totallen;
1939}
#define JB_FOBJECT
Definition: jsonb.h:204
static void convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal)
Definition: jsonb_util.c:1942

References appendToBuffer(), convertJsonbScalar(), convertJsonbValue(), copyToBuffer(), ereport, errcode(), errmsg(), ERROR, i, JB_FOBJECT, JB_OFFSET_STRIDE, JBE_OFFLENFLD, JENTRY_HAS_OFF, JENTRY_ISCONTAINER, JENTRY_OFFLENMASK, JENTRY_TYPEMASK, JsonbPair::key, StringInfoData::len, len, padBufferToInt(), reserveFromBuffer(), val, and JsonbPair::value.

Referenced by convertJsonbValue().

◆ convertJsonbScalar()

static void convertJsonbScalar ( StringInfo  buffer,
JEntry header,
JsonbValue scalarVal 
)
static

Definition at line 1942 of file jsonb_util.c.

1943{
1944 int numlen;
1945 short padlen;
1946
1947 switch (scalarVal->type)
1948 {
1949 case jbvNull:
1950 *header = JENTRY_ISNULL;
1951 break;
1952
1953 case jbvString:
1954 appendToBuffer(buffer, scalarVal->val.string.val, scalarVal->val.string.len);
1955
1956 *header = scalarVal->val.string.len;
1957 break;
1958
1959 case jbvNumeric:
1960 numlen = VARSIZE_ANY(scalarVal->val.numeric);
1961 padlen = padBufferToInt(buffer);
1962
1963 appendToBuffer(buffer, scalarVal->val.numeric, numlen);
1964
1965 *header = JENTRY_ISNUMERIC | (padlen + numlen);
1966 break;
1967
1968 case jbvBool:
1969 *header = (scalarVal->val.boolean) ?
1971 break;
1972
1973 case jbvDatetime:
1974 {
1975 char buf[MAXDATELEN + 1];
1976 size_t len;
1977
1979 scalarVal->val.datetime.value,
1980 scalarVal->val.datetime.typid,
1981 &scalarVal->val.datetime.tz);
1982 len = strlen(buf);
1983 appendToBuffer(buffer, buf, len);
1984
1985 *header = len;
1986 }
1987 break;
1988
1989 default:
1990 elog(ERROR, "invalid jsonb scalar type");
1991 }
1992}
#define MAXDATELEN
Definition: datetime.h:200
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:311
#define JENTRY_ISNUMERIC
Definition: jsonb.h:146
#define JENTRY_ISNULL
Definition: jsonb.h:149
#define JENTRY_ISBOOL_FALSE
Definition: jsonb.h:147
#define JENTRY_ISBOOL_TRUE
Definition: jsonb.h:148
static char buf[DEFAULT_XLOG_SEG_SIZE]
Definition: pg_test_fsync.c:71
static Size VARSIZE_ANY(const void *PTR)
Definition: varatt.h:460

References appendToBuffer(), buf, elog, ERROR, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvString, JENTRY_ISBOOL_FALSE, JENTRY_ISBOOL_TRUE, JENTRY_ISNULL, JENTRY_ISNUMERIC, JsonEncodeDateTime(), len, MAXDATELEN, padBufferToInt(), JsonbValue::type, JsonbValue::val, and VARSIZE_ANY().

Referenced by convertJsonbObject(), and convertJsonbValue().

◆ convertJsonbValue()

static void convertJsonbValue ( StringInfo  buffer,
JEntry header,
JsonbValue val,
int  level 
)
static

Definition at line 1717 of file jsonb_util.c.

1718{
1720
1721 if (!val)
1722 return;
1723
1724 /*
1725 * A JsonbValue passed as val should never have a type of jbvBinary, and
1726 * neither should any of its sub-components. Those values will be produced
1727 * by convertJsonbArray and convertJsonbObject, the results of which will
1728 * not be passed back to this function as an argument.
1729 */
1730
1731 if (IsAJsonbScalar(val))
1732 convertJsonbScalar(buffer, header, val);
1733 else if (val->type == jbvArray)
1734 convertJsonbArray(buffer, header, val, level);
1735 else if (val->type == jbvObject)
1736 convertJsonbObject(buffer, header, val, level);
1737 else
1738 elog(ERROR, "unknown type of jsonb container to convert");
1739}
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:299
static void convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1826
static void convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1742
void check_stack_depth(void)
Definition: stack_depth.c:95

References check_stack_depth(), convertJsonbArray(), convertJsonbObject(), convertJsonbScalar(), elog, ERROR, IsAJsonbScalar, jbvArray, jbvObject, and val.

Referenced by convertJsonbArray(), convertJsonbObject(), and convertToJsonb().

◆ convertToJsonb()

static Jsonb * convertToJsonb ( JsonbValue val)
static

Definition at line 1675 of file jsonb_util.c.

1676{
1677 StringInfoData buffer;
1678 JEntry jentry;
1679 Jsonb *res;
1680
1681 /* Should not already have binary representation */
1682 Assert(val->type != jbvBinary);
1683
1684 /* Allocate an output buffer. It will be enlarged as needed */
1685 initStringInfo(&buffer);
1686
1687 /* Make room for the varlena header */
1688 reserveFromBuffer(&buffer, VARHDRSZ);
1689
1690 convertJsonbValue(&buffer, &jentry, val, 0);
1691
1692 /*
1693 * Note: the JEntry of the root is discarded. Therefore the root
1694 * JsonbContainer struct must contain enough information to tell what kind
1695 * of value it is.
1696 */
1697
1698 res = (Jsonb *) buffer.data;
1699
1700 SET_VARSIZE(res, buffer.len);
1701
1702 return res;
1703}
#define VARHDRSZ
Definition: c.h:711
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
Definition: jsonb.h:215
static void SET_VARSIZE(void *PTR, Size len)
Definition: varatt.h:432

References Assert(), convertJsonbValue(), StringInfoData::data, initStringInfo(), jbvBinary, StringInfoData::len, reserveFromBuffer(), SET_VARSIZE(), val, and VARHDRSZ.

Referenced by JsonbValueToJsonb().

◆ copyScalarSubstructure()

static void copyScalarSubstructure ( JsonbValue v,
MemoryContext  outcontext 
)
static

Definition at line 873 of file jsonb_util.c.

874{
875 MemoryContext oldcontext;
876
877 /* Nothing to do if caller did not specify an outcontext */
878 if (outcontext == NULL)
879 return;
880 switch (v->type)
881 {
882 case jbvNull:
883 case jbvBool:
884 /* pass-by-value, nothing to do */
885 break;
886 case jbvString:
887 {
888 char *buf = MemoryContextAlloc(outcontext,
889 v->val.string.len);
890
891 memcpy(buf, v->val.string.val, v->val.string.len);
892 v->val.string.val = buf;
893 }
894 break;
895 case jbvNumeric:
896 oldcontext = MemoryContextSwitchTo(outcontext);
897 v->val.numeric =
899 false, -1));
900 MemoryContextSwitchTo(oldcontext);
901 break;
902 case jbvDatetime:
903 switch (v->val.datetime.typid)
904 {
905 case DATEOID:
906 case TIMEOID:
907 case TIMESTAMPOID:
908 case TIMESTAMPTZOID:
909 /* pass-by-value, nothing to do */
910 break;
911 case TIMETZOID:
912 /* pass-by-reference */
913 oldcontext = MemoryContextSwitchTo(outcontext);
914 v->val.datetime.value = datumCopy(v->val.datetime.value,
915 false, TIMETZ_TYPLEN);
916 MemoryContextSwitchTo(oldcontext);
917 break;
918 default:
919 elog(ERROR, "unexpected jsonb datetime type oid %u",
920 v->val.datetime.typid);
921 }
922 break;
923 default:
924 elog(ERROR, "invalid jsonb scalar type");
925 }
926}
#define TIMETZ_TYPLEN
Definition: date.h:39
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:64
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:76
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124

References buf, datumCopy(), DatumGetNumeric(), elog, ERROR, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvString, MemoryContextAlloc(), MemoryContextSwitchTo(), NumericGetDatum(), TIMETZ_TYPLEN, JsonbValue::type, and JsonbValue::val.

Referenced by appendElement(), appendKey(), and appendValue().

◆ copyToBuffer()

static void copyToBuffer ( StringInfo  buffer,
int  offset,
const void *  data,
int  len 
)
static

Definition at line 1631 of file jsonb_util.c.

1632{
1633 memcpy(buffer->data + offset, data, len);
1634}

References StringInfoData::data, data, and len.

Referenced by appendToBuffer(), convertJsonbArray(), and convertJsonbObject().

◆ equalsJsonbScalarValue()

static bool equalsJsonbScalarValue ( JsonbValue a,
JsonbValue b 
)
static

Definition at line 1528 of file jsonb_util.c.

1529{
1530 if (a->type == b->type)
1531 {
1532 switch (a->type)
1533 {
1534 case jbvNull:
1535 return true;
1536 case jbvString:
1537 return lengthCompareJsonbStringValue(a, b) == 0;
1538 case jbvNumeric:
1540 PointerGetDatum(a->val.numeric),
1541 PointerGetDatum(b->val.numeric)));
1542 case jbvBool:
1543 return a->val.boolean == b->val.boolean;
1544
1545 default:
1546 elog(ERROR, "invalid jsonb scalar type");
1547 }
1548 }
1549 elog(ERROR, "jsonb scalar type mismatch");
1550 return false;
1551}
Datum numeric_eq(PG_FUNCTION_ARGS)
Definition: numeric.c:2431
static int lengthCompareJsonbStringValue(const void *a, const void *b)
Definition: jsonb_util.c:2007
static bool DatumGetBool(Datum X)
Definition: postgres.h:100

References a, b, DatumGetBool(), DirectFunctionCall2, elog, ERROR, jbvBool, jbvNull, jbvNumeric, jbvString, lengthCompareJsonbStringValue(), numeric_eq(), and PointerGetDatum().

Referenced by findJsonbValueFromContainer(), and JsonbDeepContains().

◆ fillJsonbValue()

static void fillJsonbValue ( JsonbContainer container,
int  index,
char *  base_addr,
uint32  offset,
JsonbValue result 
)
static

Definition at line 509 of file jsonb_util.c.

512{
513 JEntry entry = container->children[index];
514
515 if (JBE_ISNULL(entry))
516 {
517 result->type = jbvNull;
518 }
519 else if (JBE_ISSTRING(entry))
520 {
521 result->type = jbvString;
522 result->val.string.val = base_addr + offset;
523 result->val.string.len = getJsonbLength(container, index);
524 Assert(result->val.string.len >= 0);
525 }
526 else if (JBE_ISNUMERIC(entry))
527 {
528 result->type = jbvNumeric;
529 result->val.numeric = (Numeric) (base_addr + INTALIGN(offset));
530 }
531 else if (JBE_ISBOOL_TRUE(entry))
532 {
533 result->type = jbvBool;
534 result->val.boolean = true;
535 }
536 else if (JBE_ISBOOL_FALSE(entry))
537 {
538 result->type = jbvBool;
539 result->val.boolean = false;
540 }
541 else
542 {
543 Assert(JBE_ISCONTAINER(entry));
544 result->type = jbvBinary;
545 /* Remove alignment padding from data pointer and length */
546 result->val.binary.data = (JsonbContainer *) (base_addr + INTALIGN(offset));
547 result->val.binary.len = getJsonbLength(container, index) -
548 (INTALIGN(offset) - offset);
549 }
550}
#define INTALIGN(LEN)
Definition: c.h:821
#define JBE_ISNULL(je_)
Definition: jsonb.h:158
#define JBE_ISBOOL_TRUE(je_)
Definition: jsonb.h:159
#define JBE_ISNUMERIC(je_)
Definition: jsonb.h:156
#define JBE_ISBOOL_FALSE(je_)
Definition: jsonb.h:160
#define JBE_ISSTRING(je_)
Definition: jsonb.h:155
#define JBE_ISCONTAINER(je_)
Definition: jsonb.h:157
uint32 getJsonbLength(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:162
struct NumericData * Numeric
Definition: numeric.h:57
JEntry children[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb.h:196
Definition: type.h:96

References Assert(), JsonbContainer::children, getJsonbLength(), INTALIGN, JBE_ISBOOL_FALSE, JBE_ISBOOL_TRUE, JBE_ISCONTAINER, JBE_ISNULL, JBE_ISNUMERIC, JBE_ISSTRING, jbvBinary, jbvBool, jbvNull, jbvNumeric, jbvString, JsonbValue::type, and JsonbValue::val.

Referenced by findJsonbValueFromContainer(), getIthJsonbValueFromContainer(), getKeyJsonValueFromContainer(), and JsonbIteratorNext().

◆ findJsonbValueFromContainer()

JsonbValue * findJsonbValueFromContainer ( JsonbContainer container,
uint32  flags,
JsonbValue key 
)

Definition at line 348 of file jsonb_util.c.

350{
351 JEntry *children = container->children;
352 int count = JsonContainerSize(container);
353
354 Assert((flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);
355
356 /* Quick out without a palloc cycle if object/array is empty */
357 if (count <= 0)
358 return NULL;
359
360 if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
361 {
363 char *base_addr = (char *) (children + count);
364 uint32 offset = 0;
365 int i;
366
367 for (i = 0; i < count; i++)
368 {
369 fillJsonbValue(container, i, base_addr, offset, result);
370
371 if (key->type == result->type)
372 {
373 if (equalsJsonbScalarValue(key, result))
374 return result;
375 }
376
377 JBE_ADVANCE_OFFSET(offset, children[i]);
378 }
379
380 pfree(result);
381 }
382 else if ((flags & JB_FOBJECT) && JsonContainerIsObject(container))
383 {
384 /* Object key passed by caller must be a string */
385 Assert(key->type == jbvString);
386
387 return getKeyJsonValueFromContainer(container, key->val.string.val,
388 key->val.string.len, NULL);
389 }
390
391 /* Not found */
392 return NULL;
393}
#define palloc_object(type)
Definition: fe_memutils.h:74
#define JsonContainerIsArray(jc)
Definition: jsonb.h:211
#define JsonContainerSize(jc)
Definition: jsonb.h:208
#define JsonContainerIsObject(jc)
Definition: jsonb.h:210
#define JBE_ADVANCE_OFFSET(offset, je)
Definition: jsonb.h:164
static void fillJsonbValue(JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
Definition: jsonb_util.c:509
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:402
static bool equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b)
Definition: jsonb_util.c:1528

References Assert(), JsonbContainer::children, equalsJsonbScalarValue(), fillJsonbValue(), getKeyJsonValueFromContainer(), i, JB_FARRAY, JB_FOBJECT, JBE_ADVANCE_OFFSET, jbvString, JsonContainerIsArray, JsonContainerIsObject, JsonContainerSize, sort-test::key, palloc_object, pfree(), and JsonbValue::type.

Referenced by executeItemOptUnwrapTarget(), getJsonPathVariableFromJsonb(), jsonb_exists(), jsonb_exists_all(), jsonb_exists_any(), and JsonbDeepContains().

◆ freeAndGetParent()

static JsonbIterator * freeAndGetParent ( JsonbIterator it)
static

Definition at line 1168 of file jsonb_util.c.

1169{
1170 JsonbIterator *v = it->parent;
1171
1172 pfree(it);
1173 return v;
1174}

References JsonbIterator::parent, and pfree().

Referenced by JsonbIteratorNext().

◆ getIthJsonbValueFromContainer()

JsonbValue * getIthJsonbValueFromContainer ( JsonbContainer container,
uint32  i 
)

Definition at line 472 of file jsonb_util.c.

473{
474 JsonbValue *result;
475 char *base_addr;
476 uint32 nelements;
477
478 if (!JsonContainerIsArray(container))
479 elog(ERROR, "not a jsonb array");
480
481 nelements = JsonContainerSize(container);
482 base_addr = (char *) &container->children[nelements];
483
484 if (i >= nelements)
485 return NULL;
486
487 result = palloc_object(JsonbValue);
488
489 fillJsonbValue(container, i, base_addr,
490 getJsonbOffset(container, i),
491 result);
492
493 return result;
494}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
uint32 getJsonbOffset(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:137

References JsonbContainer::children, elog, ERROR, fillJsonbValue(), getJsonbOffset(), i, if(), JsonContainerIsArray, JsonContainerSize, and palloc_object.

Referenced by executeItemOptUnwrapTarget(), jsonb_array_element(), jsonb_array_element_text(), and jsonb_get_element().

◆ getJsonbLength()

uint32 getJsonbLength ( const JsonbContainer jc,
int  index 
)

Definition at line 162 of file jsonb_util.c.

163{
164 uint32 off;
165 uint32 len;
166
167 /*
168 * If the length is stored directly in the JEntry, just return it.
169 * Otherwise, get the begin offset of the entry, and subtract that from
170 * the stored end+1 offset.
171 */
172 if (JBE_HAS_OFF(jc->children[index]))
173 {
174 off = getJsonbOffset(jc, index);
175 len = JBE_OFFLENFLD(jc->children[index]) - off;
176 }
177 else
179
180 return len;
181}
#define JBE_HAS_OFF(je_)
Definition: jsonb.h:154

References JsonbContainer::children, getJsonbOffset(), JBE_HAS_OFF, JBE_OFFLENFLD, and len.

Referenced by fillJsonbValue(), and getKeyJsonValueFromContainer().

◆ getJsonbOffset()

uint32 getJsonbOffset ( const JsonbContainer jc,
int  index 
)

Definition at line 137 of file jsonb_util.c.

138{
139 uint32 offset = 0;
140 int i;
141
142 /*
143 * Start offset of this entry is equal to the end offset of the previous
144 * entry. Walk backwards to the most recent entry stored as an end
145 * offset, returning that offset plus any lengths in between.
146 */
147 for (i = index - 1; i >= 0; i--)
148 {
149 offset += JBE_OFFLENFLD(jc->children[i]);
150 if (JBE_HAS_OFF(jc->children[i]))
151 break;
152 }
153
154 return offset;
155}

References JsonbContainer::children, i, JBE_HAS_OFF, and JBE_OFFLENFLD.

Referenced by getIthJsonbValueFromContainer(), getJsonbLength(), getKeyJsonValueFromContainer(), and JsonbIteratorNext().

◆ getKeyJsonValueFromContainer()

JsonbValue * getKeyJsonValueFromContainer ( JsonbContainer container,
const char *  keyVal,
int  keyLen,
JsonbValue res 
)

Definition at line 402 of file jsonb_util.c.

404{
405 JEntry *children = container->children;
406 int count = JsonContainerSize(container);
407 char *baseAddr;
408 uint32 stopLow,
409 stopHigh;
410
411 Assert(JsonContainerIsObject(container));
412
413 /* Quick out without a palloc cycle if object is empty */
414 if (count <= 0)
415 return NULL;
416
417 /*
418 * Binary search the container. Since we know this is an object, account
419 * for *Pairs* of Jentrys
420 */
421 baseAddr = (char *) (children + count * 2);
422 stopLow = 0;
423 stopHigh = count;
424 while (stopLow < stopHigh)
425 {
426 uint32 stopMiddle;
427 int difference;
428 const char *candidateVal;
429 int candidateLen;
430
431 stopMiddle = stopLow + (stopHigh - stopLow) / 2;
432
433 candidateVal = baseAddr + getJsonbOffset(container, stopMiddle);
434 candidateLen = getJsonbLength(container, stopMiddle);
435
436 difference = lengthCompareJsonbString(candidateVal, candidateLen,
437 keyVal, keyLen);
438
439 if (difference == 0)
440 {
441 /* Found our key, return corresponding value */
442 int index = stopMiddle + count;
443
444 if (!res)
446
447 fillJsonbValue(container, index, baseAddr,
448 getJsonbOffset(container, index),
449 res);
450
451 return res;
452 }
453 else
454 {
455 if (difference < 0)
456 stopLow = stopMiddle + 1;
457 else
458 stopHigh = stopMiddle;
459 }
460 }
461
462 /* Not found */
463 return NULL;
464}
Datum difference(PG_FUNCTION_ARGS)
static int lengthCompareJsonbString(const char *val1, int len1, const char *val2, int len2)
Definition: jsonb_util.c:2026

References Assert(), JsonbContainer::children, difference(), fillJsonbValue(), getJsonbLength(), getJsonbOffset(), JsonContainerIsObject, JsonContainerSize, lengthCompareJsonbString(), and palloc_object.

Referenced by findJsonbValueFromContainer(), JsObjectGetField(), jsonb_get_element(), jsonb_object_field(), jsonb_object_field_text(), and JsonbDeepContains().

◆ iteratorFromContainer()

static JsonbIterator * iteratorFromContainer ( JsonbContainer container,
JsonbIterator parent 
)
static

Definition at line 1126 of file jsonb_util.c.

1127{
1128 JsonbIterator *it;
1129
1131 it->container = container;
1132 it->parent = parent;
1133 it->nElems = JsonContainerSize(container);
1134
1135 /* Array starts just after header */
1136 it->children = container->children;
1137
1138 switch (container->header & (JB_FARRAY | JB_FOBJECT))
1139 {
1140 case JB_FARRAY:
1141 it->dataProper =
1142 (char *) it->children + it->nElems * sizeof(JEntry);
1143 it->isScalar = JsonContainerIsScalar(container);
1144 /* This is either a "raw scalar", or an array */
1145 Assert(!it->isScalar || it->nElems == 1);
1146
1147 it->state = JBI_ARRAY_START;
1148 break;
1149
1150 case JB_FOBJECT:
1151 it->dataProper =
1152 (char *) it->children + it->nElems * sizeof(JEntry) * 2;
1153 it->state = JBI_OBJECT_START;
1154 break;
1155
1156 default:
1157 elog(ERROR, "unknown type of jsonb container");
1158 }
1159
1160 return it;
1161}
#define palloc0_object(type)
Definition: fe_memutils.h:75
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:209
@ JBI_ARRAY_START
Definition: jsonb.h:361
@ JBI_OBJECT_START
Definition: jsonb.h:363
uint32 header
Definition: jsonb.h:194
JsonbIterState state
Definition: jsonb.h:393
JEntry * children
Definition: jsonb.h:375
uint32 nElems
Definition: jsonb.h:372
JsonbContainer * container
Definition: jsonb.h:371
bool isScalar
Definition: jsonb.h:374
char * dataProper
Definition: jsonb.h:377

References Assert(), JsonbContainer::children, JsonbIterator::children, JsonbIterator::container, JsonbIterator::dataProper, elog, ERROR, JsonbContainer::header, JsonbIterator::isScalar, JB_FARRAY, JB_FOBJECT, JBI_ARRAY_START, JBI_OBJECT_START, JsonContainerIsScalar, JsonContainerSize, JsonbIterator::nElems, palloc0_object, JsonbIterator::parent, and JsonbIterator::state.

Referenced by JsonbIteratorInit(), and JsonbIteratorNext().

◆ JsonbDeepContains()

bool JsonbDeepContains ( JsonbIterator **  val,
JsonbIterator **  mContained 
)

Definition at line 1189 of file jsonb_util.c.

1190{
1191 JsonbValue vval,
1192 vcontained;
1193 JsonbIteratorToken rval,
1194 rcont;
1195
1196 /*
1197 * Guard against stack overflow due to overly complex Jsonb.
1198 *
1199 * Functions called here independently take this precaution, but that
1200 * might not be sufficient since this is also a recursive function.
1201 */
1203
1204 rval = JsonbIteratorNext(val, &vval, false);
1205 rcont = JsonbIteratorNext(mContained, &vcontained, false);
1206
1207 if (rval != rcont)
1208 {
1209 /*
1210 * The differing return values can immediately be taken as indicating
1211 * two differing container types at this nesting level, which is
1212 * sufficient reason to give up entirely (but it should be the case
1213 * that they're both some container type).
1214 */
1215 Assert(rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY);
1216 Assert(rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY);
1217 return false;
1218 }
1219 else if (rcont == WJB_BEGIN_OBJECT)
1220 {
1221 Assert(vval.type == jbvObject);
1222 Assert(vcontained.type == jbvObject);
1223
1224 /*
1225 * If the lhs has fewer pairs than the rhs, it can't possibly contain
1226 * the rhs. (This conclusion is safe only because we de-duplicate
1227 * keys in all Jsonb objects; thus there can be no corresponding
1228 * optimization in the array case.) The case probably won't arise
1229 * often, but since it's such a cheap check we may as well make it.
1230 */
1231 if (vval.val.object.nPairs < vcontained.val.object.nPairs)
1232 return false;
1233
1234 /* Work through rhs "is it contained within?" object */
1235 for (;;)
1236 {
1237 JsonbValue *lhsVal; /* lhsVal is from pair in lhs object */
1238 JsonbValue lhsValBuf;
1239
1240 rcont = JsonbIteratorNext(mContained, &vcontained, false);
1241
1242 /*
1243 * When we get through caller's rhs "is it contained within?"
1244 * object without failing to find one of its values, it's
1245 * contained.
1246 */
1247 if (rcont == WJB_END_OBJECT)
1248 return true;
1249
1250 Assert(rcont == WJB_KEY);
1251 Assert(vcontained.type == jbvString);
1252
1253 /* First, find value by key... */
1254 lhsVal =
1255 getKeyJsonValueFromContainer((*val)->container,
1256 vcontained.val.string.val,
1257 vcontained.val.string.len,
1258 &lhsValBuf);
1259 if (!lhsVal)
1260 return false;
1261
1262 /*
1263 * ...at this stage it is apparent that there is at least a key
1264 * match for this rhs pair.
1265 */
1266 rcont = JsonbIteratorNext(mContained, &vcontained, true);
1267
1268 Assert(rcont == WJB_VALUE);
1269
1270 /*
1271 * Compare rhs pair's value with lhs pair's value just found using
1272 * key
1273 */
1274 if (lhsVal->type != vcontained.type)
1275 {
1276 return false;
1277 }
1278 else if (IsAJsonbScalar(lhsVal))
1279 {
1280 if (!equalsJsonbScalarValue(lhsVal, &vcontained))
1281 return false;
1282 }
1283 else
1284 {
1285 /* Nested container value (object or array) */
1286 JsonbIterator *nestval,
1287 *nestContained;
1288
1289 Assert(lhsVal->type == jbvBinary);
1290 Assert(vcontained.type == jbvBinary);
1291
1292 nestval = JsonbIteratorInit(lhsVal->val.binary.data);
1293 nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1294
1295 /*
1296 * Match "value" side of rhs datum object's pair recursively.
1297 * It's a nested structure.
1298 *
1299 * Note that nesting still has to "match up" at the right
1300 * nesting sub-levels. However, there need only be zero or
1301 * more matching pairs (or elements) at each nesting level
1302 * (provided the *rhs* pairs/elements *all* match on each
1303 * level), which enables searching nested structures for a
1304 * single String or other primitive type sub-datum quite
1305 * effectively (provided the user constructed the rhs nested
1306 * structure such that we "know where to look").
1307 *
1308 * In other words, the mapping of container nodes in the rhs
1309 * "vcontained" Jsonb to internal nodes on the lhs is
1310 * injective, and parent-child edges on the rhs must be mapped
1311 * to parent-child edges on the lhs to satisfy the condition
1312 * of containment (plus of course the mapped nodes must be
1313 * equal).
1314 */
1315 if (!JsonbDeepContains(&nestval, &nestContained))
1316 return false;
1317 }
1318 }
1319 }
1320 else if (rcont == WJB_BEGIN_ARRAY)
1321 {
1322 JsonbValue *lhsConts = NULL;
1323 uint32 nLhsElems = vval.val.array.nElems;
1324
1325 Assert(vval.type == jbvArray);
1326 Assert(vcontained.type == jbvArray);
1327
1328 /*
1329 * Handle distinction between "raw scalar" pseudo arrays, and real
1330 * arrays.
1331 *
1332 * A raw scalar may contain another raw scalar, and an array may
1333 * contain a raw scalar, but a raw scalar may not contain an array. We
1334 * don't do something like this for the object case, since objects can
1335 * only contain pairs, never raw scalars (a pair is represented by an
1336 * rhs object argument with a single contained pair).
1337 */
1338 if (vval.val.array.rawScalar && !vcontained.val.array.rawScalar)
1339 return false;
1340
1341 /* Work through rhs "is it contained within?" array */
1342 for (;;)
1343 {
1344 rcont = JsonbIteratorNext(mContained, &vcontained, true);
1345
1346 /*
1347 * When we get through caller's rhs "is it contained within?"
1348 * array without failing to find one of its values, it's
1349 * contained.
1350 */
1351 if (rcont == WJB_END_ARRAY)
1352 return true;
1353
1354 Assert(rcont == WJB_ELEM);
1355
1356 if (IsAJsonbScalar(&vcontained))
1357 {
1358 if (!findJsonbValueFromContainer((*val)->container,
1359 JB_FARRAY,
1360 &vcontained))
1361 return false;
1362 }
1363 else
1364 {
1365 uint32 i;
1366
1367 /*
1368 * If this is first container found in rhs array (at this
1369 * depth), initialize temp lhs array of containers
1370 */
1371 if (lhsConts == NULL)
1372 {
1373 uint32 j = 0;
1374
1375 /* Make room for all possible values */
1376 lhsConts = palloc_array(JsonbValue, nLhsElems);
1377
1378 for (i = 0; i < nLhsElems; i++)
1379 {
1380 /* Store all lhs elements in temp array */
1381 rcont = JsonbIteratorNext(val, &vval, true);
1382 Assert(rcont == WJB_ELEM);
1383
1384 if (vval.type == jbvBinary)
1385 lhsConts[j++] = vval;
1386 }
1387
1388 /* No container elements in temp array, so give up now */
1389 if (j == 0)
1390 return false;
1391
1392 /* We may have only partially filled array */
1393 nLhsElems = j;
1394 }
1395
1396 /* XXX: Nested array containment is O(N^2) */
1397 for (i = 0; i < nLhsElems; i++)
1398 {
1399 /* Nested container value (object or array) */
1400 JsonbIterator *nestval,
1401 *nestContained;
1402 bool contains;
1403
1404 nestval = JsonbIteratorInit(lhsConts[i].val.binary.data);
1405 nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1406
1407 contains = JsonbDeepContains(&nestval, &nestContained);
1408
1409 if (nestval)
1410 pfree(nestval);
1411 if (nestContained)
1412 pfree(nestContained);
1413 if (contains)
1414 break;
1415 }
1416
1417 /*
1418 * Report rhs container value is not contained if couldn't
1419 * match rhs container to *some* lhs cont
1420 */
1421 if (i == nLhsElems)
1422 return false;
1423 }
1424 }
1425 }
1426 else
1427 {
1428 elog(ERROR, "invalid jsonb container type");
1429 }
1430
1431 elog(ERROR, "unexpectedly fell off end of jsonb container");
1432 return false;
1433}
#define palloc_array(type, count)
Definition: fe_memutils.h:76
int j
Definition: isn.c:78
@ WJB_KEY
Definition: jsonb.h:23
@ WJB_VALUE
Definition: jsonb.h:24
@ WJB_ELEM
Definition: jsonb.h:25
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:348
bool JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
Definition: jsonb_util.c:1189

References Assert(), check_stack_depth(), elog, equalsJsonbScalarValue(), ERROR, findJsonbValueFromContainer(), getKeyJsonValueFromContainer(), i, IsAJsonbScalar, j, JB_FARRAY, jbvArray, jbvBinary, jbvObject, jbvString, JsonbDeepContains(), JsonbIteratorInit(), JsonbIteratorNext(), palloc_array, pfree(), JsonbValue::type, JsonbValue::val, val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by jsonb_contained(), jsonb_contains(), and JsonbDeepContains().

◆ JsonbHashScalarValue()

void JsonbHashScalarValue ( const JsonbValue scalarVal,
uint32 hash 
)

Definition at line 1443 of file jsonb_util.c.

1444{
1445 uint32 tmp;
1446
1447 /* Compute hash value for scalarVal */
1448 switch (scalarVal->type)
1449 {
1450 case jbvNull:
1451 tmp = 0x01;
1452 break;
1453 case jbvString:
1454 tmp = DatumGetUInt32(hash_any((const unsigned char *) scalarVal->val.string.val,
1455 scalarVal->val.string.len));
1456 break;
1457 case jbvNumeric:
1458 /* Must hash equal numerics to equal hash codes */
1460 NumericGetDatum(scalarVal->val.numeric)));
1461 break;
1462 case jbvBool:
1463 tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1464
1465 break;
1466 default:
1467 elog(ERROR, "invalid jsonb scalar type");
1468 tmp = 0; /* keep compiler quiet */
1469 break;
1470 }
1471
1472 /*
1473 * Combine hash values of successive keys, values and elements by rotating
1474 * the previous value left 1 bit, then XOR'ing in the new
1475 * key/value/element's hash value.
1476 */
1477 *hash = pg_rotate_left32(*hash, 1);
1478 *hash ^= tmp;
1479}
Datum hash_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2713
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:428
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:232
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715

References DatumGetUInt32(), DirectFunctionCall1, elog, ERROR, hash(), hash_any(), hash_numeric(), jbvBool, jbvNull, jbvNumeric, jbvString, NumericGetDatum(), pg_rotate_left32(), JsonbValue::type, and JsonbValue::val.

Referenced by gin_extract_jsonb_path(), jsonb_hash(), jsonb_path_ops__add_path_item(), and jsonb_path_ops__extract_nodes().

◆ JsonbHashScalarValueExtended()

void JsonbHashScalarValueExtended ( const JsonbValue scalarVal,
uint64 hash,
uint64  seed 
)

Definition at line 1486 of file jsonb_util.c.

1488{
1489 uint64 tmp;
1490
1491 switch (scalarVal->type)
1492 {
1493 case jbvNull:
1494 tmp = seed + 0x01;
1495 break;
1496 case jbvString:
1497 tmp = DatumGetUInt64(hash_any_extended((const unsigned char *) scalarVal->val.string.val,
1498 scalarVal->val.string.len,
1499 seed));
1500 break;
1501 case jbvNumeric:
1503 NumericGetDatum(scalarVal->val.numeric),
1504 UInt64GetDatum(seed)));
1505 break;
1506 case jbvBool:
1507 if (seed)
1509 BoolGetDatum(scalarVal->val.boolean),
1510 UInt64GetDatum(seed)));
1511 else
1512 tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1513
1514 break;
1515 default:
1516 elog(ERROR, "invalid jsonb scalar type");
1517 break;
1518 }
1519
1521 *hash ^= tmp;
1522}
Datum hash_numeric_extended(PG_FUNCTION_ARGS)
Definition: numeric.c:2793
uint64_t uint64
Definition: c.h:553
#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
Datum hashcharextended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:53
static uint64 DatumGetUInt64(Datum X)
Definition: postgres.h:413
static Datum UInt64GetDatum(uint64 X)
Definition: postgres.h:423
static Datum BoolGetDatum(bool X)
Definition: postgres.h:112

References BoolGetDatum(), DatumGetUInt64(), DirectFunctionCall2, elog, ERROR, hash(), hash_any_extended(), hash_numeric_extended(), hashcharextended(), jbvBool, jbvNull, jbvNumeric, jbvString, NumericGetDatum(), ROTATE_HIGH_AND_LOW_32BITS, JsonbValue::type, UInt64GetDatum(), and JsonbValue::val.

Referenced by jsonb_hash_extended().

◆ JsonbIteratorInit()

◆ JsonbIteratorNext()

JsonbIteratorToken JsonbIteratorNext ( JsonbIterator **  it,
JsonbValue val,
bool  skipNested 
)

Definition at line 973 of file jsonb_util.c.

974{
975 if (*it == NULL)
976 {
977 val->type = jbvNull;
978 return WJB_DONE;
979 }
980
981 /*
982 * When stepping into a nested container, we jump back here to start
983 * processing the child. We will not recurse further in one call, because
984 * processing the child will always begin in JBI_ARRAY_START or
985 * JBI_OBJECT_START state.
986 */
987recurse:
988 switch ((*it)->state)
989 {
990 case JBI_ARRAY_START:
991 /* Set v to array on first array call */
992 val->type = jbvArray;
993 val->val.array.nElems = (*it)->nElems;
994
995 /*
996 * v->val.array.elems is not actually set, because we aren't doing
997 * a full conversion
998 */
999 val->val.array.rawScalar = (*it)->isScalar;
1000 (*it)->curIndex = 0;
1001 (*it)->curDataOffset = 0;
1002 (*it)->curValueOffset = 0; /* not actually used */
1003 /* Set state for next call */
1004 (*it)->state = JBI_ARRAY_ELEM;
1005 return WJB_BEGIN_ARRAY;
1006
1007 case JBI_ARRAY_ELEM:
1008 if ((*it)->curIndex >= (*it)->nElems)
1009 {
1010 /*
1011 * All elements within array already processed. Report this
1012 * to caller, and give it back original parent iterator (which
1013 * independently tracks iteration progress at its level of
1014 * nesting).
1015 */
1016 *it = freeAndGetParent(*it);
1017 val->type = jbvNull;
1018 return WJB_END_ARRAY;
1019 }
1020
1021 fillJsonbValue((*it)->container, (*it)->curIndex,
1022 (*it)->dataProper, (*it)->curDataOffset,
1023 val);
1024
1025 JBE_ADVANCE_OFFSET((*it)->curDataOffset,
1026 (*it)->children[(*it)->curIndex]);
1027 (*it)->curIndex++;
1028
1029 if (!IsAJsonbScalar(val) && !skipNested)
1030 {
1031 /* Recurse into container. */
1032 *it = iteratorFromContainer(val->val.binary.data, *it);
1033 goto recurse;
1034 }
1035 else
1036 {
1037 /*
1038 * Scalar item in array, or a container and caller didn't want
1039 * us to recurse into it.
1040 */
1041 return WJB_ELEM;
1042 }
1043
1044 case JBI_OBJECT_START:
1045 /* Set v to object on first object call */
1046 val->type = jbvObject;
1047 val->val.object.nPairs = (*it)->nElems;
1048
1049 /*
1050 * v->val.object.pairs is not actually set, because we aren't
1051 * doing a full conversion
1052 */
1053 (*it)->curIndex = 0;
1054 (*it)->curDataOffset = 0;
1055 (*it)->curValueOffset = getJsonbOffset((*it)->container,
1056 (*it)->nElems);
1057 /* Set state for next call */
1058 (*it)->state = JBI_OBJECT_KEY;
1059 return WJB_BEGIN_OBJECT;
1060
1061 case JBI_OBJECT_KEY:
1062 if ((*it)->curIndex >= (*it)->nElems)
1063 {
1064 /*
1065 * All pairs within object already processed. Report this to
1066 * caller, and give it back original containing iterator
1067 * (which independently tracks iteration progress at its level
1068 * of nesting).
1069 */
1070 *it = freeAndGetParent(*it);
1071 val->type = jbvNull;
1072 return WJB_END_OBJECT;
1073 }
1074 else
1075 {
1076 /* Return key of a key/value pair. */
1077 fillJsonbValue((*it)->container, (*it)->curIndex,
1078 (*it)->dataProper, (*it)->curDataOffset,
1079 val);
1080 if (val->type != jbvString)
1081 elog(ERROR, "unexpected jsonb type as object key");
1082
1083 /* Set state for next call */
1084 (*it)->state = JBI_OBJECT_VALUE;
1085 return WJB_KEY;
1086 }
1087
1088 case JBI_OBJECT_VALUE:
1089 /* Set state for next call */
1090 (*it)->state = JBI_OBJECT_KEY;
1091
1092 fillJsonbValue((*it)->container, (*it)->curIndex + (*it)->nElems,
1093 (*it)->dataProper, (*it)->curValueOffset,
1094 val);
1095
1096 JBE_ADVANCE_OFFSET((*it)->curDataOffset,
1097 (*it)->children[(*it)->curIndex]);
1098 JBE_ADVANCE_OFFSET((*it)->curValueOffset,
1099 (*it)->children[(*it)->curIndex + (*it)->nElems]);
1100 (*it)->curIndex++;
1101
1102 /*
1103 * Value may be a container, in which case we recurse with new,
1104 * child iterator (unless the caller asked not to, by passing
1105 * skipNested).
1106 */
1107 if (!IsAJsonbScalar(val) && !skipNested)
1108 {
1109 *it = iteratorFromContainer(val->val.binary.data, *it);
1110 goto recurse;
1111 }
1112 else
1113 return WJB_VALUE;
1114 }
1115
1116 elog(ERROR, "invalid jsonb iterator state");
1117 /* satisfy compilers that don't know that elog(ERROR) doesn't return */
1118 val->type = jbvNull;
1119 return WJB_DONE;
1120}
@ JBI_OBJECT_VALUE
Definition: jsonb.h:365
@ JBI_ARRAY_ELEM
Definition: jsonb.h:362
@ JBI_OBJECT_KEY
Definition: jsonb.h:364
static JsonbIterator * freeAndGetParent(JsonbIterator *it)
Definition: jsonb_util.c:1168

References elog, ERROR, fillJsonbValue(), freeAndGetParent(), getJsonbOffset(), IsAJsonbScalar, iteratorFromContainer(), JBE_ADVANCE_OFFSET, JBI_ARRAY_ELEM, JBI_ARRAY_START, JBI_OBJECT_KEY, JBI_OBJECT_START, JBI_OBJECT_VALUE, jbvArray, jbvNull, jbvObject, jbvString, val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by compareJsonbContainers(), datum_to_jsonb_internal(), each_worker_jsonb(), elements_worker_jsonb(), executeAnyItem(), executeKeyValueMethod(), gin_extract_jsonb(), gin_extract_jsonb_path(), iterate_jsonb_values(), IteratorConcat(), jsonb_delete(), jsonb_delete_array(), jsonb_delete_idx(), jsonb_hash(), jsonb_hash_extended(), jsonb_object_keys(), jsonb_strip_nulls(), Jsonb_to_SV(), JsonbDeepContains(), JsonbExtractScalar(), JsonbToCStringWorker(), parse_jsonb_index_flags(), PLyObject_FromJsonbContainer(), populate_array_dim_jsonb(), populate_recordset_worker(), pushJsonbValue(), setPath(), setPathArray(), setPathObject(), and transform_jsonb_string_values().

◆ JsonbToJsonbValue()

void JsonbToJsonbValue ( Jsonb jsonb,
JsonbValue val 
)

Definition at line 76 of file jsonb_util.c.

77{
78 val->type = jbvBinary;
79 val->val.binary.data = &jsonb->root;
80 val->val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
81}
JsonbContainer root
Definition: jsonb.h:217
static Size VARSIZE(const void *PTR)
Definition: varatt.h:298

References jbvBinary, Jsonb::root, val, VARHDRSZ, and VARSIZE().

Referenced by jsonb_insert(), jsonb_set(), and jsonb_subscript_assign().

◆ JsonbValueToJsonb()

Jsonb * JsonbValueToJsonb ( JsonbValue val)

Definition at line 96 of file jsonb_util.c.

97{
98 Jsonb *out;
99
100 if (IsAJsonbScalar(val))
101 {
102 /* Scalar value, so wrap it in an array */
103 JsonbInState pstate = {0};
104 JsonbValue scalarArray;
105
106 scalarArray.type = jbvArray;
107 scalarArray.val.array.rawScalar = true;
108 scalarArray.val.array.nElems = 1;
109
110 pushJsonbValue(&pstate, WJB_BEGIN_ARRAY, &scalarArray);
111 pushJsonbValue(&pstate, WJB_ELEM, val);
112 pushJsonbValue(&pstate, WJB_END_ARRAY, NULL);
113
114 out = convertToJsonb(pstate.result);
115 }
116 else if (val->type == jbvObject || val->type == jbvArray)
117 {
118 out = convertToJsonb(val);
119 }
120 else
121 {
122 Assert(val->type == jbvBinary);
123 out = palloc(VARHDRSZ + val->val.binary.len);
124 SET_VARSIZE(out, VARHDRSZ + val->val.binary.len);
125 memcpy(VARDATA(out), val->val.binary.data, val->val.binary.len);
126 }
127
128 return out;
129}
void pushJsonbValue(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:583
static Jsonb * convertToJsonb(JsonbValue *val)
Definition: jsonb_util.c:1675
void * palloc(Size size)
Definition: mcxt.c:1365
JsonbValue * result
Definition: jsonb.h:333
static char * VARDATA(const void *PTR)
Definition: varatt.h:305

References Assert(), convertToJsonb(), IsAJsonbScalar, jbvArray, jbvBinary, jbvObject, palloc(), pushJsonbValue(), JsonbInState::result, SET_VARSIZE(), JsonbValue::type, JsonbValue::val, val, VARDATA(), VARHDRSZ, WJB_BEGIN_ARRAY, WJB_ELEM, and WJB_END_ARRAY.

Referenced by datum_to_jsonb(), each_worker_jsonb(), elements_worker_jsonb(), ExecEvalJsonExprPath(), ExecGetJsonValueItemString(), executeKeyValueMethod(), hstore_to_jsonb(), hstore_to_jsonb_loose(), jsonb_agg_finalfn(), jsonb_array_element(), jsonb_build_array_noargs(), jsonb_build_array_worker(), jsonb_build_object_noargs(), jsonb_build_object_worker(), jsonb_concat(), jsonb_delete(), jsonb_delete_array(), jsonb_delete_idx(), jsonb_delete_path(), jsonb_from_cstring(), jsonb_get_element(), jsonb_insert(), jsonb_object(), jsonb_object_agg_finalfn(), jsonb_object_field(), jsonb_object_two_arg(), jsonb_path_query_array_internal(), jsonb_path_query_first_internal(), jsonb_path_query_internal(), jsonb_set(), jsonb_set_element(), jsonb_strip_nulls(), jsonb_subscript_assign(), JsonPathQuery(), JsonTablePlanScanNextRow(), plperl_to_jsonb(), plpython_to_jsonb(), populate_scalar(), and transform_jsonb_string_values().

◆ lengthCompareJsonbPair()

static int lengthCompareJsonbPair ( const void *  a,
const void *  b,
void *  binequal 
)
static

Definition at line 2046 of file jsonb_util.c.

2047{
2048 const JsonbPair *pa = (const JsonbPair *) a;
2049 const JsonbPair *pb = (const JsonbPair *) b;
2050 int res;
2051
2052 res = lengthCompareJsonbStringValue(&pa->key, &pb->key);
2053 if (res == 0 && binequal)
2054 *((bool *) binequal) = true;
2055
2056 /*
2057 * Guarantee keeping order of equal pair. Unique algorithm will prefer
2058 * first element as value.
2059 */
2060 if (res == 0)
2061 res = (pa->order > pb->order) ? -1 : 1;
2062
2063 return res;
2064}

References a, b, JsonbPair::key, lengthCompareJsonbStringValue(), and JsonbPair::order.

Referenced by uniqueifyJsonbObject().

◆ lengthCompareJsonbString()

static int lengthCompareJsonbString ( const char *  val1,
int  len1,
const char *  val2,
int  len2 
)
static

Definition at line 2026 of file jsonb_util.c.

2027{
2028 if (len1 == len2)
2029 return memcmp(val1, val2, len1);
2030 else
2031 return len1 > len2 ? 1 : -1;
2032}

Referenced by getKeyJsonValueFromContainer(), and lengthCompareJsonbStringValue().

◆ lengthCompareJsonbStringValue()

static int lengthCompareJsonbStringValue ( const void *  a,
const void *  b 
)
static

Definition at line 2007 of file jsonb_util.c.

2008{
2009 const JsonbValue *va = (const JsonbValue *) a;
2010 const JsonbValue *vb = (const JsonbValue *) b;
2011
2012 Assert(va->type == jbvString);
2013 Assert(vb->type == jbvString);
2014
2015 return lengthCompareJsonbString(va->val.string.val, va->val.string.len,
2016 vb->val.string.val, vb->val.string.len);
2017}

References a, Assert(), b, jbvString, lengthCompareJsonbString(), JsonbValue::type, and JsonbValue::val.

Referenced by equalsJsonbScalarValue(), lengthCompareJsonbPair(), and uniqueifyJsonbObject().

◆ padBufferToInt()

static short padBufferToInt ( StringInfo  buffer)
static

Definition at line 1654 of file jsonb_util.c.

1655{
1656 int padlen,
1657 p,
1658 offset;
1659
1660 padlen = INTALIGN(buffer->len) - buffer->len;
1661
1662 offset = reserveFromBuffer(buffer, padlen);
1663
1664 /* padlen must be small, so this is probably faster than a memset */
1665 for (p = 0; p < padlen; p++)
1666 buffer->data[offset + p] = '\0';
1667
1668 return padlen;
1669}

References StringInfoData::data, INTALIGN, StringInfoData::len, and reserveFromBuffer().

Referenced by convertJsonbArray(), convertJsonbObject(), and convertJsonbScalar().

◆ pushJsonbValue()

void pushJsonbValue ( JsonbInState pstate,
JsonbIteratorToken  seq,
JsonbValue jbval 
)

Definition at line 583 of file jsonb_util.c.

585{
586 JsonbIterator *it;
587 JsonbValue v;
589 int i;
590
591 /*
592 * pushJsonbValueScalar handles all cases not involving pushing a
593 * container object as an ELEM or VALUE.
594 */
595 if (!jbval || IsAJsonbScalar(jbval) ||
596 (seq != WJB_ELEM && seq != WJB_VALUE))
597 {
598 pushJsonbValueScalar(pstate, seq, jbval);
599 return;
600 }
601
602 /* If an object or array is pushed, recursively push its contents */
603 if (jbval->type == jbvObject)
604 {
605 pushJsonbValue(pstate, WJB_BEGIN_OBJECT, NULL);
606 for (i = 0; i < jbval->val.object.nPairs; i++)
607 {
608 pushJsonbValue(pstate, WJB_KEY, &jbval->val.object.pairs[i].key);
609 pushJsonbValue(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value);
610 }
611 pushJsonbValue(pstate, WJB_END_OBJECT, NULL);
612 return;
613 }
614
615 if (jbval->type == jbvArray)
616 {
617 pushJsonbValue(pstate, WJB_BEGIN_ARRAY, NULL);
618 for (i = 0; i < jbval->val.array.nElems; i++)
619 {
620 pushJsonbValue(pstate, WJB_ELEM, &jbval->val.array.elems[i]);
621 }
622 pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
623 return;
624 }
625
626 /* Else it must be a jbvBinary value; push its contents */
627 Assert(jbval->type == jbvBinary);
628
629 it = JsonbIteratorInit(jbval->val.binary.data);
630
631 /* ... with a special case for pushing a raw scalar */
632 if ((jbval->val.binary.data->header & JB_FSCALAR) &&
633 pstate->parseState != NULL)
634 {
635 tok = JsonbIteratorNext(&it, &v, true);
636 Assert(tok == WJB_BEGIN_ARRAY);
637 Assert(v.type == jbvArray && v.val.array.rawScalar);
638
639 tok = JsonbIteratorNext(&it, &v, true);
640 Assert(tok == WJB_ELEM);
641
642 pushJsonbValueScalar(pstate, seq, &v);
643
644 tok = JsonbIteratorNext(&it, &v, true);
645 Assert(tok == WJB_END_ARRAY);
646 Assert(it == NULL);
647
648 return;
649 }
650
651 while ((tok = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
652 pushJsonbValueScalar(pstate, tok,
653 tok < WJB_BEGIN_ARRAY ||
654 (tok == WJB_BEGIN_ARRAY &&
655 v.val.array.rawScalar) ? &v : NULL);
656}
static void pushJsonbValueScalar(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *scalarVal)
Definition: jsonb_util.c:663

References Assert(), i, IsAJsonbScalar, JB_FSCALAR, jbvArray, jbvBinary, jbvObject, JsonbIteratorInit(), JsonbIteratorNext(), JsonbInState::parseState, pushJsonbValue(), pushJsonbValueScalar(), JsonbValue::type, JsonbValue::val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by array_dim_to_jsonb(), array_to_jsonb_internal(), AV_to_JsonbValue(), composite_to_jsonb(), datum_to_jsonb_internal(), executeKeyValueMethod(), hstore_to_jsonb(), hstore_to_jsonb_loose(), HV_to_JsonbValue(), IteratorConcat(), jsonb_agg_finalfn(), jsonb_agg_transfn_worker(), jsonb_build_array_noargs(), jsonb_build_array_worker(), jsonb_build_object_noargs(), jsonb_build_object_worker(), jsonb_delete(), jsonb_delete_array(), jsonb_delete_idx(), jsonb_in_array_end(), jsonb_in_array_start(), jsonb_in_object_end(), jsonb_in_object_field_start(), jsonb_in_object_start(), jsonb_in_scalar(), jsonb_object(), jsonb_object_agg_finalfn(), jsonb_object_agg_transfn_worker(), jsonb_object_two_arg(), jsonb_strip_nulls(), JsonbValueToJsonb(), PLyMapping_ToJsonbValue(), PLyObject_ToJsonbValue(), PLySequence_ToJsonbValue(), push_null_elements(), push_path(), pushJsonbValue(), setPath(), setPathArray(), setPathObject(), SV_to_JsonbValue(), transform_jsonb_string_values(), and wrapItemsInArray().

◆ pushJsonbValueScalar()

static void pushJsonbValueScalar ( JsonbInState pstate,
JsonbIteratorToken  seq,
JsonbValue scalarVal 
)
static

Definition at line 663 of file jsonb_util.c.

665{
666 JsonbParseState *ppstate;
668 MemoryContext outcontext;
669
670 switch (seq)
671 {
672 case WJB_BEGIN_ARRAY:
673 Assert(!scalarVal || scalarVal->val.array.rawScalar);
674 ppstate = pushState(pstate);
675 val = &ppstate->contVal;
676 val->type = jbvArray;
677 val->val.array.nElems = 0;
678 val->val.array.rawScalar = (scalarVal &&
679 scalarVal->val.array.rawScalar);
680 if (scalarVal && scalarVal->val.array.nElems > 0)
681 {
682 /* Assume that this array is still really a scalar */
683 Assert(scalarVal->type == jbvArray);
684 ppstate->size = scalarVal->val.array.nElems;
685 }
686 else
687 {
688 ppstate->size = 4; /* initial guess at array size */
689 }
690 outcontext = pstate->outcontext ? pstate->outcontext : CurrentMemoryContext;
691 val->val.array.elems = MemoryContextAlloc(outcontext,
692 sizeof(JsonbValue) *
693 ppstate->size);
694 break;
695 case WJB_BEGIN_OBJECT:
696 Assert(!scalarVal);
697 ppstate = pushState(pstate);
698 val = &ppstate->contVal;
699 val->type = jbvObject;
700 val->val.object.nPairs = 0;
701 ppstate->size = 4; /* initial guess at object size */
702 outcontext = pstate->outcontext ? pstate->outcontext : CurrentMemoryContext;
703 val->val.object.pairs = MemoryContextAlloc(outcontext,
704 sizeof(JsonbPair) *
705 ppstate->size);
706 break;
707 case WJB_KEY:
708 Assert(scalarVal->type == jbvString);
709 appendKey(pstate, scalarVal, true);
710 break;
711 case WJB_VALUE:
712 Assert(IsAJsonbScalar(scalarVal));
713 appendValue(pstate, scalarVal, true);
714 break;
715 case WJB_ELEM:
716 Assert(IsAJsonbScalar(scalarVal));
717 appendElement(pstate, scalarVal, true);
718 break;
719 case WJB_END_OBJECT:
720 ppstate = pstate->parseState;
722 ppstate->unique_keys,
723 ppstate->skip_nulls);
724 /* fall through! */
725 case WJB_END_ARRAY:
726 /* Steps here common to WJB_END_OBJECT case */
727 Assert(!scalarVal);
728 ppstate = pstate->parseState;
729 val = &ppstate->contVal;
730
731 /*
732 * Pop stack and push current array/object as value in parent
733 * array/object, or return it as the final result. We don't need
734 * to re-copy any scalars that are in the data structure.
735 */
736 pstate->parseState = ppstate = ppstate->next;
737 if (ppstate)
738 {
739 switch (ppstate->contVal.type)
740 {
741 case jbvArray:
742 appendElement(pstate, val, false);
743 break;
744 case jbvObject:
745 appendValue(pstate, val, false);
746 break;
747 default:
748 elog(ERROR, "invalid jsonb container type");
749 }
750 }
751 else
752 pstate->result = val;
753 break;
754 default:
755 elog(ERROR, "unrecognized jsonb sequential processing token");
756 }
757}
static void appendKey(JsonbInState *pstate, JsonbValue *string, bool needCopy)
Definition: jsonb_util.c:785
static void appendElement(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy)
Definition: jsonb_util.c:837
static void uniqueifyJsonbObject(JsonbValue *object, bool unique_keys, bool skip_nulls)
Definition: jsonb_util.c:2070
static void appendValue(JsonbInState *pstate, JsonbValue *scalarVal, bool needCopy)
Definition: jsonb_util.c:818
static JsonbParseState * pushState(JsonbInState *pstate)
Definition: jsonb_util.c:766
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
bool unique_keys
Definition: jsonb.h:351
JsonbParseState * next
Definition: jsonb.h:350
bool skip_nulls
Definition: jsonb.h:352

References appendElement(), appendKey(), appendValue(), Assert(), JsonbParseState::contVal, CurrentMemoryContext, elog, ERROR, IsAJsonbScalar, jbvArray, jbvObject, jbvString, MemoryContextAlloc(), JsonbParseState::next, JsonbInState::outcontext, JsonbInState::parseState, pushState(), JsonbInState::result, JsonbParseState::size, JsonbParseState::skip_nulls, JsonbValue::type, JsonbParseState::unique_keys, uniqueifyJsonbObject(), JsonbValue::val, val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by pushJsonbValue().

◆ pushState()

static JsonbParseState * pushState ( JsonbInState pstate)
static

Definition at line 766 of file jsonb_util.c.

767{
768 MemoryContext outcontext = pstate->outcontext ? pstate->outcontext : CurrentMemoryContext;
769 JsonbParseState *ns = MemoryContextAlloc(outcontext,
770 sizeof(JsonbParseState));
771
772 ns->next = pstate->parseState;
773 /* This module never changes these fields, but callers can: */
774 ns->unique_keys = false;
775 ns->skip_nulls = false;
776
777 pstate->parseState = ns;
778 return ns;
779}

References CurrentMemoryContext, MemoryContextAlloc(), JsonbParseState::next, JsonbInState::outcontext, JsonbInState::parseState, JsonbParseState::skip_nulls, and JsonbParseState::unique_keys.

Referenced by pushJsonbValueScalar().

◆ reserveFromBuffer()

static int reserveFromBuffer ( StringInfo  buffer,
int  len 
)
static

Definition at line 1605 of file jsonb_util.c.

1606{
1607 int offset;
1608
1609 /* Make more room if needed */
1610 enlargeStringInfo(buffer, len);
1611
1612 /* remember current offset */
1613 offset = buffer->len;
1614
1615 /* reserve the space */
1616 buffer->len += len;
1617
1618 /*
1619 * Keep a trailing null in place, even though it's not useful for us; it
1620 * seems best to preserve the invariants of StringInfos.
1621 */
1622 buffer->data[buffer->len] = '\0';
1623
1624 return offset;
1625}
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:337

References StringInfoData::data, enlargeStringInfo(), StringInfoData::len, and len.

Referenced by appendToBuffer(), convertJsonbArray(), convertJsonbObject(), convertToJsonb(), and padBufferToInt().

◆ uniqueifyJsonbObject()

static void uniqueifyJsonbObject ( JsonbValue object,
bool  unique_keys,
bool  skip_nulls 
)
static

Definition at line 2070 of file jsonb_util.c.

2071{
2072 bool hasNonUniq = false;
2073
2074 Assert(object->type == jbvObject);
2075
2076 if (object->val.object.nPairs > 1)
2077 qsort_arg(object->val.object.pairs, object->val.object.nPairs, sizeof(JsonbPair),
2078 lengthCompareJsonbPair, &hasNonUniq);
2079
2080 if (hasNonUniq && unique_keys)
2081 ereport(ERROR,
2082 errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
2083 errmsg("duplicate JSON object key value"));
2084
2085 if (hasNonUniq || skip_nulls)
2086 {
2087 JsonbPair *ptr,
2088 *res;
2089
2090 while (skip_nulls && object->val.object.nPairs > 0 &&
2091 object->val.object.pairs->value.type == jbvNull)
2092 {
2093 /* If skip_nulls is true, remove leading items with null */
2094 object->val.object.pairs++;
2095 object->val.object.nPairs--;
2096 }
2097
2098 if (object->val.object.nPairs > 0)
2099 {
2100 ptr = object->val.object.pairs + 1;
2101 res = object->val.object.pairs;
2102
2103 while (ptr - object->val.object.pairs < object->val.object.nPairs)
2104 {
2105 /* Avoid copying over duplicate or null */
2106 if (lengthCompareJsonbStringValue(ptr, res) != 0 &&
2107 (!skip_nulls || ptr->value.type != jbvNull))
2108 {
2109 res++;
2110 if (ptr != res)
2111 memcpy(res, ptr, sizeof(JsonbPair));
2112 }
2113 ptr++;
2114 }
2115
2116 object->val.object.nPairs = res + 1 - object->val.object.pairs;
2117 }
2118 }
2119}
static int lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
Definition: jsonb_util.c:2046
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)

References Assert(), ereport, errcode(), errmsg(), ERROR, jbvNull, jbvObject, lengthCompareJsonbPair(), lengthCompareJsonbStringValue(), qsort_arg(), JsonbValue::type, JsonbValue::val, and JsonbPair::value.

Referenced by pushJsonbValueScalar().