PostgreSQL Source Code  git master
jsonb_util.c File Reference
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "common/jsonapi.h"
#include "miscadmin.h"
#include "port/pg_bitutils.h"
#include "utils/builtins.h"
#include "utils/datetime.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 *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, 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 38 of file jsonb_util.c.

◆ JSONB_MAX_PAIRS

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

Definition at line 39 of file jsonb_util.c.

Function Documentation

◆ appendElement()

static void appendElement ( JsonbParseState pstate,
JsonbValue scalarVal 
)
static

Definition at line 790 of file jsonb_util.c.

791 {
792  JsonbValue *array = &pstate->contVal;
793 
794  Assert(array->type == jbvArray);
795 
796  if (array->val.array.nElems >= JSONB_MAX_ELEMS)
797  ereport(ERROR,
798  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
799  errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
800  JSONB_MAX_ELEMS)));
801 
802  if (array->val.array.nElems >= pstate->size)
803  {
804  pstate->size *= 2;
805  array->val.array.elems = repalloc(array->val.array.elems,
806  sizeof(JsonbValue) * pstate->size);
807  }
808 
809  array->val.array.elems[array->val.array.nElems++] = *scalarVal;
810 }
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
@ jbvArray
Definition: jsonb.h:241
#define JSONB_MAX_ELEMS
Definition: jsonb_util.c:38
Assert(fmt[strlen(fmt) - 1] !='\n')
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1188
JsonbValue contVal
Definition: jsonb.h:329
enum jbvType type
Definition: jsonb.h:263
char * val
Definition: jsonb.h:272

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 scalarVal 
)
static

Definition at line 748 of file jsonb_util.c.

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

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

1516 {
1517  int offset;
1518 
1519  offset = reserveFromBuffer(buffer, len);
1520  copyToBuffer(buffer, offset, data, len);
1521 }
static void copyToBuffer(StringInfo buffer, int offset, const char *data, int len)
Definition: jsonb_util.c:1506
static int reserveFromBuffer(StringInfo buffer, int len)
Definition: jsonb_util.c:1480
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 777 of file jsonb_util.c.

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

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

Referenced by pushJsonbValueScalar().

◆ compareJsonbContainers()

int compareJsonbContainers ( JsonbContainer a,
JsonbContainer b 
)

Definition at line 193 of file jsonb_util.c.

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

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

1436 {
1437  if (aScalar->type == bScalar->type)
1438  {
1439  switch (aScalar->type)
1440  {
1441  case jbvNull:
1442  return 0;
1443  case jbvString:
1444  return varstr_cmp(aScalar->val.string.val,
1445  aScalar->val.string.len,
1446  bScalar->val.string.val,
1447  bScalar->val.string.len,
1448  DEFAULT_COLLATION_OID);
1449  case jbvNumeric:
1451  PointerGetDatum(aScalar->val.numeric),
1452  PointerGetDatum(bScalar->val.numeric)));
1453  case jbvBool:
1454  if (aScalar->val.boolean == bScalar->val.boolean)
1455  return 0;
1456  else if (aScalar->val.boolean > bScalar->val.boolean)
1457  return 1;
1458  else
1459  return -1;
1460  default:
1461  elog(ERROR, "invalid jsonb scalar type");
1462  }
1463  }
1464  elog(ERROR, "jsonb scalar type mismatch");
1465  return -1;
1466 }
Datum numeric_cmp(PG_FUNCTION_ARGS)
Definition: numeric.c:2316
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:633
#define DatumGetInt32(X)
Definition: postgres.h:516
#define PointerGetDatum(X)
Definition: postgres.h:600
int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid)
Definition: varlena.c:1517

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

Referenced by compareJsonbContainers().

◆ convertJsonbArray()

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

Definition at line 1617 of file jsonb_util.c.

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

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, len, padBufferToInt(), reserveFromBuffer(), and val.

Referenced by convertJsonbValue().

◆ convertJsonbObject()

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

Definition at line 1701 of file jsonb_util.c.

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

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, len, padBufferToInt(), reserveFromBuffer(), val, and JsonbPair::value.

Referenced by convertJsonbValue().

◆ convertJsonbScalar()

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

Definition at line 1817 of file jsonb_util.c.

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

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

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

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

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

◆ convertToJsonb()

static Jsonb * convertToJsonb ( JsonbValue val)
static

Definition at line 1550 of file jsonb_util.c.

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

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

1507 {
1508  memcpy(buffer->data + offset, data, len);
1509 }

References StringInfoData::data, data, and len.

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

◆ equalsJsonbScalarValue()

static bool equalsJsonbScalarValue ( JsonbValue a,
JsonbValue b 
)
static

Definition at line 1403 of file jsonb_util.c.

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

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

Referenced by findJsonbValueFromContainer(), and JsonbDeepContains().

◆ fillJsonbValue()

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

Definition at line 507 of file jsonb_util.c.

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

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

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

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

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

References JsonbIterator::parent, and pfree().

Referenced by JsonbIteratorNext().

◆ getIthJsonbValueFromContainer()

JsonbValue* getIthJsonbValueFromContainer ( JsonbContainer container,
uint32  i 
)

Definition at line 470 of file jsonb_util.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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(), 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 74 of file jsonb_util.c.

75 {
76  val->type = jbvBinary;
77  val->val.binary.data = &jsonb->root;
78  val->val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
79 }
#define VARSIZE(PTR)
Definition: postgres.h:316
JsonbContainer root
Definition: jsonb.h:223

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

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

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 each_worker_jsonb(), elements_worker_jsonb(), ExecEvalJsonExpr(), ExecPrepareJsonItemCoercion(), 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(), JsonbMakeEmptyArray(), JsonbMakeEmptyObject(), JsonPathQuery(), JsonTableNextRow(), plperl_to_jsonb(), plpython_to_jsonb(), populate_scalar(), to_jsonb_worker(), and transform_jsonb_string_values().

◆ lengthCompareJsonbPair()

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

Definition at line 1921 of file jsonb_util.c.

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

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

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

Referenced by getKeyJsonValueFromContainer(), and lengthCompareJsonbStringValue().

◆ lengthCompareJsonbStringValue()

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

Definition at line 1882 of file jsonb_util.c.

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

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

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

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

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

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(), 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 642 of file jsonb_util.c.

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

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

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

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

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

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

1946 {
1947  bool hasNonUniq = false;
1948 
1949  Assert(object->type == jbvObject);
1950 
1951  if (object->val.object.nPairs > 1)
1952  qsort_arg(object->val.object.pairs, object->val.object.nPairs, sizeof(JsonbPair),
1953  lengthCompareJsonbPair, &hasNonUniq);
1954 
1955  if (hasNonUniq && unique_keys)
1956  ereport(ERROR,
1957  (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
1958  errmsg("duplicate JSON object key value")));
1959 
1960  if (hasNonUniq || skip_nulls)
1961  {
1962  JsonbPair *ptr,
1963  *res;
1964 
1965  while (skip_nulls && object->val.object.nPairs > 0 &&
1966  object->val.object.pairs->value.type == jbvNull)
1967  {
1968  /* If skip_nulls is true, remove leading items with null */
1969  object->val.object.pairs++;
1970  object->val.object.nPairs--;
1971  }
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 }
static int lengthCompareJsonbPair(const void *a, const void *b, void *arg)
Definition: jsonb_util.c:1921
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().