PostgreSQL Source Code  git master
jsonb_util.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/datetime.h"
#include "utils/hashutils.h"
#include "utils/jsonapi.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 char *data, int len)
 
static void copyToBuffer (StringInfo buffer, int offset, const char *data, int len)
 
static short padBufferToInt (StringInfo buffer)
 
static JsonbIteratoriteratorFromContainer (JsonbContainer *container, JsonbIterator *parent)
 
static JsonbIteratorfreeAndGetParent (JsonbIterator *it)
 
static JsonbParseStatepushState (JsonbParseState **pstate)
 
static void appendKey (JsonbParseState *pstate, JsonbValue *scalarVal)
 
static void appendValue (JsonbParseState *pstate, JsonbValue *scalarVal)
 
static void appendElement (JsonbParseState *pstate, JsonbValue *scalarVal)
 
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 *arg)
 
static void uniqueifyJsonbObject (JsonbValue *object)
 
static JsonbValuepushJsonbValueScalar (JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *scalarVal)
 
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)
 
JsonbValuepushJsonbValue (JsonbParseState **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 36 of file jsonb_util.c.

Referenced by appendElement().

◆ JSONB_MAX_PAIRS

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

Definition at line 37 of file jsonb_util.c.

Referenced by appendKey().

Function Documentation

◆ appendElement()

static void appendElement ( JsonbParseState pstate,
JsonbValue scalarVal 
)
static

Definition at line 730 of file jsonb_util.c.

References Assert, JsonbParseState::contVal, ereport, errcode(), errmsg(), ERROR, jbvArray, JSONB_MAX_ELEMS, repalloc(), JsonbParseState::size, JsonbValue::type, and JsonbValue::val.

Referenced by pushJsonbValueScalar().

731 {
732  JsonbValue *array = &pstate->contVal;
733 
734  Assert(array->type == jbvArray);
735 
736  if (array->val.array.nElems >= JSONB_MAX_ELEMS)
737  ereport(ERROR,
738  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
739  errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
740  JSONB_MAX_ELEMS)));
741 
742  if (array->val.array.nElems >= pstate->size)
743  {
744  pstate->size *= 2;
745  array->val.array.elems = repalloc(array->val.array.elems,
746  sizeof(JsonbValue) * pstate->size);
747  }
748 
749  array->val.array.elems[array->val.array.nElems++] = *scalarVal;
750 }
char * val
Definition: jsonb.h:272
int errcode(int sqlerrcode)
Definition: elog.c:570
#define JSONB_MAX_ELEMS
Definition: jsonb_util.c:36
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
JsonbValue contVal
Definition: jsonb.h:329
#define Assert(condition)
Definition: c.h:732
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
enum jbvType type
Definition: jsonb.h:263
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ appendKey()

static void appendKey ( JsonbParseState pstate,
JsonbValue scalarVal 
)
static

Definition at line 688 of file jsonb_util.c.

References Assert, JsonbParseState::contVal, ereport, errcode(), errmsg(), ERROR, jbvObject, jbvString, JSONB_MAX_PAIRS, repalloc(), JsonbParseState::size, JsonbValue::type, and JsonbValue::val.

Referenced by pushJsonbValueScalar().

689 {
690  JsonbValue *object = &pstate->contVal;
691 
692  Assert(object->type == jbvObject);
693  Assert(string->type == jbvString);
694 
695  if (object->val.object.nPairs >= JSONB_MAX_PAIRS)
696  ereport(ERROR,
697  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
698  errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
699  JSONB_MAX_PAIRS)));
700 
701  if (object->val.object.nPairs >= pstate->size)
702  {
703  pstate->size *= 2;
704  object->val.object.pairs = repalloc(object->val.object.pairs,
705  sizeof(JsonbPair) * pstate->size);
706  }
707 
708  object->val.object.pairs[object->val.object.nPairs].key = *string;
709  object->val.object.pairs[object->val.object.nPairs].order = object->val.object.nPairs;
710 }
char * val
Definition: jsonb.h:272
int errcode(int sqlerrcode)
Definition: elog.c:570
#define JSONB_MAX_PAIRS
Definition: jsonb_util.c:37
#define ERROR
Definition: elog.h:43
char string[11]
Definition: preproc-type.c:46
#define ereport(elevel, rest)
Definition: elog.h:141
JsonbValue contVal
Definition: jsonb.h:329
#define Assert(condition)
Definition: c.h:732
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
enum jbvType type
Definition: jsonb.h:263
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ appendToBuffer()

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

Definition at line 1455 of file jsonb_util.c.

References copyToBuffer(), and reserveFromBuffer().

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

1456 {
1457  int offset;
1458 
1459  offset = reserveFromBuffer(buffer, len);
1460  copyToBuffer(buffer, offset, data, len);
1461 }
static int reserveFromBuffer(StringInfo buffer, int len)
Definition: jsonb_util.c:1420
static void copyToBuffer(StringInfo buffer, int offset, const char *data, int len)
Definition: jsonb_util.c:1446

◆ appendValue()

static void appendValue ( JsonbParseState pstate,
JsonbValue scalarVal 
)
static

Definition at line 717 of file jsonb_util.c.

References Assert, JsonbParseState::contVal, jbvObject, and JsonbValue::type.

Referenced by pushJsonbValueScalar().

718 {
719  JsonbValue *object = &pstate->contVal;
720 
721  Assert(object->type == jbvObject);
722 
723  object->val.object.pairs[object->val.object.nPairs++].value = *scalarVal;
724 }
JsonbValue contVal
Definition: jsonb.h:329
#define Assert(condition)
Definition: c.h:732
enum jbvType type
Definition: jsonb.h:263

◆ compareJsonbContainers()

int compareJsonbContainers ( JsonbContainer a,
JsonbContainer b 
)

Definition at line 183 of file jsonb_util.c.

References Assert, 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().

184 {
185  JsonbIterator *ita,
186  *itb;
187  int res = 0;
188 
189  ita = JsonbIteratorInit(a);
190  itb = JsonbIteratorInit(b);
191 
192  do
193  {
194  JsonbValue va,
195  vb;
197  rb;
198 
199  ra = JsonbIteratorNext(&ita, &va, false);
200  rb = JsonbIteratorNext(&itb, &vb, false);
201 
202  if (ra == rb)
203  {
204  if (ra == WJB_DONE)
205  {
206  /* Decisively equal */
207  break;
208  }
209 
210  if (ra == WJB_END_ARRAY || ra == WJB_END_OBJECT)
211  {
212  /*
213  * There is no array or object to compare at this stage of
214  * processing. jbvArray/jbvObject values are compared
215  * initially, at the WJB_BEGIN_ARRAY and WJB_BEGIN_OBJECT
216  * tokens.
217  */
218  continue;
219  }
220 
221  if (va.type == vb.type)
222  {
223  switch (va.type)
224  {
225  case jbvString:
226  case jbvNull:
227  case jbvNumeric:
228  case jbvBool:
229  res = compareJsonbScalarValue(&va, &vb);
230  break;
231  case jbvArray:
232 
233  /*
234  * This could be a "raw scalar" pseudo array. That's
235  * a special case here though, since we still want the
236  * general type-based comparisons to apply, and as far
237  * as we're concerned a pseudo array is just a scalar.
238  */
239  if (va.val.array.rawScalar != vb.val.array.rawScalar)
240  res = (va.val.array.rawScalar) ? -1 : 1;
241  if (va.val.array.nElems != vb.val.array.nElems)
242  res = (va.val.array.nElems > vb.val.array.nElems) ? 1 : -1;
243  break;
244  case jbvObject:
245  if (va.val.object.nPairs != vb.val.object.nPairs)
246  res = (va.val.object.nPairs > vb.val.object.nPairs) ? 1 : -1;
247  break;
248  case jbvBinary:
249  elog(ERROR, "unexpected jbvBinary value");
250  break;
251  case jbvDatetime:
252  elog(ERROR, "unexpected jbvDatetime value");
253  break;
254  }
255  }
256  else
257  {
258  /* Type-defined order */
259  res = (va.type > vb.type) ? 1 : -1;
260  }
261  }
262  else
263  {
264  /*
265  * It's safe to assume that the types differed, and that the va
266  * and vb values passed were set.
267  *
268  * If the two values were of the same container type, then there'd
269  * have been a chance to observe the variation in the number of
270  * elements/pairs (when processing WJB_BEGIN_OBJECT, say). They're
271  * either two heterogeneously-typed containers, or a container and
272  * some scalar type.
273  *
274  * We don't have to consider the WJB_END_ARRAY and WJB_END_OBJECT
275  * cases here, because we would have seen the corresponding
276  * WJB_BEGIN_ARRAY and WJB_BEGIN_OBJECT tokens first, and
277  * concluded that they don't match.
278  */
279  Assert(ra != WJB_END_ARRAY && ra != WJB_END_OBJECT);
280  Assert(rb != WJB_END_ARRAY && rb != WJB_END_OBJECT);
281 
282  Assert(va.type != vb.type);
283  Assert(va.type != jbvBinary);
284  Assert(vb.type != jbvBinary);
285  /* Type-defined order */
286  res = (va.type > vb.type) ? 1 : -1;
287  }
288  }
289  while (res == 0);
290 
291  while (ita != NULL)
292  {
293  JsonbIterator *i = ita->parent;
294 
295  pfree(ita);
296  ita = i;
297  }
298  while (itb != NULL)
299  {
300  JsonbIterator *i = itb->parent;
301 
302  pfree(itb);
303  itb = i;
304  }
305 
306  return res;
307 }
char * val
Definition: jsonb.h:272
Definition: jsonb.h:239
Definition: jsonb.h:22
Definition: jsonb.h:236
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
JsonbIteratorToken
Definition: jsonb.h:20
static int compareJsonbScalarValue(JsonbValue *a, JsonbValue *b)
Definition: jsonb_util.c:1375
#define Assert(condition)
Definition: c.h:732
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:759
struct JsonbIterator * parent
Definition: jsonb.h:374
enum jbvType type
Definition: jsonb.h:263
#define elog(elevel,...)
Definition: elog.h:226
int i
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:795

