PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
jsonb_util.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "common/hashfn.h"
#include "miscadmin.h"
#include "port/pg_bitutils.h"
#include "utils/datetime.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 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 *string)
 
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 *binequal)
 
static void uniqueifyJsonbObject (JsonbValue *object, bool unique_keys, bool skip_nulls)
 
static JsonbValuepushJsonbValueScalar (JsonbParseState **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)
 
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.

◆ JSONB_MAX_PAIRS

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

Definition at line 37 of file jsonb_util.c.

Function Documentation

◆ appendElement()

static void appendElement ( JsonbParseState pstate,
JsonbValue scalarVal 
)
static

Definition at line 788 of file jsonb_util.c.

789 {
790  JsonbValue *array = &pstate->contVal;
791 
792  Assert(array->type == jbvArray);
793 
794  if (array->val.array.nElems >= JSONB_MAX_ELEMS)
795  ereport(ERROR,
796  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
797  errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
798  JSONB_MAX_ELEMS)));
799 
800  if (array->val.array.nElems >= pstate->size)
801  {
802  pstate->size *= 2;
803  array->val.array.elems = repalloc(array->val.array.elems,
804  sizeof(JsonbValue) * pstate->size);
805  }
806 
807  array->val.array.elems[array->val.array.nElems++] = *scalarVal;
808 }
#define Assert(condition)
Definition: c.h:863
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
@ jbvArray
Definition: jsonb.h:233
#define JSONB_MAX_ELEMS
Definition: jsonb_util.c:36
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
JsonbValue contVal
Definition: jsonb.h:321
enum jbvType type
Definition: jsonb.h:255
char * val
Definition: jsonb.h:264

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

Referenced by pushJsonbValueScalar().

◆ appendKey()

static void appendKey ( JsonbParseState pstate,
JsonbValue string 
)
static

Definition at line 746 of file jsonb_util.c.

747 {
748  JsonbValue *object = &pstate->contVal;
749 
750  Assert(object->type == jbvObject);
751  Assert(string->type == jbvString);
752 
753  if (object->val.object.nPairs >= JSONB_MAX_PAIRS)
754  ereport(ERROR,
755  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
756  errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
757  JSONB_MAX_PAIRS)));
758 
759  if (object->val.object.nPairs >= pstate->size)
760  {
761  pstate->size *= 2;
762  object->val.object.pairs = repalloc(object->val.object.pairs,
763  sizeof(JsonbPair) * pstate->size);
764  }
765 
766  object->val.object.pairs[object->val.object.nPairs].key = *string;
767  object->val.object.pairs[object->val.object.nPairs].order = object->val.object.nPairs;
768 }
@ jbvObject
Definition: jsonb.h:234
@ jbvString
Definition: jsonb.h:229
#define JSONB_MAX_PAIRS
Definition: jsonb_util.c:37
char string[11]
Definition: preproc-type.c:52

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

Referenced by pushJsonbValueScalar().

◆ appendToBuffer()

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

Definition at line 1513 of file jsonb_util.c.

1514 {
1515  int offset;
1516 
1517  offset = reserveFromBuffer(buffer, len);
1518  copyToBuffer(buffer, offset, data, len);
1519 }
static void copyToBuffer(StringInfo buffer, int offset, const char *data, int len)
Definition: jsonb_util.c:1504
static int reserveFromBuffer(StringInfo buffer, int len)
Definition: jsonb_util.c:1478
const void size_t len
const void * data

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

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

◆ appendValue()

static void appendValue ( JsonbParseState pstate,
JsonbValue scalarVal 
)
static

Definition at line 775 of file jsonb_util.c.

776 {
777  JsonbValue *object = &pstate->contVal;
778 
779  Assert(object->type == jbvObject);
780 
781  object->val.object.pairs[object->val.object.nPairs++].value = *scalarVal;
782 }

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

Referenced by pushJsonbValueScalar().

◆ compareJsonbContainers()

int compareJsonbContainers ( JsonbContainer a,
JsonbContainer b 
)

Definition at line 191 of file jsonb_util.c.

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

References a, Assert, b, compareJsonbScalarValue(), elog, ERROR, i, jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbIterator::parent, pfree(), res, 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 1433 of file jsonb_util.c.

1434 {
1435  if (a->type == b->type)
1436  {
1437  switch (a->type)
1438  {
1439  case jbvNull:
1440  return 0;
1441  case jbvString:
1442  return varstr_cmp(a->val.string.val,
1443  a->val.string.len,
1444  b->val.string.val,
1445  b->val.string.len,
1446  DEFAULT_COLLATION_OID);
1447  case jbvNumeric:
1449  PointerGetDatum(a->val.numeric),
1450  PointerGetDatum(b->val.numeric)));
1451  case jbvBool:
1452  if (a->val.boolean == b->val.boolean)
1453  return 0;
1454  else if (a->val.boolean > b->val.boolean)
1455  return 1;
1456  else
1457  return -1;
1458  default:
1459  elog(ERROR, "invalid jsonb scalar type");
1460  }
1461  }
1462  elog(ERROR, "jsonb scalar type mismatch");
1463  return -1;
1464 }
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2396
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid)
Definition: varlena.c:1538

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 1615 of file jsonb_util.c.

