PostgreSQL Source Code  git master
jsonb.h File Reference
#include "lib/stringinfo.h"
#include "utils/array.h"
#include "utils/numeric.h"
Include dependency graph for jsonb.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  JsonbContainer
 
struct  Jsonb
 
struct  JsonbValue
 
struct  JsonbPair
 
struct  JsonbParseState
 
struct  JsonbIterator
 

Macros

#define JsonbContainsStrategyNumber   7
 
#define JsonbExistsStrategyNumber   9
 
#define JsonbExistsAnyStrategyNumber   10
 
#define JsonbExistsAllStrategyNumber   11
 
#define JGINFLAG_KEY   0x01 /* key (or string array element) */
 
#define JGINFLAG_NULL   0x02 /* null value */
 
#define JGINFLAG_BOOL   0x03 /* boolean value */
 
#define JGINFLAG_NUM   0x04 /* numeric value */
 
#define JGINFLAG_STR   0x05 /* string value (if not an array element) */
 
#define JGINFLAG_HASHED   0x10 /* OR'd into flag if value was hashed */
 
#define JGIN_MAXLENGTH   125 /* max length of text part before hashing */
 
#define DatumGetJsonbP(d)   ((Jsonb *) PG_DETOAST_DATUM(d))
 
#define JsonbPGetDatum(p)   PointerGetDatum(p)
 
#define PG_GETARG_JSONB_P(x)   DatumGetJsonbP(PG_GETARG_DATUM(x))
 
#define PG_RETURN_JSONB_P(x)   PG_RETURN_POINTER(x)
 
#define JENTRY_OFFLENMASK   0x0FFFFFFF
 
#define JENTRY_TYPEMASK   0x70000000
 
#define JENTRY_HAS_OFF   0x80000000
 
#define JENTRY_ISSTRING   0x00000000
 
#define JENTRY_ISNUMERIC   0x10000000
 
#define JENTRY_ISBOOL_FALSE   0x20000000
 
#define JENTRY_ISBOOL_TRUE   0x30000000
 
#define JENTRY_ISNULL   0x40000000
 
#define JENTRY_ISCONTAINER   0x50000000 /* array or object */
 
#define JBE_OFFLENFLD(je_)   ((je_) & JENTRY_OFFLENMASK)
 
#define JBE_HAS_OFF(je_)   (((je_) & JENTRY_HAS_OFF) != 0)
 
#define JBE_ISSTRING(je_)   (((je_) & JENTRY_TYPEMASK) == JENTRY_ISSTRING)
 
#define JBE_ISNUMERIC(je_)   (((je_) & JENTRY_TYPEMASK) == JENTRY_ISNUMERIC)
 
#define JBE_ISCONTAINER(je_)   (((je_) & JENTRY_TYPEMASK) == JENTRY_ISCONTAINER)
 
#define JBE_ISNULL(je_)   (((je_) & JENTRY_TYPEMASK) == JENTRY_ISNULL)
 
#define JBE_ISBOOL_TRUE(je_)   (((je_) & JENTRY_TYPEMASK) == JENTRY_ISBOOL_TRUE)
 
#define JBE_ISBOOL_FALSE(je_)   (((je_) & JENTRY_TYPEMASK) == JENTRY_ISBOOL_FALSE)
 
#define JBE_ISBOOL(je_)   (JBE_ISBOOL_TRUE(je_) || JBE_ISBOOL_FALSE(je_))
 
#define JBE_ADVANCE_OFFSET(offset, je)
 
#define JB_OFFSET_STRIDE   32
 
#define JB_CMASK   0x0FFFFFFF /* mask for count field */
 
#define JB_FSCALAR   0x10000000 /* flag bits */
 
#define JB_FOBJECT   0x20000000
 
#define JB_FARRAY   0x40000000
 
#define JsonContainerSize(jc)   ((jc)->header & JB_CMASK)
 
#define JsonContainerIsScalar(jc)   (((jc)->header & JB_FSCALAR) != 0)
 
#define JsonContainerIsObject(jc)   (((jc)->header & JB_FOBJECT) != 0)
 
#define JsonContainerIsArray(jc)   (((jc)->header & JB_FARRAY) != 0)
 
#define JB_ROOT_COUNT(jbp_)   (*(uint32 *) VARDATA(jbp_) & JB_CMASK)
 
#define JB_ROOT_IS_SCALAR(jbp_)   ((*(uint32 *) VARDATA(jbp_) & JB_FSCALAR) != 0)
 
#define JB_ROOT_IS_OBJECT(jbp_)   ((*(uint32 *) VARDATA(jbp_) & JB_FOBJECT) != 0)
 
#define JB_ROOT_IS_ARRAY(jbp_)   ((*(uint32 *) VARDATA(jbp_) & JB_FARRAY) != 0)
 
#define IsAJsonbScalar(jsonbval)
 

Typedefs