◆ compareJsonbScalarValue()

static int compareJsonbScalarValue ( JsonbValue a,
JsonbValue b 
)
static

Definition at line 1375 of file jsonb_util.c.

References DatumGetInt32, DirectFunctionCall2, elog, ERROR, jbvBool, jbvNull, jbvNumeric, jbvString, numeric_cmp(), PointerGetDatum, JsonbValue::type, JsonbValue::val, and varstr_cmp().

Referenced by compareJsonbContainers().

1376 {
1377  if (aScalar->type == bScalar->type)
1378  {
1379  switch (aScalar->type)
1380  {
1381  case jbvNull:
1382  return 0;
1383  case jbvString:
1384  return varstr_cmp(aScalar->val.string.val,
1385  aScalar->val.string.len,
1386  bScalar->val.string.val,
1387  bScalar->val.string.len,
1388  DEFAULT_COLLATION_OID);
1389  case jbvNumeric:
1391  PointerGetDatum(aScalar->val.numeric),
1392  PointerGetDatum(bScalar->val.numeric)));
1393  case jbvBool:
1394  if (aScalar->val.boolean == bScalar->val.boolean)
1395  return 0;
1396  else if (aScalar->val.boolean > bScalar->val.boolean)
1397  return 1;
1398  else
1399  return -1;
1400  default:
1401  elog(ERROR, "invalid jsonb scalar type");
1402  }
1403  }
1404  elog(ERROR, "jsonb scalar type mismatch");
1405  return -1;
1406 }
#define DatumGetInt32(X)
Definition: postgres.h:472
#define PointerGetDatum(X)
Definition: postgres.h:556
Definition: jsonb.h:239
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2046
Definition: jsonb.h:236
#define ERROR
Definition: elog.h:43
int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid)
Definition: varlena.c:1474
#define elog(elevel,...)
Definition: elog.h:226
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619

◆ convertJsonbArray()

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

Definition at line 1557 of file jsonb_util.c.

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

Referenced by convertJsonbValue().

1558 {
1559  int base_offset;
1560  int jentry_offset;
1561  int i;
1562  int totallen;
1563  uint32 header;
1564  int nElems = val->val.array.nElems;
1565 
1566  /* Remember where in the buffer this array starts. */
1567  base_offset = buffer->len;
1568 
1569  /* Align to 4-byte boundary (any padding counts as part of my data) */
1570  padBufferToInt(buffer);
1571 
1572  /*
1573  * Construct the header Jentry and store it in the beginning of the
1574  * variable-length payload.
1575  */
1576  header = nElems | JB_FARRAY;
1577  if (val->val.array.rawScalar)
1578  {
1579  Assert(nElems == 1);
1580  Assert(level == 0);
1581  header |= JB_FSCALAR;
1582  }
1583 
1584  appendToBuffer(buffer, (char *) &header, sizeof(uint32));
1585 
1586  /* Reserve space for the JEntries of the elements. */
1587  jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nElems);
1588 
1589  totallen = 0;
1590  for (i = 0; i < nElems; i++)
1591  {
1592  JsonbValue *elem = &val->val.array.elems[i];
1593  int len;
1594  JEntry meta;
1595 
1596  /*
1597  * Convert element, producing a JEntry and appending its
1598  * variable-length data to buffer
1599  */
1600  convertJsonbValue(buffer, &meta, elem, level + 1);
1601 
1602  len = JBE_OFFLENFLD(meta);
1603  totallen += len;
1604 
1605  /*
1606  * Bail out if total variable-length data exceeds what will fit in a
1607  * JEntry length field. We check this in each iteration, not just
1608  * once at the end, to forestall possible integer overflow.
1609  */
1610  if (totallen > JENTRY_OFFLENMASK)
1611  ereport(ERROR,
1612  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1613  errmsg("total size of jsonb array elements exceeds the maximum of %u bytes",
1614  JENTRY_OFFLENMASK)));
1615 
1616  /*
1617  * Convert each JB_OFFSET_STRIDE'th length to an offset.
1618  */
1619  if ((i % JB_OFFSET_STRIDE) == 0)
1620  meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1621 
1622  copyToBuffer(buffer, jentry_offset, (char *) &meta, sizeof(JEntry));
1623  jentry_offset += sizeof(JEntry);
1624  }
1625 
1626  /* Total data size is everything we've appended to buffer */
1627  totallen = buffer->len - base_offset;
1628 
1629  /* Check length again, since we didn't include the metadata above */
1630  if (totallen > JENTRY_OFFLENMASK)
1631  ereport(ERROR,
1632  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1633  errmsg("total size of jsonb array elements exceeds the maximum of %u bytes",
1634  JENTRY_OFFLENMASK)));
1635 
1636  /* Initialize the header of this node in the container's JEntry array */
1637  *pheader = JENTRY_ISCONTAINER | totallen;
1638 }
#define JB_FARRAY
Definition: jsonb.h:211
static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1532
char * val
Definition: jsonb.h:272
static void appendToBuffer(StringInfo buffer, const char *data, int len)
Definition: jsonb_util.c:1455
int errcode(int sqlerrcode)
Definition: elog.c:570
#define JENTRY_OFFLENMASK
Definition: jsonb.h:146
#define JBE_OFFLENFLD(je_)
Definition: jsonb.h:159
#define JB_OFFSET_STRIDE
Definition: jsonb.h:186
#define ERROR
Definition: elog.h:43
#define JB_FSCALAR
Definition: jsonb.h:209
#define JENTRY_TYPEMASK
Definition: jsonb.h:147
static int reserveFromBuffer(StringInfo buffer, int len)
Definition: jsonb_util.c:1420
unsigned int uint32
Definition: c.h:358
#define ereport(elevel, rest)
Definition: elog.h:141
static short padBufferToInt(StringInfo buffer)
Definition: jsonb_util.c:1469
static void copyToBuffer(StringInfo buffer, int offset, const char *data, int len)
Definition: jsonb_util.c:1446
#define JENTRY_ISCONTAINER
Definition: jsonb.h:156
#define Assert(condition)
Definition: c.h:732
uint32 JEntry
Definition: jsonb.h:144
#define JENTRY_HAS_OFF
Definition: jsonb.h:148
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:210
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i

◆ convertJsonbObject()

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

Definition at line 1641 of file jsonb_util.c.

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

Referenced by convertJsonbValue().

1642 {
1643  int base_offset;
1644  int jentry_offset;
1645  int i;
1646  int totallen;
1647  uint32 header;
1648  int nPairs = val->val.object.nPairs;
1649 
1650  /* Remember where in the buffer this object starts. */
1651  base_offset = buffer->len;
1652 
1653  /* Align to 4-byte boundary (any padding counts as part of my data) */
1654  padBufferToInt(buffer);
1655 
1656  /*
1657  * Construct the header Jentry and store it in the beginning of the
1658  * variable-length payload.
1659  */
1660  header = nPairs | JB_FOBJECT;
1661  appendToBuffer(buffer, (char *) &header, sizeof(uint32));
1662 
1663  /* Reserve space for the JEntries of the keys and values. */
1664  jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nPairs * 2);
1665 
1666  /*
1667  * Iterate over the keys, then over the values, since that is the ordering
1668  * we want in the on-disk representation.
1669  */
1670  totallen = 0;
1671  for (i = 0; i < nPairs; i++)
1672  {
1673  JsonbPair *pair = &val->val.object.pairs[i];
1674  int len;
1675  JEntry meta;
1676 
1677  /*
1678  * Convert key, producing a JEntry and appending its variable-length
1679  * data to buffer
1680  */
1681  convertJsonbScalar(buffer, &meta, &pair->key);
1682 
1683  len = JBE_OFFLENFLD(meta);
1684  totallen += len;
1685 
1686  /*
1687  * Bail out if total variable-length data exceeds what will fit in a
1688  * JEntry length field. We check this in each iteration, not just
1689  * once at the end, to forestall possible integer overflow.
1690  */
1691  if (totallen > JENTRY_OFFLENMASK)
1692  ereport(ERROR,
1693  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1694  errmsg("total size of jsonb object elements exceeds the maximum of %u bytes",
1695  JENTRY_OFFLENMASK)));
1696 
1697  /*
1698  * Convert each JB_OFFSET_STRIDE'th length to an offset.
1699  */
1700  if ((i % JB_OFFSET_STRIDE) == 0)
1701  meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1702 
1703  copyToBuffer(buffer, jentry_offset, (char *) &meta, sizeof(JEntry));
1704  jentry_offset += sizeof(JEntry);
1705  }
1706  for (i = 0; i < nPairs; i++)
1707  {
1708  JsonbPair *pair = &val->val.object.pairs[i];
1709  int len;
1710  JEntry meta;
1711 
1712  /*
1713  * Convert value, producing a JEntry and appending its variable-length
1714  * data to buffer
1715  */
1716  convertJsonbValue(buffer, &meta, &pair->value, level + 1);
1717 
1718  len = JBE_OFFLENFLD(meta);
1719  totallen += len;
1720 
1721  /*
1722  * Bail out if total variable-length data exceeds what will fit in a
1723  * JEntry length field. We check this in each iteration, not just
1724  * once at the end, to forestall possible integer overflow.
1725  */
1726  if (totallen > JENTRY_OFFLENMASK)
1727  ereport(ERROR,
1728  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1729  errmsg("total size of jsonb object elements exceeds the maximum of %u bytes",
1730  JENTRY_OFFLENMASK)));
1731 
1732  /*
1733  * Convert each JB_OFFSET_STRIDE'th length to an offset.
1734  */
1735  if (((i + nPairs) % JB_OFFSET_STRIDE) == 0)
1736  meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1737 
1738  copyToBuffer(buffer, jentry_offset, (char *) &meta, sizeof(JEntry));
1739  jentry_offset += sizeof(JEntry);
1740  }
1741 
1742  /* Total data size is everything we've appended to buffer */
1743  totallen = buffer->len - base_offset;
1744 
1745  /* Check length again, since we didn't include the metadata above */
1746  if (totallen > JENTRY_OFFLENMASK)
1747  ereport(ERROR,
1748  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1749  errmsg("total size of jsonb object elements exceeds the maximum of %u bytes",
1750  JENTRY_OFFLENMASK)));
1751 
1752  /* Initialize the header of this node in the container's JEntry array */
1753  *pheader = JENTRY_ISCONTAINER | totallen;
1754 }
static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1532
char * val
Definition: jsonb.h:272
static void appendToBuffer(StringInfo buffer, const char *data, int len)
Definition: jsonb_util.c:1455
int errcode(int sqlerrcode)
Definition: elog.c:570
#define JENTRY_OFFLENMASK
Definition: jsonb.h:146
#define JBE_OFFLENFLD(je_)
Definition: jsonb.h:159
#define JB_OFFSET_STRIDE
Definition: jsonb.h:186
#define ERROR
Definition: elog.h:43
#define JENTRY_TYPEMASK
Definition: jsonb.h:147
static int reserveFromBuffer(StringInfo buffer, int len)
Definition: jsonb_util.c:1420
unsigned int uint32
Definition: c.h:358
JsonbValue key
Definition: jsonb.h:321
#define ereport(elevel, rest)
Definition: elog.h:141
static void convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal)
Definition: jsonb_util.c:1757
static short padBufferToInt(StringInfo buffer)
Definition: jsonb_util.c:1469
static void copyToBuffer(StringInfo buffer, int offset, const char *data, int len)
Definition: jsonb_util.c:1446
#define JENTRY_ISCONTAINER
Definition: jsonb.h:156
#define JB_FOBJECT
Definition: jsonb.h:210
uint32 JEntry
Definition: jsonb.h:144
#define JENTRY_HAS_OFF
Definition: jsonb.h:148
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:210
JsonbValue value
Definition: jsonb.h:322
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i