1616 {
1617  int base_offset;
1618  int jentry_offset;
1619  int i;
1620  int totallen;
1621  uint32 containerhead;
1622  int nElems = val->val.array.nElems;
1623 
1624  /* Remember where in the buffer this array starts. */
1625  base_offset = buffer->len;
1626 
1627  /* Align to 4-byte boundary (any padding counts as part of my data) */
1628  padBufferToInt(buffer);
1629 
1630  /*
1631  * Construct the header Jentry and store it in the beginning of the
1632  * variable-length payload.
1633  */
1634  containerhead = nElems | JB_FARRAY;
1635  if (val->val.array.rawScalar)
1636  {
1637  Assert(nElems == 1);
1638  Assert(level == 0);
1639  containerhead |= JB_FSCALAR;
1640  }
1641 
1642  appendToBuffer(buffer, (char *) &containerhead, sizeof(uint32));
1643 
1644  /* Reserve space for the JEntries of the elements. */
1645  jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nElems);
1646 
1647  totallen = 0;
1648  for (i = 0; i < nElems; i++)
1649  {
1650  JsonbValue *elem = &val->val.array.elems[i];
1651  int len;
1652  JEntry meta;
1653 
1654  /*
1655  * Convert element, producing a JEntry and appending its
1656  * variable-length data to buffer
1657  */
1658  convertJsonbValue(buffer, &meta, elem, level + 1);
1659 
1660  len = JBE_OFFLENFLD(meta);
1661  totallen += len;
1662 
1663  /*
1664  * Bail out if total variable-length data exceeds what will fit in a
1665  * JEntry length field. We check this in each iteration, not just
1666  * once at the end, to forestall possible integer overflow.
1667  */
1668  if (totallen > JENTRY_OFFLENMASK)
1669  ereport(ERROR,
1670  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1671  errmsg("total size of jsonb array elements exceeds the maximum of %d bytes",
1672  JENTRY_OFFLENMASK)));
1673 
1674  /*
1675  * Convert each JB_OFFSET_STRIDE'th length to an offset.
1676  */
1677  if ((i % JB_OFFSET_STRIDE) == 0)
1678  meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1679 
1680  copyToBuffer(buffer, jentry_offset, (char *) &meta, sizeof(JEntry));
1681  jentry_offset += sizeof(JEntry);
1682  }
1683 
1684  /* Total data size is everything we've appended to buffer */
1685  totallen = buffer->len - base_offset;
1686 
1687  /* Check length again, since we didn't include the metadata above */
1688  if (totallen > JENTRY_OFFLENMASK)
1689  ereport(ERROR,
1690  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1691  errmsg("total size of jsonb array elements exceeds the maximum of %d bytes",
1692  JENTRY_OFFLENMASK)));
1693 
1694  /* Initialize the header of this node in the container's JEntry array */
1695  *header = JENTRY_ISCONTAINER | totallen;
1696 }
unsigned int uint32
Definition: c.h:518
long val
Definition: informix.c:689
#define JB_FSCALAR
Definition: jsonb.h:201
#define JB_OFFSET_STRIDE
Definition: jsonb.h:178
#define JENTRY_OFFLENMASK
Definition: jsonb.h:138
#define JENTRY_ISCONTAINER
Definition: jsonb.h:148
#define JENTRY_TYPEMASK
Definition: jsonb.h:139
#define JBE_OFFLENFLD(je_)
Definition: jsonb.h:151
#define JENTRY_HAS_OFF
Definition: jsonb.h:140
#define JB_FARRAY
Definition: jsonb.h:203
uint32 JEntry
Definition: jsonb.h:136
static short padBufferToInt(StringInfo buffer)
Definition: jsonb_util.c:1527
static void appendToBuffer(StringInfo buffer, const char *data, int len)
Definition: jsonb_util.c:1513
static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1590

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 1699 of file jsonb_util.c.

1700 {
1701  int base_offset;
1702  int jentry_offset;
1703  int i;
1704  int totallen;
1705  uint32 containerheader;
1706  int nPairs = val->val.object.nPairs;
1707 
1708  /* Remember where in the buffer this object starts. */
1709  base_offset = buffer->len;
1710 
1711  /* Align to 4-byte boundary (any padding counts as part of my data) */
1712  padBufferToInt(buffer);
1713 
1714  /*
1715  * Construct the header Jentry and store it in the beginning of the
1716  * variable-length payload.
1717  */
1718  containerheader = nPairs | JB_FOBJECT;
1719  appendToBuffer(buffer, (char *) &containerheader, sizeof(uint32));
1720 
1721  /* Reserve space for the JEntries of the keys and values. */
1722  jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nPairs * 2);
1723 
1724  /*
1725  * Iterate over the keys, then over the values, since that is the ordering
1726  * we want in the on-disk representation.
1727  */
1728  totallen = 0;
1729  for (i = 0; i < nPairs; i++)
1730  {
1731  JsonbPair *pair = &val->val.object.pairs[i];
1732  int len;
1733  JEntry meta;
1734 
1735  /*
1736  * Convert key, producing a JEntry and appending its variable-length
1737  * data to buffer
1738  */
1739  convertJsonbScalar(buffer, &meta, &pair->key);
1740 
1741  len = JBE_OFFLENFLD(meta);
1742  totallen += len;
1743 
1744  /*
1745  * Bail out if total variable-length data exceeds what will fit in a
1746  * JEntry length field. We check this in each iteration, not just
1747  * once at the end, to forestall possible integer overflow.
1748  */
1749  if (totallen > JENTRY_OFFLENMASK)
1750  ereport(ERROR,
1751  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1752  errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1753  JENTRY_OFFLENMASK)));
1754 
1755  /*
1756  * Convert each JB_OFFSET_STRIDE'th length to an offset.
1757  */
1758  if ((i % JB_OFFSET_STRIDE) == 0)
1759  meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1760 
1761  copyToBuffer(buffer, jentry_offset, (char *) &meta, sizeof(JEntry));
1762  jentry_offset += sizeof(JEntry);
1763  }
1764  for (i = 0; i < nPairs; i++)
1765  {
1766  JsonbPair *pair = &val->val.object.pairs[i];
1767  int len;
1768  JEntry meta;
1769 
1770  /*
1771  * Convert value, producing a JEntry and appending its variable-length
1772  * data to buffer
1773  */
1774  convertJsonbValue(buffer, &meta, &pair->value, level + 1);
1775 
1776  len = JBE_OFFLENFLD(meta);
1777  totallen += len;
1778 
1779  /*
1780  * Bail out if total variable-length data exceeds what will fit in a
1781  * JEntry length field. We check this in each iteration, not just
1782  * once at the end, to forestall possible integer overflow.
1783  */
1784  if (totallen > JENTRY_OFFLENMASK)
1785  ereport(ERROR,
1786  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1787  errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1788  JENTRY_OFFLENMASK)));
1789 
1790  /*
1791  * Convert each JB_OFFSET_STRIDE'th length to an offset.
1792  */
1793  if (((i + nPairs) % JB_OFFSET_STRIDE) == 0)
1794  meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF;
1795 
1796  copyToBuffer(buffer, jentry_offset, (char *) &meta, sizeof(JEntry));
1797  jentry_offset += sizeof(JEntry);
1798  }
1799 
1800  /* Total data size is everything we've appended to buffer */
1801  totallen = buffer->len - base_offset;
1802 
1803  /* Check length again, since we didn't include the metadata above */
1804  if (totallen > JENTRY_OFFLENMASK)
1805  ereport(ERROR,
1806  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1807  errmsg("total size of jsonb object elements exceeds the maximum of %d bytes",
1808  JENTRY_OFFLENMASK)));
1809 
1810  /* Initialize the header of this node in the container's JEntry array */
1811  *header = JENTRY_ISCONTAINER | totallen;
1812 }
#define JB_FOBJECT
Definition: jsonb.h:202
static void convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal)
Definition: jsonb_util.c:1815
JsonbValue key
Definition: jsonb.h:313
JsonbValue value
Definition: jsonb.h:314

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 1815 of file jsonb_util.c.