typedef struct JsonbPair JsonbPair
 
typedef struct JsonbValue JsonbValue
 
typedef uint32 JEntry
 
typedef struct JsonbContainer JsonbContainer
 
typedef struct JsonbParseState JsonbParseState
 
typedef struct JsonbIterator JsonbIterator
 

Enumerations

enum  JsonbIteratorToken {
  WJB_DONE, WJB_KEY, WJB_VALUE, WJB_ELEM,
  WJB_BEGIN_ARRAY, WJB_END_ARRAY, WJB_BEGIN_OBJECT, WJB_END_OBJECT
}
 
enum  jbvType {
  jbvNull = 0x0, jbvString, jbvNumeric, jbvBool,
  jbvArray = 0x10, jbvObject, jbvBinary
}
 
enum  JsonbIterState {
  JBI_ARRAY_START, JBI_ARRAY_ELEM, JBI_OBJECT_START, JBI_OBJECT_KEY,
  JBI_OBJECT_VALUE
}
 

Functions

uint32 getJsonbOffset (const JsonbContainer *jc, int index)
 
uint32 getJsonbLength (const JsonbContainer *jc, int index)
 
int compareJsonbContainers (JsonbContainer *a, JsonbContainer *b)
 
JsonbValuefindJsonbValueFromContainer (JsonbContainer *sheader, uint32 flags, JsonbValue *key)
 
JsonbValuegetIthJsonbValueFromContainer (JsonbContainer *sheader, uint32 i)
 
JsonbValuepushJsonbValue (JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbVal)
 
JsonbIteratorJsonbIteratorInit (JsonbContainer *container)
 
JsonbIteratorToken JsonbIteratorNext (JsonbIterator **it, JsonbValue *val, bool skipNested)
 
JsonbJsonbValueToJsonb (JsonbValue *val)
 
bool JsonbDeepContains (JsonbIterator **val, JsonbIterator **mContained)
 
void JsonbHashScalarValue (const JsonbValue *scalarVal, uint32 *hash)
 
void JsonbHashScalarValueExtended (const JsonbValue *scalarVal, uint64 *hash, uint64 seed)
 
char * JsonbToCString (StringInfo out, JsonbContainer *in, int estimated_len)
 
char * JsonbToCStringIndent (StringInfo out, JsonbContainer *in, int estimated_len)
 

Macro Definition Documentation

◆ DatumGetJsonbP

#define DatumGetJsonbP (   d)    ((Jsonb *) PG_DETOAST_DATUM(d))

Definition at line 68 of file jsonb.h.

Referenced by datum_to_jsonb().

◆ IsAJsonbScalar

#define IsAJsonbScalar (   jsonbval)

◆ JB_CMASK

#define JB_CMASK   0x0FFFFFFF /* mask for count field */

Definition at line 203 of file jsonb.h.

◆ JB_FARRAY

◆ JB_FOBJECT

◆ JB_FSCALAR

#define JB_FSCALAR   0x10000000 /* flag bits */

Definition at line 204 of file jsonb.h.

Referenced by convertJsonbArray().

◆ JB_OFFSET_STRIDE

#define JB_OFFSET_STRIDE   32

Definition at line 181 of file jsonb.h.

Referenced by convertJsonbArray(), and convertJsonbObject().

◆ JB_ROOT_COUNT

◆ JB_ROOT_IS_ARRAY

◆ JB_ROOT_IS_OBJECT

#define JB_ROOT_IS_OBJECT (   jbp_)    ((*(uint32 *) VARDATA(jbp_) & JB_FOBJECT) != 0)

◆ JB_ROOT_IS_SCALAR

◆ JBE_ADVANCE_OFFSET

#define JBE_ADVANCE_OFFSET (   offset,
  je 
)
Value:
do { \
JEntry je_ = (je); \
if (JBE_HAS_OFF(je_)) \
(offset) = JBE_OFFLENFLD(je_); \
else \
(offset) += JBE_OFFLENFLD(je_); \
} while(0)
#define JBE_OFFLENFLD(je_)
Definition: jsonb.h:154
#define JBE_HAS_OFF(je_)
Definition: jsonb.h:155

Definition at line 165 of file jsonb.h.

Referenced by findJsonbValueFromContainer(), and JsonbIteratorNext().

◆ JBE_HAS_OFF

#define JBE_HAS_OFF (   je_)    (((je_) & JENTRY_HAS_OFF) != 0)

Definition at line 155 of file jsonb.h.

Referenced by getJsonbLength(), and getJsonbOffset().

◆ JBE_ISBOOL

#define JBE_ISBOOL (   je_)    (JBE_ISBOOL_TRUE(je_) || JBE_ISBOOL_FALSE(je_))

Definition at line 162 of file jsonb.h.

◆ JBE_ISBOOL_FALSE

#define JBE_ISBOOL_FALSE (   je_)    (((je_) & JENTRY_TYPEMASK) == JENTRY_ISBOOL_FALSE)