◆ convertJsonbScalar()

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

Definition at line 1757 of file jsonb_util.c.

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

Referenced by convertJsonbObject(), and convertJsonbValue().

1758 {
1759  int numlen;
1760  short padlen;
1761 
1762  switch (scalarVal->type)
1763  {
1764  case jbvNull:
1765  *jentry = JENTRY_ISNULL;
1766  break;
1767 
1768  case jbvString:
1769  appendToBuffer(buffer, scalarVal->val.string.val, scalarVal->val.string.len);
1770 
1771  *jentry = scalarVal->val.string.len;
1772  break;
1773 
1774  case jbvNumeric:
1775  /* replace numeric NaN with string "NaN" */
1776  if (numeric_is_nan(scalarVal->val.numeric))
1777  {
1778  appendToBuffer(buffer, "NaN", 3);
1779  *jentry = 3;
1780  break;
1781  }
1782 
1783  numlen = VARSIZE_ANY(scalarVal->val.numeric);
1784  padlen = padBufferToInt(buffer);
1785 
1786  appendToBuffer(buffer, (char *) scalarVal->val.numeric, numlen);
1787 
1788  *jentry = JENTRY_ISNUMERIC | (padlen + numlen);
1789  break;
1790 
1791  case jbvBool:
1792  *jentry = (scalarVal->val.boolean) ?
1794  break;
1795 
1796  case jbvDatetime:
1797  {
1798  char buf[MAXDATELEN + 1];
1799  size_t len;
1800 
1801  JsonEncodeDateTime(buf,
1802  scalarVal->val.datetime.value,
1803  scalarVal->val.datetime.typid,
1804  &scalarVal->val.datetime.tz);
1805  len = strlen(buf);
1806  appendToBuffer(buffer, buf, len);
1807 
1808  *jentry = len;
1809  }
1810  break;
1811 
1812  default:
1813  elog(ERROR, "invalid jsonb scalar type");
1814  }
1815 }
#define MAXDATELEN
Definition: datetime.h:201
#define JENTRY_ISNULL
Definition: jsonb.h:155
char * val
Definition: jsonb.h:272
static void appendToBuffer(StringInfo buffer, const char *data, int len)
Definition: jsonb_util.c:1455
Definition: jsonb.h:239
Definition: jsonb.h:236
#define JENTRY_ISNUMERIC
Definition: jsonb.h:152
#define ERROR
Definition: elog.h:43
bool numeric_is_nan(Numeric num)
Definition: numeric.c:683
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:1557
static char * buf
Definition: pg_test_fsync.c:68
static short padBufferToInt(StringInfo buffer)
Definition: jsonb_util.c:1469
#define VARSIZE_ANY(PTR)
Definition: postgres.h:335
enum jbvType type
Definition: jsonb.h:263
#define JENTRY_ISBOOL_TRUE
Definition: jsonb.h:154
#define JENTRY_ISBOOL_FALSE
Definition: jsonb.h:153
#define elog(elevel,...)
Definition: elog.h:226

◆ convertJsonbValue()

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

Definition at line 1532 of file jsonb_util.c.

References check_stack_depth(), convertJsonbArray(), convertJsonbObject(), convertJsonbScalar(), elog, ERROR, IsAJsonbScalar, jbvArray, jbvObject, and JsonbValue::type.

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

1533 {
1535 
1536  if (!val)
1537  return;
1538 
1539  /*
1540  * A JsonbValue passed as val should never have a type of jbvBinary, and
1541  * neither should any of its sub-components. Those values will be produced
1542  * by convertJsonbArray and convertJsonbObject, the results of which will
1543  * not be passed back to this function as an argument.
1544  */
1545 
1546  if (IsAJsonbScalar(val))
1547  convertJsonbScalar(buffer, header, val);
1548  else if (val->type == jbvArray)
1549  convertJsonbArray(buffer, header, val, level);
1550  else if (val->type == jbvObject)
1551  convertJsonbObject(buffer, header, val, level);
1552  else
1553  elog(ERROR, "unknown type of jsonb container to convert");
1554 }
#define ERROR
Definition: elog.h:43
void check_stack_depth(void)
Definition: postgres.c:3262
static void convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1557
static void convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal)
Definition: jsonb_util.c:1757
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:305
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:210
enum jbvType type
Definition: jsonb.h:263
#define elog(elevel,...)
Definition: elog.h:226
static void convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1641

◆ convertToJsonb()

static Jsonb * convertToJsonb ( JsonbValue val)
static

Definition at line 1490 of file jsonb_util.c.

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

Referenced by JsonbValueToJsonb().

1491 {
1492  StringInfoData buffer;
1493  JEntry jentry;
1494  Jsonb *res;
1495 
1496  /* Should not already have binary representation */
1497  Assert(val->type != jbvBinary);
1498 
1499  /* Allocate an output buffer. It will be enlarged as needed */
1500  initStringInfo(&buffer);
1501 
1502  /* Make room for the varlena header */
1503  reserveFromBuffer(&buffer, VARHDRSZ);
1504 
1505  convertJsonbValue(&buffer, &jentry, val, 0);
1506 
1507  /*
1508  * Note: the JEntry of the root is discarded. Therefore the root
1509  * JsonbContainer struct must contain enough information to tell what kind
1510  * of value it is.
1511  */
1512 
1513  res = (Jsonb *) buffer.data;
1514 
1515  SET_VARSIZE(res, buffer.len);
1516 
1517  return res;
1518 }
Definition: jsonb.h:220
#define VARHDRSZ
Definition: c.h:555
static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1532
static int reserveFromBuffer(StringInfo buffer, int len)
Definition: jsonb_util.c:1420
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define Assert(condition)
Definition: c.h:732
uint32 JEntry
Definition: jsonb.h:144
enum jbvType type
Definition: jsonb.h:263
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329

◆ copyToBuffer()

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

Definition at line 1446 of file jsonb_util.c.

References StringInfoData::data.

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

1447 {
1448  memcpy(buffer->data + offset, data, len);
1449 }

◆ equalsJsonbScalarValue()

static bool equalsJsonbScalarValue ( JsonbValue a,
JsonbValue b 
)
static

Definition at line 1343 of file jsonb_util.c.

References DatumGetBool, DirectFunctionCall2, elog, ERROR, jbvBool, jbvNull, jbvNumeric, jbvString, lengthCompareJsonbStringValue(), numeric_eq(), PointerGetDatum, JsonbValue::type, and JsonbValue::val.

Referenced by findJsonbValueFromContainer(), and JsonbDeepContains().