1816 {
1817  int numlen;
1818  short padlen;
1819 
1820  switch (scalarVal->type)
1821  {
1822  case jbvNull:
1823  *header = JENTRY_ISNULL;
1824  break;
1825 
1826  case jbvString:
1827  appendToBuffer(buffer, scalarVal->val.string.val, scalarVal->val.string.len);
1828 
1829  *header = scalarVal->val.string.len;
1830  break;
1831 
1832  case jbvNumeric:
1833  numlen = VARSIZE_ANY(scalarVal->val.numeric);
1834  padlen = padBufferToInt(buffer);
1835 
1836  appendToBuffer(buffer, (char *) scalarVal->val.numeric, numlen);
1837 
1838  *header = JENTRY_ISNUMERIC | (padlen + numlen);
1839  break;
1840 
1841  case jbvBool:
1842  *header = (scalarVal->val.boolean) ?
1844  break;
1845 
1846  case jbvDatetime:
1847  {
1848  char buf[MAXDATELEN + 1];
1849  size_t len;
1850 
1852  scalarVal->val.datetime.value,
1853  scalarVal->val.datetime.typid,
1854  &scalarVal->val.datetime.tz);
1855  len = strlen(buf);
1856  appendToBuffer(buffer, buf, len);
1857 
1858  *header = len;
1859  }
1860  break;
1861 
1862  default:
1863  elog(ERROR, "invalid jsonb scalar type");
1864  }
1865 }
#define MAXDATELEN
Definition: datetime.h:200
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:310
#define JENTRY_ISNUMERIC
Definition: jsonb.h:144
#define JENTRY_ISNULL
Definition: jsonb.h:147
#define JENTRY_ISBOOL_FALSE
Definition: jsonb.h:145
#define JENTRY_ISBOOL_TRUE
Definition: jsonb.h:146
static char * buf
Definition: pg_test_fsync.c:72
#define VARSIZE_ANY(PTR)
Definition: varatt.h:311

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 1590 of file jsonb_util.c.

1591 {
1593 
1594  if (!val)
1595  return;
1596 
1597  /*
1598  * A JsonbValue passed as val should never have a type of jbvBinary, and
1599  * neither should any of its sub-components. Those values will be produced
1600  * by convertJsonbArray and convertJsonbObject, the results of which will
1601  * not be passed back to this function as an argument.
1602  */
1603 
1604  if (IsAJsonbScalar(val))
1605  convertJsonbScalar(buffer, header, val);
1606  else if (val->type == jbvArray)
1607  convertJsonbArray(buffer, header, val, level);
1608  else if (val->type == jbvObject)
1609  convertJsonbObject(buffer, header, val, level);
1610  else
1611  elog(ERROR, "unknown type of jsonb container to convert");
1612 }
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:297
static void convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1699
static void convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level)
Definition: jsonb_util.c:1615
void check_stack_depth(void)
Definition: postgres.c:3563

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 1548 of file jsonb_util.c.

1549 {
1550  StringInfoData buffer;
1551  JEntry jentry;
1552  Jsonb *res;
1553 
1554  /* Should not already have binary representation */
1555  Assert(val->type != jbvBinary);
1556 
1557  /* Allocate an output buffer. It will be enlarged as needed */
1558  initStringInfo(&buffer);
1559 
1560  /* Make room for the varlena header */
1561  reserveFromBuffer(&buffer, VARHDRSZ);
1562 
1563  convertJsonbValue(&buffer, &jentry, val, 0);
1564 
1565  /*
1566  * Note: the JEntry of the root is discarded. Therefore the root
1567  * JsonbContainer struct must contain enough information to tell what kind
1568  * of value it is.
1569  */
1570 
1571  res = (Jsonb *) buffer.data;
1572 
1573  SET_VARSIZE(res, buffer.len);
1574 
1575  return res;
1576 }
#define VARHDRSZ
Definition: c.h:697
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
Definition: jsonb.h:213
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

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

Referenced by JsonbValueToJsonb().

◆ copyToBuffer()

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

Definition at line 1504 of file jsonb_util.c.

1505 {
1506  memcpy(buffer->data + offset, data, len);
1507 }

References StringInfoData::data, data, and len.

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

◆ equalsJsonbScalarValue()

static bool equalsJsonbScalarValue ( JsonbValue a,
JsonbValue b 
)
static

Definition at line 1401 of file jsonb_util.c.

1402 {
1403  if (a->type == b->type)
1404  {
1405  switch (a->type)
1406  {
1407  case jbvNull:
1408  return true;
1409  case jbvString:
1410  return lengthCompareJsonbStringValue(a, b) == 0;
1411  case jbvNumeric:
1413  PointerGetDatum(a->val.numeric),
1414  PointerGetDatum(b->val.numeric)));
1415  case jbvBool:
1416  return a->val.boolean == b->val.boolean;
1417 
1418  default:
1419  elog(ERROR, "invalid jsonb scalar type");
1420  }
1421  }
1422  elog(ERROR, "jsonb scalar type mismatch");
1423  return false;
1424 }
Datum numeric_eq(PG_FUNCTION_ARGS)
Definition: numeric.c:2412
static int lengthCompareJsonbStringValue(const void *a, const void *b)
Definition: jsonb_util.c:1880
static bool DatumGetBool(Datum X)
Definition: postgres.h:90

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 505 of file jsonb_util.c.

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

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 344 of file jsonb_util.c.

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

References Assert, JsonbContainer::children, equalsJsonbScalarValue(), fillJsonbValue(), getKeyJsonValueFromContainer(), i, JB_FARRAY, JB_FOBJECT, JBE_ADVANCE_OFFSET, jbvString, JsonContainerIsArray, JsonContainerIsObject, JsonContainerSize, sort-test::key, palloc(), 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 1041 of file jsonb_util.c.

1042 {
1043  JsonbIterator *v = it->parent;
1044 
1045  pfree(it);
1046  return v;
1047 }

References JsonbIterator::parent, and pfree().

Referenced by JsonbIteratorNext().

◆ getIthJsonbValueFromContainer()

JsonbValue* getIthJsonbValueFromContainer ( JsonbContainer container,
uint32  i 
)