Definition at line 161 of file jsonb.h.

Referenced by fillJsonbValue().

◆ JBE_ISBOOL_TRUE

#define JBE_ISBOOL_TRUE (   je_)    (((je_) & JENTRY_TYPEMASK) == JENTRY_ISBOOL_TRUE)

Definition at line 160 of file jsonb.h.

Referenced by fillJsonbValue().

◆ JBE_ISCONTAINER

#define JBE_ISCONTAINER (   je_)    (((je_) & JENTRY_TYPEMASK) == JENTRY_ISCONTAINER)

Definition at line 158 of file jsonb.h.

Referenced by fillJsonbValue().

◆ JBE_ISNULL

#define JBE_ISNULL (   je_)    (((je_) & JENTRY_TYPEMASK) == JENTRY_ISNULL)

Definition at line 159 of file jsonb.h.

Referenced by fillJsonbValue().

◆ JBE_ISNUMERIC

#define JBE_ISNUMERIC (   je_)    (((je_) & JENTRY_TYPEMASK) == JENTRY_ISNUMERIC)

Definition at line 157 of file jsonb.h.

Referenced by fillJsonbValue().

◆ JBE_ISSTRING

#define JBE_ISSTRING (   je_)    (((je_) & JENTRY_TYPEMASK) == JENTRY_ISSTRING)

Definition at line 156 of file jsonb.h.

Referenced by fillJsonbValue().

◆ JBE_OFFLENFLD

#define JBE_OFFLENFLD (   je_)    ((je_) & JENTRY_OFFLENMASK)

Definition at line 154 of file jsonb.h.

Referenced by convertJsonbArray(), convertJsonbObject(), getJsonbLength(), and getJsonbOffset().

◆ JENTRY_HAS_OFF

#define JENTRY_HAS_OFF   0x80000000

Definition at line 143 of file jsonb.h.

Referenced by convertJsonbArray(), and convertJsonbObject().

◆ JENTRY_ISBOOL_FALSE

#define JENTRY_ISBOOL_FALSE   0x20000000

Definition at line 148 of file jsonb.h.

Referenced by convertJsonbScalar().

◆ JENTRY_ISBOOL_TRUE

#define JENTRY_ISBOOL_TRUE   0x30000000

Definition at line 149 of file jsonb.h.

Referenced by convertJsonbScalar().

◆ JENTRY_ISCONTAINER

#define JENTRY_ISCONTAINER   0x50000000 /* array or object */

Definition at line 151 of file jsonb.h.

Referenced by convertJsonbArray(), and convertJsonbObject().

◆ JENTRY_ISNULL

#define JENTRY_ISNULL   0x40000000

Definition at line 150 of file jsonb.h.

Referenced by convertJsonbScalar().

◆ JENTRY_ISNUMERIC

#define JENTRY_ISNUMERIC   0x10000000

Definition at line 147 of file jsonb.h.

Referenced by convertJsonbScalar().

◆ JENTRY_ISSTRING

#define JENTRY_ISSTRING   0x00000000

Definition at line 146 of file jsonb.h.

◆ JENTRY_OFFLENMASK

#define JENTRY_OFFLENMASK   0x0FFFFFFF

Definition at line 141 of file jsonb.h.

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

◆ JENTRY_TYPEMASK

#define JENTRY_TYPEMASK   0x70000000

Definition at line 142 of file jsonb.h.

Referenced by convertJsonbArray(), and convertJsonbObject().

◆ JGIN_MAXLENGTH

#define JGIN_MAXLENGTH   125 /* max length of text part before hashing */

Definition at line 65 of file jsonb.h.

Referenced by make_text_key().

◆ JGINFLAG_BOOL

#define JGINFLAG_BOOL   0x03 /* boolean value */

Definition at line 61 of file jsonb.h.

Referenced by make_scalar_key().

◆ JGINFLAG_HASHED

#define JGINFLAG_HASHED   0x10 /* OR'd into flag if value was hashed */

Definition at line 64 of file jsonb.h.

Referenced by make_text_key().

◆ JGINFLAG_KEY

#define JGINFLAG_KEY   0x01 /* key (or string array element) */

Definition at line 59 of file jsonb.h.

Referenced by gin_extract_jsonb_query(), and make_scalar_key().

◆ JGINFLAG_NULL

#define JGINFLAG_NULL   0x02 /* null value */

Definition at line 60 of file jsonb.h.

Referenced by make_scalar_key().

◆ JGINFLAG_NUM

#define JGINFLAG_NUM   0x04 /* numeric value */

Definition at line 62 of file jsonb.h.

Referenced by make_scalar_key().

◆ JGINFLAG_STR

#define JGINFLAG_STR   0x05 /* string value (if not an array element) */

Definition at line 63 of file jsonb.h.

Referenced by make_scalar_key().