1344 {
1345  if (aScalar->type == bScalar->type)
1346  {
1347  switch (aScalar->type)
1348  {
1349  case jbvNull:
1350  return true;
1351  case jbvString:
1352  return lengthCompareJsonbStringValue(aScalar, bScalar) == 0;
1353  case jbvNumeric:
1355  PointerGetDatum(aScalar->val.numeric),
1356  PointerGetDatum(bScalar->val.numeric)));
1357  case jbvBool:
1358  return aScalar->val.boolean == bScalar->val.boolean;
1359 
1360  default:
1361  elog(ERROR, "invalid jsonb scalar type");
1362  }
1363  }
1364  elog(ERROR, "jsonb scalar type mismatch");
1365  return false;
1366 }
#define PointerGetDatum(X)
Definition: postgres.h:556
Definition: jsonb.h:239
Definition: jsonb.h:236
Datum numeric_eq(PG_FUNCTION_ARGS)
Definition: numeric.c:2062
#define ERROR
Definition: elog.h:43
#define DatumGetBool(X)
Definition: postgres.h:393
#define elog(elevel,...)
Definition: elog.h:226
static int lengthCompareJsonbStringValue(const void *a, const void *b)
Definition: jsonb_util.c:1830
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619

◆ fillJsonbValue()

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

Definition at line 497 of file jsonb_util.c.

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().