Definition at line 468 of file jsonb_util.c.

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

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

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 159 of file jsonb_util.c.

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

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 134 of file jsonb_util.c.

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

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 398 of file jsonb_util.c.

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

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

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 999 of file jsonb_util.c.

1000 {
1001  JsonbIterator *it;
1002 
1003  it = palloc0(sizeof(JsonbIterator));
1004  it->container = container;
1005  it->parent = parent;
1006  it->nElems = JsonContainerSize(container);
1007 
1008  /* Array starts just after header */
1009  it->children = container->children;
1010 
1011  switch (container->header & (JB_FARRAY | JB_FOBJECT))
1012  {
1013  case JB_FARRAY:
1014  it->dataProper =
1015  (char *) it->children + it->nElems * sizeof(JEntry);
1016  it->isScalar = JsonContainerIsScalar(container);
1017  /* This is either a "raw scalar", or an array */
1018  Assert(!it->isScalar || it->nElems == 1);
1019 
1020  it->state = JBI_ARRAY_START;
1021  break;
1022 
1023  case JB_FOBJECT:
1024  it->dataProper =
1025  (char *) it->children + it->nElems * sizeof(JEntry) * 2;
1026  it->state = JBI_OBJECT_START;
1027  break;
1028 
1029  default:
1030  elog(ERROR, "unknown type of jsonb container");
1031  }
1032 
1033  return it;
1034 }
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:207
@ JBI_ARRAY_START
Definition: jsonb.h:334
@ JBI_OBJECT_START
Definition: jsonb.h:336
void * palloc0(Size size)
Definition: mcxt.c:1347
uint32 header
Definition: jsonb.h:192
JsonbIterState state
Definition: jsonb.h:366
JEntry * children
Definition: jsonb.h:348
uint32 nElems
Definition: jsonb.h:345
JsonbContainer * container
Definition: jsonb.h:344
bool isScalar
Definition: jsonb.h:347
char * dataProper
Definition: jsonb.h:350

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

◆ JsonbDeepContains()

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

Definition at line 1062 of file jsonb_util.c.

1063 {
1064  JsonbValue vval,
1065  vcontained;
1066  JsonbIteratorToken rval,
1067  rcont;
1068 
1069  /*
1070  * Guard against stack overflow due to overly complex Jsonb.
1071  *
1072  * Functions called here independently take this precaution, but that
1073  * might not be sufficient since this is also a recursive function.
1074  */
1076 
1077  rval = JsonbIteratorNext(val, &vval, false);
1078  rcont = JsonbIteratorNext(mContained, &vcontained, false);
1079 
1080  if (rval != rcont)
1081  {
1082  /*
1083  * The differing return values can immediately be taken as indicating
1084  * two differing container types at this nesting level, which is
1085  * sufficient reason to give up entirely (but it should be the case
1086  * that they're both some container type).
1087  */
1088  Assert(rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY);
1089  Assert(rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY);
1090  return false;
1091  }
1092  else if (rcont == WJB_BEGIN_OBJECT)
1093  {
1094  Assert(vval.type == jbvObject);
1095  Assert(vcontained.type == jbvObject);
1096 
1097  /*
1098  * If the lhs has fewer pairs than the rhs, it can't possibly contain
1099  * the rhs. (This conclusion is safe only because we de-duplicate
1100  * keys in all Jsonb objects; thus there can be no corresponding
1101  * optimization in the array case.) The case probably won't arise
1102  * often, but since it's such a cheap check we may as well make it.
1103  */
1104  if (vval.val.object.nPairs < vcontained.val.object.nPairs)
1105  return false;
1106 
1107  /* Work through rhs "is it contained within?" object */
1108  for (;;)
1109  {
1110  JsonbValue *lhsVal; /* lhsVal is from pair in lhs object */
1111  JsonbValue lhsValBuf;
1112 
1113  rcont = JsonbIteratorNext(mContained, &vcontained, false);
1114 
1115  /*
1116  * When we get through caller's rhs "is it contained within?"
1117  * object without failing to find one of its values, it's
1118  * contained.
1119  */
1120  if (rcont == WJB_END_OBJECT)
1121  return true;
1122 
1123  Assert(rcont == WJB_KEY);
1124  Assert(vcontained.type == jbvString);
1125 
1126  /* First, find value by key... */
1127  lhsVal =
1128  getKeyJsonValueFromContainer((*val)->container,
1129  vcontained.val.string.val,
1130  vcontained.val.string.len,
1131  &lhsValBuf);
1132  if (!lhsVal)
1133  return false;
1134 
1135  /*
1136  * ...at this stage it is apparent that there is at least a key
1137  * match for this rhs pair.
1138  */
1139  rcont = JsonbIteratorNext(mContained, &vcontained, true);
1140 
1141  Assert(rcont == WJB_VALUE);
1142 
1143  /*
1144  * Compare rhs pair's value with lhs pair's value just found using
1145  * key
1146  */
1147  if (lhsVal->type != vcontained.type)
1148  {
1149  return false;
1150  }
1151  else if (IsAJsonbScalar(lhsVal))
1152  {
1153  if (!equalsJsonbScalarValue(lhsVal, &vcontained))
1154  return false;
1155  }
1156  else
1157  {
1158  /* Nested container value (object or array) */
1159  JsonbIterator *nestval,
1160  *nestContained;
1161 
1162  Assert(lhsVal->type == jbvBinary);
1163  Assert(vcontained.type == jbvBinary);
1164 
1165  nestval = JsonbIteratorInit(lhsVal->val.binary.data);
1166  nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1167 
1168  /*
1169  * Match "value" side of rhs datum object's pair recursively.
1170  * It's a nested structure.
1171  *
1172  * Note that nesting still has to "match up" at the right
1173  * nesting sub-levels. However, there need only be zero or
1174  * more matching pairs (or elements) at each nesting level
1175  * (provided the *rhs* pairs/elements *all* match on each
1176  * level), which enables searching nested structures for a
1177  * single String or other primitive type sub-datum quite
1178  * effectively (provided the user constructed the rhs nested
1179  * structure such that we "know where to look").
1180  *
1181  * In other words, the mapping of container nodes in the rhs
1182  * "vcontained" Jsonb to internal nodes on the lhs is
1183  * injective, and parent-child edges on the rhs must be mapped
1184  * to parent-child edges on the lhs to satisfy the condition
1185  * of containment (plus of course the mapped nodes must be
1186  * equal).
1187  */
1188  if (!JsonbDeepContains(&nestval, &nestContained))
1189  return false;
1190  }
1191  }
1192  }
1193  else if (rcont == WJB_BEGIN_ARRAY)
1194  {
1195  JsonbValue *lhsConts = NULL;
1196  uint32 nLhsElems = vval.val.array.nElems;
1197 
1198  Assert(vval.type == jbvArray);
1199  Assert(vcontained.type == jbvArray);
1200 
1201  /*
1202  * Handle distinction between "raw scalar" pseudo arrays, and real
1203  * arrays.
1204  *
1205  * A raw scalar may contain another raw scalar, and an array may
1206  * contain a raw scalar, but a raw scalar may not contain an array. We
1207  * don't do something like this for the object case, since objects can
1208  * only contain pairs, never raw scalars (a pair is represented by an
1209  * rhs object argument with a single contained pair).
1210  */
1211  if (vval.val.array.rawScalar && !vcontained.val.array.rawScalar)
1212  return false;
1213 
1214  /* Work through rhs "is it contained within?" array */
1215  for (;;)
1216  {
1217  rcont = JsonbIteratorNext(mContained, &vcontained, true);
1218 
1219  /*
1220  * When we get through caller's rhs "is it contained within?"
1221  * array without failing to find one of its values, it's
1222  * contained.
1223  */
1224  if (rcont == WJB_END_ARRAY)
1225  return true;
1226 
1227  Assert(rcont == WJB_ELEM);
1228 
1229  if (IsAJsonbScalar(&vcontained))
1230  {
1231  if (!findJsonbValueFromContainer((*val)->container,
1232  JB_FARRAY,
1233  &vcontained))
1234  return false;
1235  }
1236  else
1237  {
1238  uint32 i;
1239 
1240  /*
1241  * If this is first container found in rhs array (at this
1242  * depth), initialize temp lhs array of containers
1243  */
1244  if (lhsConts == NULL)
1245  {
1246  uint32 j = 0;
1247 
1248  /* Make room for all possible values */
1249  lhsConts = palloc(sizeof(JsonbValue) * nLhsElems);
1250 
1251  for (i = 0; i < nLhsElems; i++)
1252  {
1253  /* Store all lhs elements in temp array */
1254  rcont = JsonbIteratorNext(val, &vval, true);
1255  Assert(rcont == WJB_ELEM);
1256 
1257  if (vval.type == jbvBinary)
1258  lhsConts[j++] = vval;
1259  }
1260 
1261  /* No container elements in temp array, so give up now */
1262  if (j == 0)
1263  return false;
1264 
1265  /* We may have only partially filled array */
1266  nLhsElems = j;
1267  }
1268 
1269  /* XXX: Nested array containment is O(N^2) */
1270  for (i = 0; i < nLhsElems; i++)
1271  {
1272  /* Nested container value (object or array) */
1273  JsonbIterator *nestval,
1274  *nestContained;
1275  bool contains;
1276 
1277  nestval = JsonbIteratorInit(lhsConts[i].val.binary.data);
1278  nestContained = JsonbIteratorInit(vcontained.val.binary.data);
1279 
1280  contains = JsonbDeepContains(&nestval, &nestContained);
1281 
1282  if (nestval)
1283  pfree(nestval);
1284  if (nestContained)
1285  pfree(nestContained);
1286  if (contains)
1287  break;
1288  }
1289 
1290  /*
1291  * Report rhs container value is not contained if couldn't
1292  * match rhs container to *some* lhs cont
1293  */
1294  if (i == nLhsElems)
1295  return false;
1296  }
1297  }
1298  }
1299  else
1300  {
1301  elog(ERROR, "invalid jsonb container type");
1302  }
1303 
1304  elog(ERROR, "unexpectedly fell off end of jsonb container");
1305  return false;
1306 }
int j
Definition: isn.c:73
@ 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:344
bool JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
Definition: jsonb_util.c:1062