◆ JsonbContainsStrategyNumber

◆ JsonbExistsAllStrategyNumber

#define JsonbExistsAllStrategyNumber   11

Definition at line 36 of file jsonb.h.

Referenced by gin_consistent_jsonb(), gin_extract_jsonb_query(), and gin_triconsistent_jsonb().

◆ JsonbExistsAnyStrategyNumber

#define JsonbExistsAnyStrategyNumber   10

Definition at line 35 of file jsonb.h.

Referenced by gin_consistent_jsonb(), gin_extract_jsonb_query(), and gin_triconsistent_jsonb().

◆ JsonbExistsStrategyNumber

#define JsonbExistsStrategyNumber   9

Definition at line 34 of file jsonb.h.

Referenced by gin_consistent_jsonb(), gin_extract_jsonb_query(), and gin_triconsistent_jsonb().

◆ JsonbPGetDatum

#define JsonbPGetDatum (   p)    PointerGetDatum(p)

Definition at line 69 of file jsonb.h.

Referenced by jsonb_to_tsvector(), and populate_scalar().

◆ JsonContainerIsArray

#define JsonContainerIsArray (   jc)    (((jc)->header & JB_FARRAY) != 0)

◆ JsonContainerIsObject

#define JsonContainerIsObject (   jc)    (((jc)->header & JB_FOBJECT) != 0)

◆ JsonContainerIsScalar

#define JsonContainerIsScalar (   jc)    (((jc)->header & JB_FSCALAR) != 0)

Definition at line 210 of file jsonb.h.

Referenced by iteratorFromContainer(), JsValueToJsObject(), and populate_array_dim_jsonb().

◆ JsonContainerSize

#define JsonContainerSize (   jc)    ((jc)->header & JB_CMASK)

◆ PG_GETARG_JSONB_P

◆ PG_RETURN_JSONB_P

Typedef Documentation

◆ JEntry

Definition at line 139 of file jsonb.h.

◆ JsonbContainer

◆ JsonbIterator

◆ JsonbPair

Definition at line 73 of file jsonb.h.

◆ JsonbParseState

◆ JsonbValue

Definition at line 74 of file jsonb.h.

Enumeration Type Documentation

◆ jbvType

enum jbvType
Enumerator
jbvNull 
jbvString 
jbvNumeric 
jbvBool 
jbvArray 
jbvObject 
jbvBinary 

Definition at line 228 of file jsonb.h.

229 {
230  /* Scalar types */
231  jbvNull = 0x0,
232  jbvString,
233  jbvNumeric,
234  jbvBool,
235  /* Composite types */
236  jbvArray = 0x10,
237  jbvObject,
238  /* Binary (i.e. struct Jsonb) jbvArray/jbvObject */
239  jbvBinary
240 };
Definition: jsonb.h:234
Definition: jsonb.h:231

◆ JsonbIteratorToken

Enumerator
WJB_DONE 
WJB_KEY 
WJB_VALUE 
WJB_ELEM 
WJB_BEGIN_ARRAY 
WJB_END_ARRAY 
WJB_BEGIN_OBJECT 
WJB_END_OBJECT 

Definition at line 20 of file jsonb.h.