500 {
501  JEntry entry = container->children[index];
502 
503  if (JBE_ISNULL(entry))
504  {
505  result->type = jbvNull;
506  }
507  else if (JBE_ISSTRING(entry))
508  {
509  result->type = jbvString;
510  result->val.string.val = base_addr + offset;
511  result->val.string.len = getJsonbLength(container, index);
512  Assert(result->val.string.len >= 0);
513  }
514  else if (JBE_ISNUMERIC(entry))
515  {
516  result->type = jbvNumeric;
517  result->val.numeric = (Numeric) (base_addr + INTALIGN(offset));
518  }
519  else if (JBE_ISBOOL_TRUE(entry))
520  {
521  result->type = jbvBool;
522  result->val.boolean = true;
523  }
524  else if (JBE_ISBOOL_FALSE(entry))
525  {
526  result->type = jbvBool;
527  result->val.boolean = false;
528  }
529  else
530  {
531  Assert(JBE_ISCONTAINER(entry));
532  result->type = jbvBinary;
533  /* Remove alignment padding from data pointer and length */
534  result->val.binary.data = (JsonbContainer *) (base_addr + INTALIGN(offset));
535  result->val.binary.len = getJsonbLength(container, index) -
536  (INTALIGN(offset) - offset);
537  }
538 }
JEntry children[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb.h:202
#define JBE_ISCONTAINER(je_)
Definition: jsonb.h:163
char * val
Definition: jsonb.h:272
#define JBE_ISBOOL_TRUE(je_)
Definition: jsonb.h:165
Definition: jsonb.h:239
uint32 getJsonbLength(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:151
Definition: jsonb.h:236
#define INTALIGN(LEN)
Definition: c.h:682
struct NumericData * Numeric
Definition: numeric.h:43
#define JBE_ISSTRING(je_)
Definition: jsonb.h:161
Definition: type.h:89
#define Assert(condition)
Definition: c.h:732
#define JBE_ISNUMERIC(je_)
Definition: jsonb.h:162
uint32 JEntry
Definition: jsonb.h:144
#define JBE_ISNULL(je_)
Definition: jsonb.h:164
enum jbvType type
Definition: jsonb.h:263
#define JBE_ISBOOL_FALSE(je_)
Definition: jsonb.h:166

◆ findJsonbValueFromContainer()

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

Definition at line 336 of file jsonb_util.c.

References Assert, JsonbContainer::children, equalsJsonbScalarValue(), fillJsonbValue(), getKeyJsonValueFromContainer(), i, JB_FARRAY, JB_FOBJECT, JBE_ADVANCE_OFFSET, jbvString, JsonContainerIsArray, JsonContainerIsObject, JsonContainerSize, palloc(), pfree(), JsonbValue::type, and JsonbValue::val.

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

338 {
339  JEntry *children = container->children;
340  int count = JsonContainerSize(container);
341 
342  Assert((flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);
343 
344  /* Quick out without a palloc cycle if object/array is empty */
345  if (count <= 0)
346  return NULL;
347 
348  if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
349  {
350  JsonbValue *result = palloc(sizeof(JsonbValue));
351  char *base_addr = (char *) (children + count);
352  uint32 offset = 0;
353  int i;
354 
355  for (i = 0; i < count; i++)
356  {
357  fillJsonbValue(container, i, base_addr, offset, result);
358 
359  if (key->type == result->type)
360  {
361  if (equalsJsonbScalarValue(key, result))
362  return result;
363  }
364 
365  JBE_ADVANCE_OFFSET(offset, children[i]);
366  }
367 
368  pfree(result);
369  }
370  else if ((flags & JB_FOBJECT) && JsonContainerIsObject(container))
371  {
372  /* Object key passed by caller must be a string */
373  Assert(key->type == jbvString);
374 
375  return getKeyJsonValueFromContainer(container, key->val.string.val,
376  key->val.string.len, NULL);
377  }
378 
379  /* Not found */
380  return NULL;
381 }
JEntry children[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb.h:202
#define JB_FARRAY
Definition: jsonb.h:211
char * val
Definition: jsonb.h:272
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:390
#define JBE_ADVANCE_OFFSET(offset, je)
Definition: jsonb.h:170
void pfree(void *pointer)
Definition: mcxt.c:1056
#define JsonContainerSize(jc)
Definition: jsonb.h:214
unsigned int uint32
Definition: c.h:358
static void fillJsonbValue(JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
Definition: jsonb_util.c:497
#define JsonContainerIsArray(jc)
Definition: jsonb.h:217
static bool equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b)
Definition: jsonb_util.c:1343
#define JsonContainerIsObject(jc)
Definition: jsonb.h:216
#define Assert(condition)
Definition: c.h:732
#define JB_FOBJECT
Definition: jsonb.h:210
uint32 JEntry
Definition: jsonb.h:144
enum jbvType type
Definition: jsonb.h:263
void * palloc(Size size)
Definition: mcxt.c:949
int i

◆ freeAndGetParent()

static JsonbIterator * freeAndGetParent ( JsonbIterator it)
static

Definition at line 983 of file jsonb_util.c.

References JsonbIterator::parent, and pfree().

Referenced by JsonbIteratorNext().

984 {
985  JsonbIterator *v = it->parent;
986 
987  pfree(it);
988  return v;
989 }
void pfree(void *pointer)
Definition: mcxt.c:1056
struct JsonbIterator * parent
Definition: jsonb.h:374

◆ getIthJsonbValueFromContainer()

JsonbValue* getIthJsonbValueFromContainer ( JsonbContainer container,
uint32  i 
)

Definition at line 460 of file jsonb_util.c.

References JsonbContainer::children, elog, ERROR, fillJsonbValue(), getJsonbOffset(), JsonContainerIsArray, JsonContainerSize, and palloc().

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

461 {
462  JsonbValue *result;
463  char *base_addr;
464  uint32 nelements;
465 
466  if (!JsonContainerIsArray(container))
467  elog(ERROR, "not a jsonb array");
468 
469  nelements = JsonContainerSize(container);
470  base_addr = (char *) &container->children[nelements];
471 
472  if (i >= nelements)
473  return NULL;
474 
475  result = palloc(sizeof(JsonbValue));
476 
477  fillJsonbValue(container, i, base_addr,
478  getJsonbOffset(container, i),
479  result);
480 
481  return result;
482 }
JEntry children[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb.h:202
uint32 getJsonbOffset(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:126
#define ERROR
Definition: elog.h:43
#define JsonContainerSize(jc)
Definition: jsonb.h:214
unsigned int uint32
Definition: c.h:358
static void fillJsonbValue(JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
Definition: jsonb_util.c:497
#define JsonContainerIsArray(jc)
Definition: jsonb.h:217
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:226
int i

◆ getJsonbLength()

uint32 getJsonbLength ( const JsonbContainer jc,
int  index 
)

Definition at line 151 of file jsonb_util.c.

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

Referenced by fillJsonbValue(), and getKeyJsonValueFromContainer().

152 {
153  uint32 off;
154  uint32 len;
155 
156  /*
157  * If the length is stored directly in the JEntry, just return it.
158  * Otherwise, get the begin offset of the entry, and subtract that from
159  * the stored end+1 offset.
160  */
161  if (JBE_HAS_OFF(jc->children[index]))
162  {
163  off = getJsonbOffset(jc, index);
164  len = JBE_OFFLENFLD(jc->children[index]) - off;
165  }
166  else
167  len = JBE_OFFLENFLD(jc->children[index]);
168 
169  return len;
170 }
JEntry children[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb.h:202
uint32 getJsonbOffset(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:126
#define JBE_OFFLENFLD(je_)
Definition: jsonb.h:159
Definition: type.h:89
unsigned int uint32
Definition: c.h:358
#define JBE_HAS_OFF(je_)
Definition: jsonb.h:160

◆ getJsonbOffset()

uint32 getJsonbOffset ( const JsonbContainer jc,
int  index 
)

Definition at line 126 of file jsonb_util.c.

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

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

127 {
128  uint32 offset = 0;
129  int i;
130 
131  /*
132  * Start offset of this entry is equal to the end offset of the previous
133  * entry. Walk backwards to the most recent entry stored as an end
134  * offset, returning that offset plus any lengths in between.
135  */
136  for (i = index - 1; i >= 0; i--)
137  {
138  offset += JBE_OFFLENFLD(jc->children[i]);
139  if (JBE_HAS_OFF(jc->children[i]))
140  break;
141  }
142 
143  return offset;
144 }
JEntry children[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb.h:202
#define JBE_OFFLENFLD(je_)
Definition: jsonb.h:159
Definition: type.h:89
unsigned int uint32
Definition: c.h:358
#define JBE_HAS_OFF(je_)
Definition: jsonb.h:160
int i

◆ getKeyJsonValueFromContainer()

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

Definition at line 390 of file jsonb_util.c.

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

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

392 {
393  JEntry *children = container->children;
394  int count = JsonContainerSize(container);
395  char *baseAddr;
396  uint32 stopLow,
397  stopHigh;
398 
399  Assert(JsonContainerIsObject(container));
400 
401  /* Quick out without a palloc cycle if object is empty */
402  if (count <= 0)
403  return NULL;
404 
405  /*
406  * Binary search the container. Since we know this is an object, account
407  * for *Pairs* of Jentrys
408  */
409  baseAddr = (char *) (children + count * 2);
410  stopLow = 0;
411  stopHigh = count;
412  while (stopLow < stopHigh)
413  {
414  uint32 stopMiddle;
415  int difference;
416  const char *candidateVal;
417  int candidateLen;
418 
419  stopMiddle = stopLow + (stopHigh - stopLow) / 2;
420 
421  candidateVal = baseAddr + getJsonbOffset(container, stopMiddle);
422  candidateLen = getJsonbLength(container, stopMiddle);
423 
424  difference = lengthCompareJsonbString(candidateVal, candidateLen,
425  keyVal, keyLen);
426 
427  if (difference == 0)
428  {
429  /* Found our key, return corresponding value */
430  int index = stopMiddle + count;
431 
432  if (!res)
433  res = palloc(sizeof(JsonbValue));
434 
435  fillJsonbValue(container, index, baseAddr,
436  getJsonbOffset(container, index),
437  res);
438 
439  return res;
440  }
441  else
442  {
443  if (difference < 0)
444  stopLow = stopMiddle + 1;
445  else
446  stopHigh = stopMiddle;
447  }
448  }
449 
450  /* Not found */
451  return NULL;
452 }
JEntry children[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb.h:202
uint32 getJsonbOffset(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:126
uint32 getJsonbLength(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:151
static int lengthCompareJsonbString(const char *val1, int len1, const char *val2, int len2)
Definition: jsonb_util.c:1849
Definition: type.h:89
#define JsonContainerSize(jc)
Definition: jsonb.h:214
unsigned int uint32
Definition: c.h:358
static void fillJsonbValue(JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
Definition: jsonb_util.c:497
#define JsonContainerIsObject(jc)
Definition: jsonb.h:216
Datum difference(PG_FUNCTION_ARGS)
#define Assert(condition)
Definition: c.h:732
uint32 JEntry
Definition: jsonb.h:144
void * palloc(Size size)
Definition: mcxt.c:949

◆ iteratorFromContainer()

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

Definition at line 941 of file jsonb_util.c.

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(), JsonbIterator::parent, and JsonbIterator::state.

Referenced by JsonbIteratorInit(), and JsonbIteratorNext().

942 {
943  JsonbIterator *it;
944 
945  it = palloc0(sizeof(JsonbIterator));
946  it->container = container;
947  it->parent = parent;
948  it->nElems = JsonContainerSize(container);
949 
950  /* Array starts just after header */
951  it->children = container->children;
952 
953  switch (container->header & (JB_FARRAY | JB_FOBJECT))
954  {
955  case JB_FARRAY:
956  it->dataProper =
957  (char *) it->children + it->nElems * sizeof(JEntry);
958  it->isScalar = JsonContainerIsScalar(container);
959  /* This is either a "raw scalar", or an array */
960  Assert(!it->isScalar || it->nElems == 1);
961 
962  it->state = JBI_ARRAY_START;
963  break;
964 
965  case JB_FOBJECT:
966  it->dataProper =
967  (char *) it->children + it->nElems * sizeof(JEntry) * 2;
968  it->state = JBI_OBJECT_START;
969  break;
970 
971  default:
972  elog(ERROR, "unknown type of jsonb container");
973  }
974 
975  return it;
976 }
JsonbIterState state
Definition: jsonb.h:372
JEntry children[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonb.h:202
#define JB_FARRAY
Definition: jsonb.h:211
JEntry * children
Definition: jsonb.h:354
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:215
#define ERROR
Definition: elog.h:43
JsonbContainer * container
Definition: jsonb.h:350
#define JsonContainerSize(jc)
Definition: jsonb.h:214
uint32 header
Definition: jsonb.h:200
void * palloc0(Size size)
Definition: mcxt.c:980
bool isScalar
Definition: jsonb.h:353
#define Assert(condition)
Definition: c.h:732
#define JB_FOBJECT
Definition: jsonb.h:210
struct JsonbIterator * parent
Definition: jsonb.h:374
uint32 JEntry
Definition: jsonb.h:144
char * dataProper
Definition: jsonb.h:356
#define elog(elevel,...)
Definition: elog.h:226
uint32 nElems
Definition: jsonb.h:351

◆ JsonbDeepContains()

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

Definition at line 1004 of file jsonb_util.c.

References Assert, check_stack_depth(), elog, equalsJsonbScalarValue(), ERROR, findJsonbValueFromContainer(), getKeyJsonValueFromContainer(), i, IsAJsonbScalar, JB_FARRAY, jbvArray, jbvBinary, jbvObject, jbvString, JsonbDeepContains(), JsonbIteratorInit(), JsonbIteratorNext(), palloc(), pfree(), JsonbValue::type, JsonbValue::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().

1005 {
1006  JsonbValue vval,
1007  vcontained;
1008  JsonbIteratorToken rval,
1009  rcont;
1010 
1011  /*
1012  * Guard against stack overflow due to overly complex Jsonb.
1013  *
1014  * Functions called here independently take this precaution, but that
1015  * might not be sufficient since this is also a recursive function.
1016  */
1018 
1019  rval = JsonbIteratorNext(val, &vval, false);
1020  rcont = JsonbIteratorNext(mContained, &vcontained, false);
1021 
1022  if (rval != rcont)
1023  {
1024  /*
1025  * The differing return values can immediately be taken as indicating
1026  * two differing container types at this nesting level, which is
1027  * sufficient reason to give up entirely (but it should be the case
1028  * that they're both some container type).
1029  */
1030  Assert(rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY);
1031  Assert(rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY);
1032  return false;
1033  }
1034  else if (rcont == WJB_BEGIN_OBJECT)
1035  {
1036  Assert(vval.type == jbvObject);
1037  Assert(vcontained.type == jbvObject);
1038 
1039  /*
1040  * If the lhs has fewer pairs than the rhs, it can't possibly contain
1041  * the rhs. (This conclusion is safe only because we de-duplicate
1042  * keys in all Jsonb objects; thus there can be no corresponding
1043  * optimization in the array case.) The case probably won't arise
1044  * often, but since it's such a cheap check we may as well make it.
1045  */
1046  if (vval.val.object.nPairs < vcontained.val.object.nPairs)
1047  return false;
1048 
1049  /* Work through rhs "is it contained within?" object */
1050  for (;;)
1051  {
1052  JsonbValue *lhsVal; /* lhsVal is from pair in lhs object */
1053  JsonbValue lhsValBuf;
1054 
1055  rcont = JsonbIteratorNext(mContained, &vcontained, false);
1056 
1057  /*
1058  * When we get through caller's rhs "is it contained within?"
1059  * object without failing to find one of its values, it's
1060  * contained.
1061  */
1062  if (rcont == WJB_END_OBJECT)
1063  return true;
1064 
1065  Assert(rcont == WJB_KEY);
1066  Assert(vcontained.type == jbvString);
1067 
1068  /* First, find value by key... */
1069  lhsVal =
1070  getKeyJsonValueFromContainer((*val)->container,
1071  vcontained.val.string.val,
1072  vcontained.val.string.len,
1073  &lhsValBuf);
1074  if (!lhsVal)
1075  return false;
1076 
1077  /*
1078  * ...at this stage it is apparent that there is at least a key
1079  * match for this rhs pair.
1080  */
1081  rcont = JsonbIteratorNext(mContained, &vcontained, true);
1082 
1083  Assert(rcont == WJB_VALUE);
1084 
1085  /*
1086  * Compare rhs pair's value with lhs pair's value just found using
1087  * key
1088  */
1089  if (lhsVal->type != vcontained.type)
1090  {
1091  return false;
1092  }
1093  else if (IsAJsonbScalar(lhsVal))
1094  {
1095  if (!equalsJsonbScalarValue(lhsVal, &vcontained))
1096  return false;
1097  }
1098  else
1099  {
1100  /* Nested container value (object or array) */
1101  JsonbIterator *nestval,
1102  *nestContained;
1103 
1104  Assert(lhsVal->type == jbvBinary);
1105  Assert(vcontained.type == jbvBinary);
1106 
1107  nestval = JsonbIteratorInit(lhsVal->val.binary.data);
1108  nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1109 
1110  /*
1111  * Match "value" side of rhs datum object's pair recursively.
1112  * It's a nested structure.
1113  *
1114  * Note that nesting still has to "match up" at the right
1115  * nesting sub-levels. However, there need only be zero or
1116  * more matching pairs (or elements) at each nesting level
1117  * (provided the *rhs* pairs/elements *all* match on each
1118  * level), which enables searching nested structures for a
1119  * single String or other primitive type sub-datum quite
1120  * effectively (provided the user constructed the rhs nested
1121  * structure such that we "know where to look").
1122  *
1123  * In other words, the mapping of container nodes in the rhs
1124  * "vcontained" Jsonb to internal nodes on the lhs is
1125  * injective, and parent-child edges on the rhs must be mapped
1126  * to parent-child edges on the lhs to satisfy the condition
1127  * of containment (plus of course the mapped nodes must be
1128  * equal).
1129  */
1130  if (!JsonbDeepContains(&nestval, &nestContained))
1131  return false;
1132  }
1133  }
1134  }
1135  else if (rcont == WJB_BEGIN_ARRAY)
1136  {
1137  JsonbValue *lhsConts = NULL;
1138  uint32 nLhsElems = vval.val.array.nElems;
1139 
1140  Assert(vval.type == jbvArray);
1141  Assert(vcontained.type == jbvArray);
1142 
1143  /*
1144  * Handle distinction between "raw scalar" pseudo arrays, and real
1145  * arrays.
1146  *
1147  * A raw scalar may contain another raw scalar, and an array may
1148  * contain a raw scalar, but a raw scalar may not contain an array. We
1149  * don't do something like this for the object case, since objects can
1150  * only contain pairs, never raw scalars (a pair is represented by an
1151  * rhs object argument with a single contained pair).
1152  */
1153  if (vval.val.array.rawScalar && !vcontained.val.array.rawScalar)
1154  return false;
1155 
1156  /* Work through rhs "is it contained within?" array */
1157  for (;;)
1158  {
1159  rcont = JsonbIteratorNext(mContained, &vcontained, true);
1160 
1161  /*
1162  * When we get through caller's rhs "is it contained within?"
1163  * array without failing to find one of its values, it's
1164  * contained.
1165  */
1166  if (rcont == WJB_END_ARRAY)
1167  return true;
1168 
1169  Assert(rcont == WJB_ELEM);
1170 
1171  if (IsAJsonbScalar(&vcontained))
1172  {
1173  if (!findJsonbValueFromContainer((*val)->container,
1174  JB_FARRAY,
1175  &vcontained))
1176  return false;
1177  }
1178  else
1179  {
1180  uint32 i;
1181 
1182  /*
1183  * If this is first container found in rhs array (at this
1184  * depth), initialize temp lhs array of containers
1185  */
1186  if (lhsConts == NULL)
1187  {
1188  uint32 j = 0;
1189 
1190  /* Make room for all possible values */
1191  lhsConts = palloc(sizeof(JsonbValue) * nLhsElems);
1192 
1193  for (i = 0; i < nLhsElems; i++)
1194  {
1195  /* Store all lhs elements in temp array */
1196  rcont = JsonbIteratorNext(val, &vval, true);
1197  Assert(rcont == WJB_ELEM);
1198 
1199  if (vval.type == jbvBinary)
1200  lhsConts[j++] = vval;
1201  }
1202 
1203  /* No container elements in temp array, so give up now */
1204  if (j == 0)
1205  return false;
1206 
1207  /* We may have only partially filled array */
1208  nLhsElems = j;
1209  }
1210 
1211  /* XXX: Nested array containment is O(N^2) */
1212  for (i = 0; i < nLhsElems; i++)
1213  {
1214  /* Nested container value (object or array) */
1215  JsonbIterator *nestval,
1216  *nestContained;
1217  bool contains;
1218 
1219  nestval = JsonbIteratorInit(lhsConts[i].val.binary.data);
1220  nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1221 
1222  contains = JsonbDeepContains(&nestval, &nestContained);
1223 
1224  if (nestval)
1225  pfree(nestval);
1226  if (nestContained)
1227  pfree(nestContained);
1228  if (contains)
1229  break;
1230  }
1231 
1232  /*
1233  * Report rhs container value is not contained if couldn't
1234  * match rhs container to *some* lhs cont
1235  */
1236  if (i == nLhsElems)
1237  return false;
1238  }
1239  }
1240  }
1241  else
1242  {
1243  elog(ERROR, "invalid jsonb container type");
1244  }
1245 
1246  elog(ERROR, "unexpectedly fell off end of jsonb container");
1247  return false;
1248 }
#define JB_FARRAY
Definition: jsonb.h:211
bool JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
Definition: jsonb_util.c:1004
char * val
Definition: jsonb.h:272
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:390
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
void check_stack_depth(void)
Definition: postgres.c:3262
unsigned int uint32
Definition: c.h:358
Definition: jsonb.h:23
static bool equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b)
Definition: jsonb_util.c:1343
JsonbIteratorToken
Definition: jsonb.h:20
#define Assert(condition)
Definition: c.h:732
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:759
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:305
enum jbvType type
Definition: jsonb.h:263
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:226
int i
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:336
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:795
Definition: jsonb.h:25

◆ JsonbHashScalarValue()

void JsonbHashScalarValue ( const JsonbValue scalarVal,
uint32 hash 
)

Definition at line 1258 of file jsonb_util.c.

References DatumGetUInt32, DirectFunctionCall1, elog, ERROR, hash_any(), hash_numeric(), jbvBool, jbvNull, jbvNumeric, jbvString, NumericGetDatum, 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().

1259 {
1260  uint32 tmp;
1261 
1262  /* Compute hash value for scalarVal */
1263  switch (scalarVal->type)
1264  {
1265  case jbvNull:
1266  tmp = 0x01;
1267  break;
1268  case jbvString:
1269  tmp = DatumGetUInt32(hash_any((const unsigned char *) scalarVal->val.string.val,
1270  scalarVal->val.string.len));
1271  break;
1272  case jbvNumeric:
1273  /* Must hash equal numerics to equal hash codes */
1275  NumericGetDatum(scalarVal->val.numeric)));
1276  break;
1277  case jbvBool:
1278  tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1279 
1280  break;
1281  default:
1282  elog(ERROR, "invalid jsonb scalar type");
1283  tmp = 0; /* keep compiler quiet */
1284  break;
1285  }
1286 
1287  /*
1288  * Combine hash values of successive keys, values and elements by rotating
1289  * the previous value left 1 bit, then XOR'ing in the new
1290  * key/value/element's hash value.
1291  */
1292  *hash = (*hash << 1) | (*hash >> 31);
1293  *hash ^= tmp;
1294 }
#define DatumGetUInt32(X)
Definition: postgres.h:486
Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.c:148
Datum hash_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2259
char * val
Definition: jsonb.h:272
#define NumericGetDatum(X)
Definition: numeric.h:51
Definition: jsonb.h:239
Definition: jsonb.h:236
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:617
#define ERROR
Definition: elog.h:43
unsigned int uint32
Definition: c.h:358
enum jbvType type
Definition: jsonb.h:263
#define elog(elevel,...)
Definition: elog.h:226
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:541

◆ JsonbHashScalarValueExtended()

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

Definition at line 1301 of file jsonb_util.c.

References BoolGetDatum, DatumGetUInt64, DirectFunctionCall2, elog, ERROR, 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().

1303 {
1304  uint64 tmp;
1305 
1306  switch (scalarVal->type)
1307  {
1308  case jbvNull:
1309  tmp = seed + 0x01;
1310  break;
1311  case jbvString:
1312  tmp = DatumGetUInt64(hash_any_extended((const unsigned char *) scalarVal->val.string.val,
1313  scalarVal->val.string.len,
1314  seed));
1315  break;
1316  case jbvNumeric:
1318  NumericGetDatum(scalarVal->val.numeric),
1319  UInt64GetDatum(seed)));
1320  break;
1321  case jbvBool:
1322  if (seed)
1324  BoolGetDatum(scalarVal->val.boolean),
1325  UInt64GetDatum(seed)));
1326  else
1327  tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1328 
1329  break;
1330  default:
1331  elog(ERROR, "invalid jsonb scalar type");
1332  break;
1333  }
1334 
1336  *hash ^= tmp;
1337 }
Datum hash_numeric_extended(PG_FUNCTION_ARGS)
Definition: numeric.c:2339
#define UInt64GetDatum(X)
Definition: postgres.h:648
char * val
Definition: jsonb.h:272
#define NumericGetDatum(X)
Definition: numeric.h:51
Definition: jsonb.h:239
Definition: jsonb.h:236
Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.c:374
#define ERROR
Definition: elog.h:43
#define ROTATE_HIGH_AND_LOW_32BITS(v)
Definition: hashutils.h:18
#define BoolGetDatum(X)
Definition: postgres.h:402
#define DatumGetUInt64(X)
Definition: postgres.h:634
enum jbvType type
Definition: jsonb.h:263
Datum hashcharextended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:53
#define elog(elevel,...)
Definition: elog.h:226
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:541
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619

◆ JsonbIteratorInit()

◆ JsonbIteratorNext()

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

Definition at line 795 of file jsonb_util.c.

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, jbvObject, jbvString, 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 addJsonbToParseState(), compareJsonbContainers(), datum_to_jsonb(), each_worker_jsonb(), elements_worker_jsonb(), executeAnyItem(), executeKeyValueMethod(), gin_extract_jsonb(), gin_extract_jsonb_path(), iterate_jsonb_values(), IteratorConcat(), jsonb_agg_transfn(), jsonb_delete(), jsonb_delete_array(), jsonb_delete_idx(), jsonb_hash(), jsonb_hash_extended(), jsonb_object_agg_transfn(), 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().

796 {
797  if (*it == NULL)
798  return WJB_DONE;
799 
800  /*
801  * When stepping into a nested container, we jump back here to start
802  * processing the child. We will not recurse further in one call, because
803  * processing the child will always begin in JBI_ARRAY_START or
804  * JBI_OBJECT_START state.
805  */
806 recurse:
807  switch ((*it)->state)
808  {
809  case JBI_ARRAY_START:
810  /* Set v to array on first array call */
811  val->type = jbvArray;
812  val->val.array.nElems = (*it)->nElems;
813 
814  /*
815  * v->val.array.elems is not actually set, because we aren't doing
816  * a full conversion
817  */
818  val->val.array.rawScalar = (*it)->isScalar;
819  (*it)->curIndex = 0;
820  (*it)->curDataOffset = 0;
821  (*it)->curValueOffset = 0; /* not actually used */
822  /* Set state for next call */
823  (*it)->state = JBI_ARRAY_ELEM;
824  return WJB_BEGIN_ARRAY;
825 
826  case JBI_ARRAY_ELEM:
827  if ((*it)->curIndex >= (*it)->nElems)
828  {
829  /*
830  * All elements within array already processed. Report this
831  * to caller, and give it back original parent iterator (which
832  * independently tracks iteration progress at its level of
833  * nesting).
834  */
835  *it = freeAndGetParent(*it);
836  return WJB_END_ARRAY;
837  }
838 
839  fillJsonbValue((*it)->container, (*it)->curIndex,
840  (*it)->dataProper, (*it)->curDataOffset,
841  val);
842 
843  JBE_ADVANCE_OFFSET((*it)->curDataOffset,
844  (*it)->children[(*it)->curIndex]);
845  (*it)->curIndex++;
846 
847  if (!IsAJsonbScalar(val) && !skipNested)
848  {
849  /* Recurse into container. */
850  *it = iteratorFromContainer(val->val.binary.data, *it);
851  goto recurse;
852  }
853  else
854  {
855  /*
856  * Scalar item in array, or a container and caller didn't want
857  * us to recurse into it.
858  */
859  return WJB_ELEM;
860  }
861 
862  case JBI_OBJECT_START:
863  /* Set v to object on first object call */
864  val->type = jbvObject;
865  val->val.object.nPairs = (*it)->nElems;
866 
867  /*
868  * v->val.object.pairs is not actually set, because we aren't
869  * doing a full conversion
870  */
871  (*it)->curIndex = 0;
872  (*it)->curDataOffset = 0;
873  (*it)->curValueOffset = getJsonbOffset((*it)->container,
874  (*it)->nElems);
875  /* Set state for next call */
876  (*it)->state = JBI_OBJECT_KEY;
877  return WJB_BEGIN_OBJECT;
878 
879  case JBI_OBJECT_KEY:
880  if ((*it)->curIndex >= (*it)->nElems)
881  {
882  /*
883  * All pairs within object already processed. Report this to
884  * caller, and give it back original containing iterator
885  * (which independently tracks iteration progress at its level
886  * of nesting).
887  */
888  *it = freeAndGetParent(*it);
889  return WJB_END_OBJECT;
890  }
891  else
892  {
893  /* Return key of a key/value pair. */
894  fillJsonbValue((*it)->container, (*it)->curIndex,
895  (*it)->dataProper, (*it)->curDataOffset,
896  val);
897  if (val->type != jbvString)
898  elog(ERROR, "unexpected jsonb type as object key");
899 
900  /* Set state for next call */
901  (*it)->state = JBI_OBJECT_VALUE;
902  return WJB_KEY;
903  }
904 
905  case JBI_OBJECT_VALUE:
906  /* Set state for next call */
907  (*it)->state = JBI_OBJECT_KEY;
908 
909  fillJsonbValue((*it)->container, (*it)->curIndex + (*it)->nElems,
910  (*it)->dataProper, (*it)->curValueOffset,
911  val);
912 
913  JBE_ADVANCE_OFFSET((*it)->curDataOffset,
914  (*it)->children[(*it)->curIndex]);
915  JBE_ADVANCE_OFFSET((*it)->curValueOffset,
916  (*it)->children[(*it)->curIndex + (*it)->nElems]);
917  (*it)->curIndex++;
918 
919  /*
920  * Value may be a container, in which case we recurse with new,
921  * child iterator (unless the caller asked not to, by passing
922  * skipNested).
923  */
924  if (!IsAJsonbScalar(val) && !skipNested)
925  {
926  *it = iteratorFromContainer(val->val.binary.data, *it);
927  goto recurse;
928  }
929  else
930  return WJB_VALUE;
931  }
932 
933  elog(ERROR, "invalid iterator state");
934  return -1;
935 }
uint32 getJsonbOffset(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:126
char * val
Definition: jsonb.h:272
Definition: jsonb.h:22
static JsonbIterator * freeAndGetParent(JsonbIterator *it)
Definition: jsonb_util.c:983
#define JBE_ADVANCE_OFFSET(offset, je)
Definition: jsonb.h:170
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
static void fillJsonbValue(JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
Definition: jsonb_util.c:497
static JsonbIterator * iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent)
Definition: jsonb_util.c:941
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:305
enum jbvType type
Definition: jsonb.h:263
#define elog(elevel,...)
Definition: elog.h:226
Definition: jsonb.h:25

◆ JsonbValueToJsonb()

Jsonb* JsonbValueToJsonb ( JsonbValue val)

Definition at line 84 of file jsonb_util.c.

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

Referenced by each_worker_jsonb(), elements_worker_jsonb(), executeKeyValueMethod(), get_jsonb_path_all(), hstore_to_jsonb(), hstore_to_jsonb_loose(), jsonb_agg_finalfn(), jsonb_agg_transfn(), jsonb_array_element(), jsonb_build_array(), jsonb_build_array_noargs(), jsonb_build_object(), jsonb_build_object_noargs(), jsonb_concat(), jsonb_delete(), jsonb_delete_array(), jsonb_delete_idx(), jsonb_delete_path(), jsonb_from_cstring(), jsonb_insert(), jsonb_object(), jsonb_object_agg_finalfn(), jsonb_object_agg_transfn(), jsonb_object_field(), jsonb_object_two_arg(), jsonb_path_query_array_internal(), jsonb_path_query_first_internal(), jsonb_path_query_internal(), jsonb_set(), jsonb_strip_nulls(), plperl_to_jsonb(), plpython_to_jsonb(), populate_scalar(), to_jsonb(), and transform_jsonb_string_values().

85 {
86  Jsonb *out;
87 
88  if (IsAJsonbScalar(val))
89  {
90  /* Scalar value */
91  JsonbParseState *pstate = NULL;
92  JsonbValue *res;
93  JsonbValue scalarArray;
94 
95  scalarArray.type = jbvArray;
96  scalarArray.val.array.rawScalar = true;
97  scalarArray.val.array.nElems = 1;
98 
99  pushJsonbValue(&pstate, WJB_BEGIN_ARRAY, &scalarArray);
100  pushJsonbValue(&pstate, WJB_ELEM, val);
101  res = pushJsonbValue(&pstate, WJB_END_ARRAY, NULL);
102 
103  out = convertToJsonb(res);
104  }
105  else if (val->type == jbvObject || val->type == jbvArray)
106  {
107  out = convertToJsonb(val);
108  }
109  else
110  {
111  Assert(val->type == jbvBinary);
112  out = palloc(VARHDRSZ + val->val.binary.len);
113  SET_VARSIZE(out, VARHDRSZ + val->val.binary.len);
114  memcpy(VARDATA(out), val->val.binary.data, val->val.binary.len);
115  }
116 
117  return out;
118 }
#define VARDATA(PTR)
Definition: postgres.h:302
Definition: jsonb.h:220
#define VARHDRSZ
Definition: c.h:555
char * val
Definition: jsonb.h:272
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:558
#define Assert(condition)
Definition: c.h:732
static Jsonb * convertToJsonb(JsonbValue *val)
Definition: jsonb_util.c:1490
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:305
enum jbvType type
Definition: jsonb.h:263
void * palloc(Size size)
Definition: mcxt.c:949
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
Definition: jsonb.h:25

◆ lengthCompareJsonbPair()

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

Definition at line 1869 of file jsonb_util.c.

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

Referenced by uniqueifyJsonbObject().

1870 {
1871  const JsonbPair *pa = (const JsonbPair *) a;
1872  const JsonbPair *pb = (const JsonbPair *) b;
1873  int res;
1874 
1875  res = lengthCompareJsonbStringValue(&pa->key, &pb->key);
1876  if (res == 0 && binequal)
1877  *((bool *) binequal) = true;
1878 
1879  /*
1880  * Guarantee keeping order of equal pair. Unique algorithm will prefer
1881  * first element as value.
1882  */
1883  if (res == 0)
1884  res = (pa->order > pb->order) ? -1 : 1;
1885 
1886  return res;
1887 }
uint32 order
Definition: jsonb.h:323
JsonbValue key
Definition: jsonb.h:321
static int lengthCompareJsonbStringValue(const void *a, const void *b)
Definition: jsonb_util.c:1830

◆ lengthCompareJsonbString()

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

Definition at line 1849 of file jsonb_util.c.

Referenced by getKeyJsonValueFromContainer(), and lengthCompareJsonbStringValue().

1850 {
1851  if (len1 == len2)
1852  return memcmp(val1, val2, len1);
1853  else
1854  return len1 > len2 ? 1 : -1;
1855 }

◆ lengthCompareJsonbStringValue()

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

Definition at line 1830 of file jsonb_util.c.

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

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

1831 {
1832  const JsonbValue *va = (const JsonbValue *) a;
1833  const JsonbValue *vb = (const JsonbValue *) b;
1834 
1835  Assert(va->type == jbvString);
1836  Assert(vb->type == jbvString);
1837 
1838  return lengthCompareJsonbString(va->val.string.val, va->val.string.len,
1839  vb->val.string.val, vb->val.string.len);
1840 }
char * val
Definition: jsonb.h:272
static int lengthCompareJsonbString(const char *val1, int len1, const char *val2, int len2)
Definition: jsonb_util.c:1849
#define Assert(condition)
Definition: c.h:732
enum jbvType type
Definition: jsonb.h:263

◆ padBufferToInt()

static short padBufferToInt ( StringInfo  buffer)
static

Definition at line 1469 of file jsonb_util.c.

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

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

1470 {
1471  int padlen,
1472  p,
1473  offset;
1474 
1475  padlen = INTALIGN(buffer->len) - buffer->len;
1476 
1477  offset = reserveFromBuffer(buffer, padlen);
1478 
1479  /* padlen must be small, so this is probably faster than a memset */
1480  for (p = 0; p < padlen; p++)
1481  buffer->data[offset + p] = '\0';
1482 
1483  return padlen;
1484 }
#define INTALIGN(LEN)
Definition: c.h:682
static int reserveFromBuffer(StringInfo buffer, int len)
Definition: jsonb_util.c:1420

◆ pushJsonbValue()

JsonbValue* pushJsonbValue ( JsonbParseState **  pstate,
JsonbIteratorToken  seq,
JsonbValue jbval 
)

Definition at line 558 of file jsonb_util.c.

References jbvBinary, JsonbIteratorInit(), JsonbIteratorNext(), pushJsonbValueScalar(), JsonbValue::type, JsonbValue::val, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, and WJB_VALUE.

Referenced by addJsonbToParseState(), array_dim_to_jsonb(), array_to_jsonb_internal(), AV_to_JsonbValue(), composite_to_jsonb(), datum_to_jsonb(), executeKeyValueMethod(), hstore_to_jsonb(), hstore_to_jsonb_loose(), HV_to_JsonbValue(), IteratorConcat(), jsonb_agg_finalfn(), jsonb_agg_transfn(), jsonb_build_array(), jsonb_build_array_noargs(), jsonb_build_object(), jsonb_build_object_noargs(), 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(), jsonb_object_two_arg(), jsonb_strip_nulls(), JsonbValueToJsonb(), PLyMapping_ToJsonbValue(), PLyObject_ToJsonbValue(), PLySequence_ToJsonbValue(), setPath(), setPathArray(), setPathObject(), SV_to_JsonbValue(), transform_jsonb_string_values(), and wrapItemsInArray().

560 {
561  JsonbIterator *it;
562  JsonbValue *res = NULL;
563  JsonbValue v;
564  JsonbIteratorToken tok;
565 
566  if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
567  jbval->type != jbvBinary)
568  {
569  /* drop through */
570  return pushJsonbValueScalar(pstate, seq, jbval);
571  }
572 
573  /* unpack the binary and add each piece to the pstate */
574  it = JsonbIteratorInit(jbval->val.binary.data);
575  while ((tok = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
576  res = pushJsonbValueScalar(pstate, tok,
577  tok < WJB_BEGIN_ARRAY ? &v : NULL);
578 
579  return res;
580 }
char * val
Definition: jsonb.h:272
Definition: jsonb.h:22
static JsonbValue * pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *scalarVal)
Definition: jsonb_util.c:587
JsonbIteratorToken
Definition: jsonb.h:20
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:759
enum jbvType type
Definition: jsonb.h:263
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:795
Definition: jsonb.h:25

◆ pushJsonbValueScalar()

static JsonbValue * pushJsonbValueScalar ( JsonbParseState **  pstate,
JsonbIteratorToken  seq,
JsonbValue scalarVal 
)
static

Definition at line 587 of file jsonb_util.c.

References appendElement(), appendKey(), appendValue(), Assert, elog, ERROR, IsAJsonbScalar, jbvArray, jbvObject, jbvString, JsonbParseState::next, palloc(), pushState(), JsonbValue::type, uniqueifyJsonbObject(), JsonbValue::val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by pushJsonbValue().

589 {
590  JsonbValue *result = NULL;
591 
592  switch (seq)
593  {
594  case WJB_BEGIN_ARRAY:
595  Assert(!scalarVal || scalarVal->val.array.rawScalar);
596  *pstate = pushState(pstate);
597  result = &(*pstate)->contVal;
598  (*pstate)->contVal.type = jbvArray;
599  (*pstate)->contVal.val.array.nElems = 0;
600  (*pstate)->contVal.val.array.rawScalar = (scalarVal &&
601  scalarVal->val.array.rawScalar);
602  if (scalarVal && scalarVal->val.array.nElems > 0)
603  {
604  /* Assume that this array is still really a scalar */
605  Assert(scalarVal->type == jbvArray);
606  (*pstate)->size = scalarVal->val.array.nElems;
607  }
608  else
609  {
610  (*pstate)->size = 4;
611  }
612  (*pstate)->contVal.val.array.elems = palloc(sizeof(JsonbValue) *
613  (*pstate)->size);
614  break;
615  case WJB_BEGIN_OBJECT:
616  Assert(!scalarVal);
617  *pstate = pushState(pstate);
618  result = &(*pstate)->contVal;
619  (*pstate)->contVal.type = jbvObject;
620  (*pstate)->contVal.val.object.nPairs = 0;
621  (*pstate)->size = 4;
622  (*pstate)->contVal.val.object.pairs = palloc(sizeof(JsonbPair) *
623  (*pstate)->size);
624  break;
625  case WJB_KEY:
626  Assert(scalarVal->type == jbvString);
627  appendKey(*pstate, scalarVal);
628  break;
629  case WJB_VALUE:
630  Assert(IsAJsonbScalar(scalarVal));
631  appendValue(*pstate, scalarVal);
632  break;
633  case WJB_ELEM:
634  Assert(IsAJsonbScalar(scalarVal));
635  appendElement(*pstate, scalarVal);
636  break;
637  case WJB_END_OBJECT:
638  uniqueifyJsonbObject(&(*pstate)->contVal);
639  /* fall through! */
640  case WJB_END_ARRAY:
641  /* Steps here common to WJB_END_OBJECT case */
642  Assert(!scalarVal);
643  result = &(*pstate)->contVal;
644 
645  /*
646  * Pop stack and push current array/object as value in parent
647  * array/object
648  */
649  *pstate = (*pstate)->next;
650  if (*pstate)
651  {
652  switch ((*pstate)->contVal.type)
653  {
654  case jbvArray:
655  appendElement(*pstate, result);
656  break;
657  case jbvObject:
658  appendValue(*pstate, result);
659  break;
660  default:
661  elog(ERROR, "invalid jsonb container type");
662  }
663  }
664  break;
665  default:
666  elog(ERROR, "unrecognized jsonb sequential processing token");
667  }
668 
669  return result;
670 }
static void appendValue(JsonbParseState *pstate, JsonbValue *scalarVal)
Definition: jsonb_util.c:717
char * val
Definition: jsonb.h:272
static JsonbParseState * pushState(JsonbParseState **pstate)
Definition: jsonb_util.c:676
static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
Definition: jsonb_util.c:730
struct JsonbParseState * next
Definition: jsonb.h:331
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
static void uniqueifyJsonbObject(JsonbValue *object)
Definition: jsonb_util.c:1893
#define Assert(condition)
Definition: c.h:732
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:305
enum jbvType type
Definition: jsonb.h:263
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:226
Definition: jsonb.h:25
static void appendKey(JsonbParseState *pstate, JsonbValue *scalarVal)
Definition: jsonb_util.c:688

◆ pushState()

static JsonbParseState * pushState ( JsonbParseState **  pstate)
static

Definition at line 676 of file jsonb_util.c.

References JsonbParseState::next, and palloc().

Referenced by pushJsonbValueScalar().

677 {
678  JsonbParseState *ns = palloc(sizeof(JsonbParseState));
679 
680  ns->next = *pstate;
681  return ns;
682 }
struct JsonbParseState * next
Definition: jsonb.h:331
void * palloc(Size size)
Definition: mcxt.c:949

◆ reserveFromBuffer()

static int reserveFromBuffer ( StringInfo  buffer,
int  len 
)
static

Definition at line 1420 of file jsonb_util.c.

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

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

1421 {
1422  int offset;
1423 
1424  /* Make more room if needed */
1425  enlargeStringInfo(buffer, len);
1426 
1427  /* remember current offset */
1428  offset = buffer->len;
1429 
1430  /* reserve the space */
1431  buffer->len += len;
1432 
1433  /*
1434  * Keep a trailing null in place, even though it's not useful for us; it
1435  * seems best to preserve the invariants of StringInfos.
1436  */
1437  buffer->data[buffer->len] = '\0';
1438 
1439  return offset;
1440 }
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:270

◆ uniqueifyJsonbObject()

static void uniqueifyJsonbObject ( JsonbValue object)
static

Definition at line 1893 of file jsonb_util.c.

References Assert, jbvObject, lengthCompareJsonbPair(), lengthCompareJsonbStringValue(), qsort_arg(), JsonbValue::type, and JsonbValue::val.

Referenced by pushJsonbValueScalar().

1894 {
1895  bool hasNonUniq = false;
1896 
1897  Assert(object->type == jbvObject);
1898 
1899  if (object->val.object.nPairs > 1)
1900  qsort_arg(object->val.object.pairs, object->val.object.nPairs, sizeof(JsonbPair),
1901  lengthCompareJsonbPair, &hasNonUniq);
1902 
1903  if (hasNonUniq)
1904  {
1905  JsonbPair *ptr = object->val.object.pairs + 1,
1906  *res = object->val.object.pairs;
1907 
1908  while (ptr - object->val.object.pairs < object->val.object.nPairs)
1909  {
1910  /* Avoid copying over duplicate */
1911  if (lengthCompareJsonbStringValue(ptr, res) != 0)
1912  {
1913  res++;
1914  if (ptr != res)
1915  memcpy(res, ptr, sizeof(JsonbPair));
1916  }
1917  ptr++;
1918  }
1919 
1920  object->val.object.nPairs = res + 1 - object->val.object.pairs;
1921  }
1922 }
char * val
Definition: jsonb.h:272
static int lengthCompareJsonbPair(const void *a, const void *b, void *arg)
Definition: jsonb_util.c:1869
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
Definition: qsort_arg.c:113
#define Assert(condition)
Definition: c.h:732
enum jbvType type
Definition: jsonb.h:263
static int lengthCompareJsonbStringValue(const void *a, const void *b)
Definition: jsonb_util.c:1830