References Assert, check_stack_depth(), elog, equalsJsonbScalarValue(), ERROR, findJsonbValueFromContainer(), getKeyJsonValueFromContainer(), i, IsAJsonbScalar, j, JB_FARRAY, jbvArray, jbvBinary, jbvObject, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), palloc(), 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(), and jsonb_contains().

◆ JsonbHashScalarValue()

void JsonbHashScalarValue ( const JsonbValue scalarVal,
uint32 hash 
)

Definition at line 1316 of file jsonb_util.c.

1317 {
1318  uint32 tmp;
1319 
1320  /* Compute hash value for scalarVal */
1321  switch (scalarVal->type)
1322  {
1323  case jbvNull:
1324  tmp = 0x01;
1325  break;
1326  case jbvString:
1327  tmp = DatumGetUInt32(hash_any((const unsigned char *) scalarVal->val.string.val,
1328  scalarVal->val.string.len));
1329  break;
1330  case jbvNumeric:
1331  /* Must hash equal numerics to equal hash codes */
1333  NumericGetDatum(scalarVal->val.numeric)));
1334  break;
1335  case jbvBool:
1336  tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1337 
1338  break;
1339  default:
1340  elog(ERROR, "invalid jsonb scalar type");
1341  tmp = 0; /* keep compiler quiet */
1342  break;
1343  }
1344 
1345  /*
1346  * Combine hash values of successive keys, values and elements by rotating
1347  * the previous value left 1 bit, then XOR'ing in the new
1348  * key/value/element's hash value.
1349  */
1350  *hash = pg_rotate_left32(*hash, 1);
1351  *hash ^= tmp;
1352 }
Datum hash_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2694
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:404
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:222
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 1359 of file jsonb_util.c.

1361 {
1362  uint64 tmp;
1363 
1364  switch (scalarVal->type)
1365  {
1366  case jbvNull:
1367  tmp = seed + 0x01;
1368  break;
1369  case jbvString:
1370  tmp = DatumGetUInt64(hash_any_extended((const unsigned char *) scalarVal->val.string.val,
1371  scalarVal->val.string.len,
1372  seed));
1373  break;
1374  case jbvNumeric:
1376  NumericGetDatum(scalarVal->val.numeric),
1377  UInt64GetDatum(seed)));
1378  break;
1379  case jbvBool:
1380  if (seed)
1382  BoolGetDatum(scalarVal->val.boolean),
1383  UInt64GetDatum(seed)));
1384  else
1385  tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1386 
1387  break;
1388  default:
1389  elog(ERROR, "invalid jsonb scalar type");
1390  break;
1391  }
1392 
1394  *hash ^= tmp;
1395 }
Datum hash_numeric_extended(PG_FUNCTION_ARGS)
Definition: numeric.c:2774
#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:419
static Datum UInt64GetDatum(uint64 X)
Definition: postgres.h:436
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102

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 853 of file jsonb_util.c.