21 {
22  WJB_DONE,
23  WJB_KEY,
24  WJB_VALUE,
25  WJB_ELEM,
Definition: jsonb.h:22
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
Definition: jsonb.h:25

◆ JsonbIterState

Enumerator
JBI_ARRAY_START 
JBI_ARRAY_ELEM 
JBI_OBJECT_START 
JBI_OBJECT_KEY 
JBI_OBJECT_VALUE 

Definition at line 315 of file jsonb.h.

Function Documentation

◆ compareJsonbContainers()

int compareJsonbContainers ( JsonbContainer a,
JsonbContainer b 
)

Definition at line 178 of file jsonb_util.c.

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

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

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

◆ findJsonbValueFromContainer()

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

Definition at line 327 of file jsonb_util.c.

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

Referenced by findJsonbValueFromContainerLen(), jsonb_exists(), jsonb_exists_all(), jsonb_exists_any(), and JsonbDeepContains().

329 {
330  JEntry *children = container->children;
331  int count = JsonContainerSize(container);
332  JsonbValue *result;
333 
334  Assert((flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);
335 
336  /* Quick out without a palloc cycle if object/array is empty */
337  if (count <= 0)
338  return NULL;
339 
340  result = palloc(sizeof(JsonbValue));
341 
342  if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
343  {
344  char *base_addr = (char *) (children + count);
345  uint32 offset = 0;
346  int i;
347 
348  for (i = 0; i < count; i++)
349  {
350  fillJsonbValue(container, i, base_addr, offset, result);
351 
352  if (key->type == result->type)
353  {
354  if (equalsJsonbScalarValue(key, result))
355  return result;
356  }
357 
358  JBE_ADVANCE_OFFSET(offset, children[i]);
359  }
360  }
361  else if ((flags & JB_FOBJECT) && JsonContainerIsObject(container))
362  {
363  /* Since this is an object, account for *Pairs* of Jentrys */
364  char *base_addr = (char *) (children + count * 2);
365  uint32 stopLow = 0,
366  stopHigh = count;
367 
368  /* Object key passed by caller must be a string */
369  Assert(key->type == jbvString);
370 
371  /* Binary search on object/pair keys *only* */
372  while (stopLow < stopHigh)
373  {
374  uint32 stopMiddle;
375  int difference;
376  JsonbValue candidate;
377 
378  stopMiddle = stopLow + (stopHigh - stopLow) / 2;
379 
380  candidate.type = jbvString;
381  candidate.val.string.val =
382  base_addr + getJsonbOffset(container, stopMiddle);
383  candidate.val.string.len = getJsonbLength(container, stopMiddle);
384 
385  difference = lengthCompareJsonbStringValue(&candidate, key);
386 
387  if (difference == 0)
388  {
389  /* Found our key, return corresponding value */
390  int index = stopMiddle + count;
391 
392  fillJsonbValue(container, index, base_addr,
393  getJsonbOffset(container, index),
394  result);
395 
396  return result;
397  }
398  else
399  {
400  if (difference < 0)
401  stopLow = stopMiddle + 1;
402  else
403  stopHigh = stopMiddle;
404  }
405  }
406  }
407 
408  /* Not found */
409  pfree(result);
410  return NULL;
411 }
uint32 getJsonbOffset(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:121
#define JB_FARRAY
Definition: jsonb.h:206
char * val
Definition: jsonb.h:259
uint32 getJsonbLength(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:146
Definition: type.h:89
#define JBE_ADVANCE_OFFSET(offset, je)
Definition: jsonb.h:165
void pfree(void *pointer)
Definition: mcxt.c:936
#define JsonContainerSize(jc)
Definition: jsonb.h:209
unsigned int uint32
Definition: c.h:306
static void fillJsonbValue(JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
Definition: jsonb_util.c:456
#define JsonContainerIsArray(jc)
Definition: jsonb.h:212
static bool equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b)
Definition: jsonb_util.c:1299
#define JsonContainerIsObject(jc)
Definition: jsonb.h:211
Datum difference(PG_FUNCTION_ARGS)
#define Assert(condition)
Definition: c.h:680
#define JB_FOBJECT
Definition: jsonb.h:205
uint32 JEntry
Definition: jsonb.h:139
enum jbvType type
Definition: jsonb.h:250
void * palloc(Size size)
Definition: mcxt.c:835
int i
static int lengthCompareJsonbStringValue(const void *a, const void *b)
Definition: jsonb_util.c:1762

◆ getIthJsonbValueFromContainer()

JsonbValue* getIthJsonbValueFromContainer ( JsonbContainer sheader,
uint32  i 
)

Definition at line 419 of file jsonb_util.c.

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

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

420 {
421  JsonbValue *result;
422  char *base_addr;
423  uint32 nelements;
424 
425  if (!JsonContainerIsArray(container))
426  elog(ERROR, "not a jsonb array");
427 
428  nelements = JsonContainerSize(container);
429  base_addr = (char *) &container->children[nelements];
430 
431  if (i >= nelements)
432  return NULL;
433 
434  result = palloc(sizeof(JsonbValue));
435 
436  fillJsonbValue(container, i, base_addr,
437  getJsonbOffset(container, i),
438  result);
439 
440  return result;
441 }
uint32 getJsonbOffset(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:121
#define ERROR
Definition: elog.h:43
#define JsonContainerSize(jc)
Definition: jsonb.h:209
unsigned int uint32
Definition: c.h:306
static void fillJsonbValue(JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
Definition: jsonb_util.c:456
#define JsonContainerIsArray(jc)
Definition: jsonb.h:212
void * palloc(Size size)
Definition: mcxt.c:835
int i
#define elog
Definition: elog.h:219

◆ getJsonbLength()

uint32 getJsonbLength ( const JsonbContainer jc,
int  index 
)

Definition at line 146 of file jsonb_util.c.

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

Referenced by fillJsonbValue(), and findJsonbValueFromContainer().

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

◆ getJsonbOffset()

uint32 getJsonbOffset ( const JsonbContainer jc,
int  index 
)

Definition at line 121 of file jsonb_util.c.

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

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

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

◆ JsonbDeepContains()

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

Definition at line 963 of file jsonb_util.c.

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

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

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

◆ JsonbHashScalarValue()

void JsonbHashScalarValue ( const JsonbValue scalarVal,
uint32 hash 
)

Definition at line 1214 of file jsonb_util.c.

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

Referenced by gin_extract_jsonb_path(), and jsonb_hash().

1215 {
1216  uint32 tmp;
1217 
1218  /* Compute hash value for scalarVal */
1219  switch (scalarVal->type)
1220  {
1221  case jbvNull:
1222  tmp = 0x01;
1223  break;
1224  case jbvString:
1225  tmp = DatumGetUInt32(hash_any((const unsigned char *) scalarVal->val.string.val,
1226  scalarVal->val.string.len));
1227  break;
1228  case jbvNumeric:
1229  /* Must hash equal numerics to equal hash codes */
1231  NumericGetDatum(scalarVal->val.numeric)));
1232  break;
1233  case jbvBool:
1234  tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1235 
1236  break;
1237  default:
1238  elog(ERROR, "invalid jsonb scalar type");
1239  tmp = 0; /* keep compiler quiet */
1240  break;
1241  }
1242 
1243  /*
1244  * Combine hash values of successive keys, values and elements by rotating
1245  * the previous value left 1 bit, then XOR'ing in the new
1246  * key/value/element's hash value.
1247  */
1248  *hash = (*hash << 1) | (*hash >> 31);
1249  *hash ^= tmp;
1250 }
#define DatumGetUInt32(X)
Definition: postgres.h:492
Datum hash_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2169
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
Definition: jsonb.h:234
Definition: jsonb.h:231
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
#define ERROR
Definition: elog.h:43
unsigned int uint32
Definition: c.h:306
Datum hash_any(register const unsigned char *k, register int keylen)
Definition: hashfunc.c:428
enum jbvType type
Definition: jsonb.h:250
#define elog
Definition: elog.h:219
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:541

◆ JsonbHashScalarValueExtended()

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

Definition at line 1257 of file jsonb_util.c.

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

Referenced by jsonb_hash_extended().

1259 {
1260  uint64 tmp;
1261 
1262  switch (scalarVal->type)
1263  {
1264  case jbvNull:
1265  tmp = seed + 0x01;
1266  break;
1267  case jbvString:
1268  tmp = DatumGetUInt64(hash_any_extended((const unsigned char *) scalarVal->val.string.val,
1269  scalarVal->val.string.len,
1270  seed));
1271  break;
1272  case jbvNumeric:
1274  NumericGetDatum(scalarVal->val.numeric),
1275  UInt64GetDatum(seed)));
1276  break;
1277  case jbvBool:
1278  if (seed)
1280  BoolGetDatum(scalarVal->val.boolean),
1281  UInt64GetDatum(seed)));
1282  else
1283  tmp = scalarVal->val.boolean ? 0x02 : 0x04;
1284 
1285  break;
1286  default:
1287  elog(ERROR, "invalid jsonb scalar type");
1288  break;
1289  }
1290 
1292  *hash ^= tmp;
1293 }
Datum hash_numeric_extended(PG_FUNCTION_ARGS)
Definition: numeric.c:2249
#define UInt64GetDatum(X)
Definition: postgres.h:654
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
Definition: jsonb.h:234
Definition: jsonb.h:231
#define ROTATE_HIGH_AND_LOW_32BITS(v)
Definition: hash.h:48
#define ERROR
Definition: elog.h:43
#define BoolGetDatum(X)
Definition: postgres.h:408
#define DatumGetUInt64(X)
Definition: postgres.h:640
enum jbvType type
Definition: jsonb.h:250
Datum hashcharextended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:50
#define elog
Definition: elog.h:219
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:541
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587
Datum hash_any_extended(register const unsigned char *k, register int keylen, uint64 seed)
Definition: hashfunc.c:634