854 {
855  if (*it == NULL)
856  return WJB_DONE;
857 
858  /*
859  * When stepping into a nested container, we jump back here to start
860  * processing the child. We will not recurse further in one call, because
861  * processing the child will always begin in JBI_ARRAY_START or
862  * JBI_OBJECT_START state.
863  */
864 recurse:
865  switch ((*it)->state)
866  {
867  case JBI_ARRAY_START:
868  /* Set v to array on first array call */
869  val->type = jbvArray;
870  val->val.array.nElems = (*it)->nElems;
871 
872  /*
873  * v->val.array.elems is not actually set, because we aren't doing
874  * a full conversion
875  */
876  val->val.array.rawScalar = (*it)->isScalar;
877  (*it)->curIndex = 0;
878  (*it)->curDataOffset = 0;
879  (*it)->curValueOffset = 0; /* not actually used */
880  /* Set state for next call */
881  (*it)->state = JBI_ARRAY_ELEM;
882  return WJB_BEGIN_ARRAY;
883 
884  case JBI_ARRAY_ELEM:
885  if ((*it)->curIndex >= (*it)->nElems)
886  {
887  /*
888  * All elements within array already processed. Report this
889  * to caller, and give it back original parent iterator (which
890  * independently tracks iteration progress at its level of
891  * nesting).
892  */
893  *it = freeAndGetParent(*it);
894  return WJB_END_ARRAY;
895  }
896 
897  fillJsonbValue((*it)->container, (*it)->curIndex,
898  (*it)->dataProper, (*it)->curDataOffset,
899  val);
900 
901  JBE_ADVANCE_OFFSET((*it)->curDataOffset,
902  (*it)->children[(*it)->curIndex]);
903  (*it)->curIndex++;
904 
905  if (!IsAJsonbScalar(val) && !skipNested)
906  {
907  /* Recurse into container. */
908  *it = iteratorFromContainer(val->val.binary.data, *it);
909  goto recurse;
910  }
911  else
912  {
913  /*
914  * Scalar item in array, or a container and caller didn't want
915  * us to recurse into it.
916  */
917  return WJB_ELEM;
918  }
919 
920  case JBI_OBJECT_START:
921  /* Set v to object on first object call */
922  val->type = jbvObject;
923  val->val.object.nPairs = (*it)->nElems;
924 
925  /*
926  * v->val.object.pairs is not actually set, because we aren't
927  * doing a full conversion
928  */
929  (*it)->curIndex = 0;
930  (*it)->curDataOffset = 0;
931  (*it)->curValueOffset = getJsonbOffset((*it)->container,
932  (*it)->nElems);
933  /* Set state for next call */
934  (*it)->state = JBI_OBJECT_KEY;
935  return WJB_BEGIN_OBJECT;
936 
937  case JBI_OBJECT_KEY:
938  if ((*it)->curIndex >= (*it)->nElems)
939  {
940  /*
941  * All pairs within object already processed. Report this to
942  * caller, and give it back original containing iterator
943  * (which independently tracks iteration progress at its level
944  * of nesting).
945  */
946  *it = freeAndGetParent(*it);
947  return WJB_END_OBJECT;
948  }
949  else
950  {
951  /* Return key of a key/value pair. */
952  fillJsonbValue((*it)->container, (*it)->curIndex,
953  (*it)->dataProper, (*it)->curDataOffset,
954  val);
955  if (val->type != jbvString)
956  elog(ERROR, "unexpected jsonb type as object key");
957 
958  /* Set state for next call */
959  (*it)->state = JBI_OBJECT_VALUE;
960  return WJB_KEY;
961  }
962 
963  case JBI_OBJECT_VALUE:
964  /* Set state for next call */
965  (*it)->state = JBI_OBJECT_KEY;
966 
967  fillJsonbValue((*it)->container, (*it)->curIndex + (*it)->nElems,
968  (*it)->dataProper, (*it)->curValueOffset,
969  val);
970 
971  JBE_ADVANCE_OFFSET((*it)->curDataOffset,
972  (*it)->children[(*it)->curIndex]);
973  JBE_ADVANCE_OFFSET((*it)->curValueOffset,
974  (*it)->children[(*it)->curIndex + (*it)->nElems]);
975  (*it)->curIndex++;
976 
977  /*
978  * Value may be a container, in which case we recurse with new,
979  * child iterator (unless the caller asked not to, by passing
980  * skipNested).
981  */
982  if (!IsAJsonbScalar(val) && !skipNested)
983  {
984  *it = iteratorFromContainer(val->val.binary.data, *it);
985  goto recurse;
986  }
987  else
988  return WJB_VALUE;
989  }
990 
991  elog(ERROR, "invalid iterator state");
992  return -1;
993 }
@ JBI_OBJECT_VALUE
Definition: jsonb.h:338
@ JBI_ARRAY_ELEM
Definition: jsonb.h:335
@ JBI_OBJECT_KEY
Definition: jsonb.h:337
static JsonbIterator * freeAndGetParent(JsonbIterator *it)
Definition: jsonb_util.c:1041

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, 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_agg_transfn_worker(), jsonb_delete(), jsonb_delete_array(), jsonb_delete_idx(), jsonb_hash(), jsonb_hash_extended(), jsonb_object_agg_transfn_worker(), 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 72 of file jsonb_util.c.

73 {
74  val->type = jbvBinary;
75  val->val.binary.data = &jsonb->root;
76  val->val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
77 }
JsonbContainer root
Definition: jsonb.h:215
#define VARSIZE(PTR)
Definition: varatt.h:279

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 92 of file jsonb_util.c.

93 {
94  Jsonb *out;
95 
96  if (IsAJsonbScalar(val))
97  {
98  /* Scalar value */
99  JsonbParseState *pstate = NULL;
100  JsonbValue *res;
101  JsonbValue scalarArray;
102 
103  scalarArray.type = jbvArray;
104  scalarArray.val.array.rawScalar = true;
105  scalarArray.val.array.nElems = 1;
106 
107  pushJsonbValue(&pstate, WJB_BEGIN_ARRAY, &scalarArray);
108  pushJsonbValue(&pstate, WJB_ELEM, val);
109  res = pushJsonbValue(&pstate, WJB_END_ARRAY, NULL);
110 
111  out = convertToJsonb(res);
112  }
113  else if (val->type == jbvObject || val->type == jbvArray)
114  {
115  out = convertToJsonb(val);
116  }
117  else
118  {
119  Assert(val->type == jbvBinary);
120  out = palloc(VARHDRSZ + val->val.binary.len);
121  SET_VARSIZE(out, VARHDRSZ + val->val.binary.len);
122  memcpy(VARDATA(out), val->val.binary.data, val->val.binary.len);
123  }
124 
125  return out;
126 }
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:566
static Jsonb * convertToJsonb(JsonbValue *val)
Definition: jsonb_util.c:1548
#define VARDATA(PTR)
Definition: varatt.h:278

References Assert, convertToJsonb(), IsAJsonbScalar, jbvArray, jbvBinary, jbvObject, palloc(), pushJsonbValue(), res, 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_agg_transfn_worker(), 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_agg_transfn_worker(), 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 1919 of file jsonb_util.c.

1920 {
1921  const JsonbPair *pa = (const JsonbPair *) a;
1922  const JsonbPair *pb = (const JsonbPair *) b;
1923  int res;
1924 
1925  res = lengthCompareJsonbStringValue(&pa->key, &pb->key);
1926  if (res == 0 && binequal)
1927  *((bool *) binequal) = true;
1928 
1929  /*
1930  * Guarantee keeping order of equal pair. Unique algorithm will prefer
1931  * first element as value.
1932  */
1933  if (res == 0)
1934  res = (pa->order > pb->order) ? -1 : 1;
1935 
1936  return res;
1937 }
uint32 order
Definition: jsonb.h:315

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

Referenced by uniqueifyJsonbObject().

◆ lengthCompareJsonbString()

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

Definition at line 1899 of file jsonb_util.c.

1900 {
1901  if (len1 == len2)
1902  return memcmp(val1, val2, len1);
1903  else
1904  return len1 > len2 ? 1 : -1;
1905 }

Referenced by getKeyJsonValueFromContainer(), and lengthCompareJsonbStringValue().

◆ lengthCompareJsonbStringValue()

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

Definition at line 1880 of file jsonb_util.c.

1881 {
1882  const JsonbValue *va = (const JsonbValue *) a;
1883  const JsonbValue *vb = (const JsonbValue *) b;
1884 
1885  Assert(va->type == jbvString);
1886  Assert(vb->type == jbvString);
1887 
1888  return lengthCompareJsonbString(va->val.string.val, va->val.string.len,
1889  vb->val.string.val, vb->val.string.len);
1890 }

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 1527 of file jsonb_util.c.

1528 {
1529  int padlen,
1530  p,
1531  offset;
1532 
1533  padlen = INTALIGN(buffer->len) - buffer->len;
1534 
1535  offset = reserveFromBuffer(buffer, padlen);
1536 
1537  /* padlen must be small, so this is probably faster than a memset */
1538  for (p = 0; p < padlen; p++)
1539  buffer->data[offset + p] = '\0';
1540 
1541  return padlen;
1542 }

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

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

◆ pushJsonbValue()

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

Definition at line 566 of file jsonb_util.c.

568 {
569  JsonbIterator *it;
570  JsonbValue *res = NULL;
571  JsonbValue v;
572  JsonbIteratorToken tok;
573  int i;
574 
575  if (jbval && (seq == WJB_ELEM || seq == WJB_VALUE) && jbval->type == jbvObject)
576  {
577  pushJsonbValue(pstate, WJB_BEGIN_OBJECT, NULL);
578  for (i = 0; i < jbval->val.object.nPairs; i++)
579  {
580  pushJsonbValue(pstate, WJB_KEY, &jbval->val.object.pairs[i].key);
581  pushJsonbValue(pstate, WJB_VALUE, &jbval->val.object.pairs[i].value);
582  }
583 
584  return pushJsonbValue(pstate, WJB_END_OBJECT, NULL);
585  }
586 
587  if (jbval && (seq == WJB_ELEM || seq == WJB_VALUE) && jbval->type == jbvArray)
588  {
589  pushJsonbValue(pstate, WJB_BEGIN_ARRAY, NULL);
590  for (i = 0; i < jbval->val.array.nElems; i++)
591  {
592  pushJsonbValue(pstate, WJB_ELEM, &jbval->val.array.elems[i]);
593  }
594 
595  return pushJsonbValue(pstate, WJB_END_ARRAY, NULL);
596  }
597 
598  if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
599  jbval->type != jbvBinary)
600  {
601  /* drop through */
602  return pushJsonbValueScalar(pstate, seq, jbval);
603  }
604 
605  /* unpack the binary and add each piece to the pstate */
606  it = JsonbIteratorInit(jbval->val.binary.data);
607 
608  if ((jbval->val.binary.data->header & JB_FSCALAR) && *pstate)
609  {
610  tok = JsonbIteratorNext(&it, &v, true);
611  Assert(tok == WJB_BEGIN_ARRAY);
612  Assert(v.type == jbvArray && v.val.array.rawScalar);
613 
614  tok = JsonbIteratorNext(&it, &v, true);
615  Assert(tok == WJB_ELEM);
616 
617  res = pushJsonbValueScalar(pstate, seq, &v);
618 
619  tok = JsonbIteratorNext(&it, &v, true);
620  Assert(tok == WJB_END_ARRAY);
621  Assert(it == NULL);
622 
623  return res;
624  }
625 
626  while ((tok = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
627  res = pushJsonbValueScalar(pstate, tok,
628  tok < WJB_BEGIN_ARRAY ||
629  (tok == WJB_BEGIN_ARRAY &&
630  v.val.array.rawScalar) ? &v : NULL);
631 
632  return res;
633 }
static JsonbValue * pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *scalarVal)
Definition: jsonb_util.c:640

References Assert, i, JB_FSCALAR, jbvArray, jbvBinary, jbvObject, JsonbIteratorInit(), JsonbIteratorNext(), pushJsonbValueScalar(), res, 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(), setPath(), setPathArray(), setPathObject(), SV_to_JsonbValue(), transform_jsonb_string_values(), and wrapItemsInArray().

◆ pushJsonbValueScalar()

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

Definition at line 640 of file jsonb_util.c.