◆ JsonbIteratorInit()

◆ JsonbIteratorNext()

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

Definition at line 754 of file jsonb_util.c.

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

Referenced by addJsonbToParseState(), compareJsonbContainers(), datum_to_jsonb(), each_worker_jsonb(), elements_worker_jsonb(), get_jsonb_path_all(), gin_extract_jsonb(), gin_extract_jsonb_path(), iterate_jsonb_string_values(), IteratorConcat(), jsonb_agg_transfn(), jsonb_delete(), jsonb_delete_array(), jsonb_delete_idx(), jsonb_hash(), jsonb_hash_extended(), jsonb_object_agg_transfn(), jsonb_object_keys(), jsonb_strip_nulls(), jsonb_typeof(), JsonbDeepContains(), JsonbToCStringWorker(), populate_array_dim_jsonb(), populate_recordset_worker(), pushJsonbValue(), setPath(), setPathArray(), setPathObject(), and transform_jsonb_string_values().

755 {
756  if (*it == NULL)
757  return WJB_DONE;
758 
759  /*
760  * When stepping into a nested container, we jump back here to start
761  * processing the child. We will not recurse further in one call, because
762  * processing the child will always begin in JBI_ARRAY_START or
763  * JBI_OBJECT_START state.
764  */
765 recurse:
766  switch ((*it)->state)
767  {
768  case JBI_ARRAY_START:
769  /* Set v to array on first array call */
770  val->type = jbvArray;
771  val->val.array.nElems = (*it)->nElems;
772 
773  /*
774  * v->val.array.elems is not actually set, because we aren't doing
775  * a full conversion
776  */
777  val->val.array.rawScalar = (*it)->isScalar;
778  (*it)->curIndex = 0;
779  (*it)->curDataOffset = 0;
780  (*it)->curValueOffset = 0; /* not actually used */
781  /* Set state for next call */
782  (*it)->state = JBI_ARRAY_ELEM;
783  return WJB_BEGIN_ARRAY;
784 
785  case JBI_ARRAY_ELEM:
786  if ((*it)->curIndex >= (*it)->nElems)
787  {
788  /*
789  * All elements within array already processed. Report this
790  * to caller, and give it back original parent iterator (which
791  * independently tracks iteration progress at its level of
792  * nesting).
793  */
794  *it = freeAndGetParent(*it);
795  return WJB_END_ARRAY;
796  }
797 
798  fillJsonbValue((*it)->container, (*it)->curIndex,
799  (*it)->dataProper, (*it)->curDataOffset,
800  val);
801 
802  JBE_ADVANCE_OFFSET((*it)->curDataOffset,
803  (*it)->children[(*it)->curIndex]);
804  (*it)->curIndex++;
805 
806  if (!IsAJsonbScalar(val) && !skipNested)
807  {
808  /* Recurse into container. */
809  *it = iteratorFromContainer(val->val.binary.data, *it);
810  goto recurse;
811  }
812  else
813  {
814  /*
815  * Scalar item in array, or a container and caller didn't want
816  * us to recurse into it.
817  */
818  return WJB_ELEM;
819  }
820 
821  case JBI_OBJECT_START:
822  /* Set v to object on first object call */
823  val->type = jbvObject;
824  val->val.object.nPairs = (*it)->nElems;
825 
826  /*
827  * v->val.object.pairs is not actually set, because we aren't
828  * doing a full conversion
829  */
830  (*it)->curIndex = 0;
831  (*it)->curDataOffset = 0;
832  (*it)->curValueOffset = getJsonbOffset((*it)->container,
833  (*it)->nElems);
834  /* Set state for next call */
835  (*it)->state = JBI_OBJECT_KEY;
836  return WJB_BEGIN_OBJECT;
837 
838  case JBI_OBJECT_KEY:
839  if ((*it)->curIndex >= (*it)->nElems)
840  {
841  /*
842  * All pairs within object already processed. Report this to
843  * caller, and give it back original containing iterator
844  * (which independently tracks iteration progress at its level
845  * of nesting).
846  */
847  *it = freeAndGetParent(*it);
848  return WJB_END_OBJECT;
849  }
850  else
851  {
852  /* Return key of a key/value pair. */
853  fillJsonbValue((*it)->container, (*it)->curIndex,
854  (*it)->dataProper, (*it)->curDataOffset,
855  val);
856  if (val->type != jbvString)
857  elog(ERROR, "unexpected jsonb type as object key");
858 
859  /* Set state for next call */
860  (*it)->state = JBI_OBJECT_VALUE;
861  return WJB_KEY;
862  }
863 
864  case JBI_OBJECT_VALUE:
865  /* Set state for next call */
866  (*it)->state = JBI_OBJECT_KEY;
867 
868  fillJsonbValue((*it)->container, (*it)->curIndex + (*it)->nElems,
869  (*it)->dataProper, (*it)->curValueOffset,
870  val);
871 
872  JBE_ADVANCE_OFFSET((*it)->curDataOffset,
873  (*it)->children[(*it)->curIndex]);
874  JBE_ADVANCE_OFFSET((*it)->curValueOffset,
875  (*it)->children[(*it)->curIndex + (*it)->nElems]);
876  (*it)->curIndex++;
877 
878  /*
879  * Value may be a container, in which case we recurse with new,
880  * child iterator (unless the caller asked not to, by passing
881  * skipNested).
882  */
883  if (!IsAJsonbScalar(val) && !skipNested)
884  {
885  *it = iteratorFromContainer(val->val.binary.data, *it);
886  goto recurse;
887  }
888  else
889  return WJB_VALUE;
890  }
891 
892  elog(ERROR, "invalid iterator state");
893  return -1;
894 }
uint32 getJsonbOffset(const JsonbContainer *jc, int index)
Definition: jsonb_util.c:121
char * val
Definition: jsonb.h:259
Definition: jsonb.h:22
static JsonbIterator * freeAndGetParent(JsonbIterator *it)
Definition: jsonb_util.c:942
#define JBE_ADVANCE_OFFSET(offset, je)
Definition: jsonb.h:165
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
static void fillJsonbValue(JsonbContainer *container, int index, char *base_addr, uint32 offset, JsonbValue *result)
Definition: jsonb_util.c:456
static JsonbIterator * iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent)
Definition: jsonb_util.c:900
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:283
enum jbvType type
Definition: jsonb.h:250
#define elog
Definition: elog.h:219
Definition: jsonb.h:25

◆ JsonbToCString()

char* JsonbToCString ( StringInfo  out,
JsonbContainer in,
int  estimated_len 
)

Definition at line 429 of file jsonb.c.

References JsonbToCStringWorker().

Referenced by each_worker_jsonb(), elements_worker_jsonb(), get_jsonb_path_all(), jsonb_array_element_text(), jsonb_object_field_text(), jsonb_out(), jsonb_send(), and populate_scalar().

430 {
431  return JsonbToCStringWorker(out, in, estimated_len, false);
432 }
static char * JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
Definition: jsonb.c:447

◆ JsonbToCStringIndent()

char* JsonbToCStringIndent ( StringInfo  out,
JsonbContainer in,
int  estimated_len 
)

Definition at line 438 of file jsonb.c.

References JsonbToCStringWorker().

Referenced by jsonb_pretty().

439 {
440  return JsonbToCStringWorker(out, in, estimated_len, true);
441 }
static char * JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
Definition: jsonb.c:447

◆ JsonbValueToJsonb()

Jsonb* JsonbValueToJsonb ( JsonbValue val)

Definition at line 79 of file jsonb_util.c.

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

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

80 {
81  Jsonb *out;
82 
83  if (IsAJsonbScalar(val))
84  {
85  /* Scalar value */
86  JsonbParseState *pstate = NULL;
87  JsonbValue *res;
88  JsonbValue scalarArray;
89 
90  scalarArray.type = jbvArray;
91  scalarArray.val.array.rawScalar = true;
92  scalarArray.val.array.nElems = 1;
93 
94  pushJsonbValue(&pstate, WJB_BEGIN_ARRAY, &scalarArray);
95  pushJsonbValue(&pstate, WJB_ELEM, val);
96  res = pushJsonbValue(&pstate, WJB_END_ARRAY, NULL);
97 
98  out = convertToJsonb(res);
99  }
100  else if (val->type == jbvObject || val->type == jbvArray)
101  {
102  out = convertToJsonb(val);
103  }
104  else
105  {
106  Assert(val->type == jbvBinary);
107  out = palloc(VARHDRSZ + val->val.binary.len);
108  SET_VARSIZE(out, VARHDRSZ + val->val.binary.len);
109  memcpy(VARDATA(out), val->val.binary.data, val->val.binary.len);
110  }
111 
112  return out;
113 }
#define VARDATA(PTR)
Definition: postgres.h:303
Definition: jsonb.h:215
#define VARHDRSZ
Definition: c.h:503
char * val
Definition: jsonb.h:259
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define Assert(condition)
Definition: c.h:680
static Jsonb * convertToJsonb(JsonbValue *val)
Definition: jsonb_util.c:1446
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:283
enum jbvType type
Definition: jsonb.h:250
void * palloc(Size size)
Definition: mcxt.c:835
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
Definition: jsonb.h:25