642 {
643  JsonbValue *result = NULL;
644 
645  switch (seq)
646  {
647  case WJB_BEGIN_ARRAY:
648  Assert(!scalarVal || scalarVal->val.array.rawScalar);
649  *pstate = pushState(pstate);
650  result = &(*pstate)->contVal;
651  (*pstate)->contVal.type = jbvArray;
652  (*pstate)->contVal.val.array.nElems = 0;
653  (*pstate)->contVal.val.array.rawScalar = (scalarVal &&
654  scalarVal->val.array.rawScalar);
655  if (scalarVal && scalarVal->val.array.nElems > 0)
656  {
657  /* Assume that this array is still really a scalar */
658  Assert(scalarVal->type == jbvArray);
659  (*pstate)->size = scalarVal->val.array.nElems;
660  }
661  else
662  {
663  (*pstate)->size = 4;
664  }
665  (*pstate)->contVal.val.array.elems = palloc(sizeof(JsonbValue) *
666  (*pstate)->size);
667  break;
668  case WJB_BEGIN_OBJECT:
669  Assert(!scalarVal);
670  *pstate = pushState(pstate);
671  result = &(*pstate)->contVal;
672  (*pstate)->contVal.type = jbvObject;
673  (*pstate)->contVal.val.object.nPairs = 0;
674  (*pstate)->size = 4;
675  (*pstate)->contVal.val.object.pairs = palloc(sizeof(JsonbPair) *
676  (*pstate)->size);
677  break;
678  case WJB_KEY:
679  Assert(scalarVal->type == jbvString);
680  appendKey(*pstate, scalarVal);
681  break;
682  case WJB_VALUE:
683  Assert(IsAJsonbScalar(scalarVal));
684  appendValue(*pstate, scalarVal);
685  break;
686  case WJB_ELEM:
687  Assert(IsAJsonbScalar(scalarVal));
688  appendElement(*pstate, scalarVal);
689  break;
690  case WJB_END_OBJECT:
691  uniqueifyJsonbObject(&(*pstate)->contVal,
692  (*pstate)->unique_keys,
693  (*pstate)->skip_nulls);
694  /* fall through! */
695  case WJB_END_ARRAY:
696  /* Steps here common to WJB_END_OBJECT case */
697  Assert(!scalarVal);
698  result = &(*pstate)->contVal;
699 
700  /*
701  * Pop stack and push current array/object as value in parent
702  * array/object
703  */
704  *pstate = (*pstate)->next;
705  if (*pstate)
706  {
707  switch ((*pstate)->contVal.type)
708  {
709  case jbvArray:
710  appendElement(*pstate, result);
711  break;
712  case jbvObject:
713  appendValue(*pstate, result);
714  break;
715  default:
716  elog(ERROR, "invalid jsonb container type");
717  }
718  }
719  break;
720  default:
721  elog(ERROR, "unrecognized jsonb sequential processing token");
722  }
723 
724  return result;
725 }
static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
Definition: jsonb_util.c:788
static void uniqueifyJsonbObject(JsonbValue *object, bool unique_keys, bool skip_nulls)
Definition: jsonb_util.c:1943
static void appendValue(JsonbParseState *pstate, JsonbValue *scalarVal)
Definition: jsonb_util.c:775
static JsonbParseState * pushState(JsonbParseState **pstate)
Definition: jsonb_util.c:731
static void appendKey(JsonbParseState *pstate, JsonbValue *string)
Definition: jsonb_util.c:746
struct JsonbParseState * next
Definition: jsonb.h:323

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

◆ pushState()

static JsonbParseState * pushState ( JsonbParseState **  pstate)
static

Definition at line 731 of file jsonb_util.c.

732 {
733  JsonbParseState *ns = palloc(sizeof(JsonbParseState));
734 
735  ns->next = *pstate;
736  ns->unique_keys = false;
737  ns->skip_nulls = false;
738 
739  return ns;
740 }
bool unique_keys
Definition: jsonb.h:324
bool skip_nulls
Definition: jsonb.h:325

References JsonbParseState::next, palloc(), JsonbParseState::skip_nulls, and JsonbParseState::unique_keys.

Referenced by pushJsonbValueScalar().

◆ reserveFromBuffer()

static int reserveFromBuffer ( StringInfo  buffer,
int  len 
)
static

Definition at line 1478 of file jsonb_util.c.

1479 {
1480  int offset;
1481 
1482  /* Make more room if needed */
1483  enlargeStringInfo(buffer, len);
1484 
1485  /* remember current offset */
1486  offset = buffer->len;
1487 
1488  /* reserve the space */
1489  buffer->len += len;
1490 
1491  /*
1492  * Keep a trailing null in place, even though it's not useful for us; it
1493  * seems best to preserve the invariants of StringInfos.
1494  */
1495  buffer->data[buffer->len] = '\0';
1496 
1497  return offset;
1498 }
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:286

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 1943 of file jsonb_util.c.

1944 {
1945  bool hasNonUniq = false;
1946 
1947  Assert(object->type == jbvObject);
1948 
1949  if (object->val.object.nPairs > 1)
1950  qsort_arg(object->val.object.pairs, object->val.object.nPairs, sizeof(JsonbPair),
1951  lengthCompareJsonbPair, &hasNonUniq);
1952 
1953  if (hasNonUniq && unique_keys)
1954  ereport(ERROR,
1955  errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1956  errmsg("duplicate JSON object key value"));
1957 
1958  if (hasNonUniq || skip_nulls)
1959  {
1960  JsonbPair *ptr,
1961  *res;
1962 
1963  while (skip_nulls && object->val.object.nPairs > 0 &&
1964  object->val.object.pairs->value.type == jbvNull)
1965  {
1966  /* If skip_nulls is true, remove leading items with null */
1967  object->val.object.pairs++;
1968  object->val.object.nPairs--;
1969  }
1970 
1971  if (object->val.object.nPairs > 0)
1972  {
1973  ptr = object->val.object.pairs + 1;
1974  res = object->val.object.pairs;
1975 
1976  while (ptr - object->val.object.pairs < object->val.object.nPairs)
1977  {
1978  /* Avoid copying over duplicate or null */
1979  if (lengthCompareJsonbStringValue(ptr, res) != 0 &&
1980  (!skip_nulls || ptr->value.type != jbvNull))
1981  {
1982  res++;
1983  if (ptr != res)
1984  memcpy(res, ptr, sizeof(JsonbPair));
1985  }
1986  ptr++;
1987  }
1988 
1989  object->val.object.nPairs = res + 1 - object->val.object.pairs;
1990  }
1991  }
1992 }
static int lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
Definition: jsonb_util.c:1919
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(), res, JsonbValue::type, JsonbValue::val, and JsonbPair::value.

Referenced by pushJsonbValueScalar().