◆ pushJsonbValue()

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

Definition at line 517 of file jsonb_util.c.

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

Referenced by addJsonbToParseState(), array_dim_to_jsonb(), array_to_jsonb_internal(), composite_to_jsonb(), datum_to_jsonb(), hstore_to_jsonb(), hstore_to_jsonb_loose(), IteratorConcat(), jsonb_agg_finalfn(), jsonb_agg_transfn(), jsonb_build_array(), jsonb_build_array_noargs(), jsonb_build_object(), jsonb_build_object_noargs(), jsonb_delete(), jsonb_delete_array(), jsonb_delete_idx(), jsonb_in_array_end(), jsonb_in_array_start(), jsonb_in_object_end(), jsonb_in_object_field_start(), jsonb_in_object_start(), jsonb_in_scalar(), jsonb_object(), jsonb_object_agg_finalfn(), jsonb_object_agg_transfn(), jsonb_object_two_arg(), jsonb_strip_nulls(), JsonbValueToJsonb(), setPath(), setPathArray(), setPathObject(), and transform_jsonb_string_values().

519 {
520  JsonbIterator *it;
521  JsonbValue *res = NULL;
522  JsonbValue v;
523  JsonbIteratorToken tok;
524 
525  if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
526  jbval->type != jbvBinary)
527  {
528  /* drop through */
529  return pushJsonbValueScalar(pstate, seq, jbval);
530  }
531 
532  /* unpack the binary and add each piece to the pstate */
533  it = JsonbIteratorInit(jbval->val.binary.data);
534  while ((tok = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
535  res = pushJsonbValueScalar(pstate, tok,
536  tok < WJB_BEGIN_ARRAY ? &v : NULL);
537 
538  return res;
539 }
Definition: jsonb.h:22
static JsonbValue * pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *scalarVal)
Definition: jsonb_util.c:546
JsonbIteratorToken
Definition: jsonb.h:20
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25