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  JsonbInState
 
struct  JsonbParseState
 
struct  JsonbIterator
 

Macros

#define JsonbContainsStrategyNumber   7
 
#define JsonbExistsStrategyNumber   9
 
#define JsonbExistsAnyStrategyNumber   10
 
#define JsonbExistsAllStrategyNumber   11
 
#define JsonbJsonpathExistsStrategyNumber   15
 
#define JsonbJsonpathPredicateStrategyNumber   16
 
#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 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)
 
#define PG_GETARG_JSONB_P(x)   DatumGetJsonbP(PG_GETARG_DATUM(x))
 
#define PG_GETARG_JSONB_P_COPY(x)   DatumGetJsonbPCopy(PG_GETARG_DATUM(x))
 
#define PG_RETURN_JSONB_P(x)   PG_RETURN_POINTER(x)
 

Typedefs

typedef struct JsonbPair JsonbPair
 
typedef struct JsonbValue JsonbValue
 
typedef struct JsonbParseState JsonbParseState
 
typedef uint32 JEntry
 
typedef struct JsonbContainer JsonbContainer
 
typedef struct JsonbInState JsonbInState
 
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 , jbvDatetime = 0x20
}
 
enum  JsonbIterState {
  JBI_ARRAY_START , JBI_ARRAY_ELEM , JBI_OBJECT_START , JBI_OBJECT_KEY ,
  JBI_OBJECT_VALUE
}
 

Functions

static JsonbDatumGetJsonbP (Datum d)
 
static JsonbDatumGetJsonbPCopy (Datum d)
 
static Datum JsonbPGetDatum (const Jsonb *p)
 
uint32 getJsonbOffset (const JsonbContainer *jc, int index)
 
uint32 getJsonbLength (const JsonbContainer *jc, int index)
 
int compareJsonbContainers (JsonbContainer *a, JsonbContainer *b)
 
JsonbValuefindJsonbValueFromContainer (JsonbContainer *container, uint32 flags, JsonbValue *key)
 
JsonbValuegetKeyJsonValueFromContainer (JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
 
JsonbValuegetIthJsonbValueFromContainer (JsonbContainer *container, uint32 i)
 
void pushJsonbValue (JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)
 
JsonbIteratorJsonbIteratorInit (JsonbContainer *container)
 
JsonbIteratorToken JsonbIteratorNext (JsonbIterator **it, JsonbValue *val, bool skipNested)
 
void JsonbToJsonbValue (Jsonb *jsonb, JsonbValue *val)
 
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)
 
char * JsonbUnquote (Jsonb *jb)
 
bool JsonbExtractScalar (JsonbContainer *jbc, JsonbValue *res)
 
const char * JsonbTypeName (JsonbValue *val)
 
Datum jsonb_set_element (Jsonb *jb, const Datum *path, int path_len, JsonbValue *newval)
 
Datum jsonb_get_element (Jsonb *jb, const Datum *path, int npath, bool *isnull, bool as_text)
 
bool to_jsonb_is_immutable (Oid typoid)
 
Datum jsonb_build_object_worker (int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys)
 
Datum jsonb_build_array_worker (int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null)
 

Macro Definition Documentation

◆ IsAJsonbScalar

#define IsAJsonbScalar (   jsonbval)
Value:
(((jsonbval)->type >= jbvNull && \
(jsonbval)->type <= jbvBool) || \
(jsonbval)->type == jbvDatetime)
@ jbvBool
Definition: jsonb.h:233
@ jbvNull
Definition: jsonb.h:230
@ jbvDatetime
Definition: jsonb.h:246
const char * type

Definition at line 299 of file jsonb.h.

◆ JB_CMASK

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

Definition at line 202 of file jsonb.h.

◆ JB_FARRAY

#define JB_FARRAY   0x40000000

Definition at line 205 of file jsonb.h.

◆ JB_FOBJECT

#define JB_FOBJECT   0x20000000

Definition at line 204 of file jsonb.h.

◆ JB_FSCALAR

#define JB_FSCALAR   0x10000000 /* flag bits */

Definition at line 203 of file jsonb.h.

◆ JB_OFFSET_STRIDE

#define JB_OFFSET_STRIDE   32

Definition at line 180 of file jsonb.h.

◆ JB_ROOT_COUNT

#define JB_ROOT_COUNT (   jbp_)    (*(uint32 *) VARDATA(jbp_) & JB_CMASK)

Definition at line 221 of file jsonb.h.

◆ JB_ROOT_IS_ARRAY

#define JB_ROOT_IS_ARRAY (   jbp_)    ((*(uint32 *) VARDATA(jbp_) & JB_FARRAY) != 0)

Definition at line 224 of file jsonb.h.

◆ JB_ROOT_IS_OBJECT

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

Definition at line 223 of file jsonb.h.

◆ JB_ROOT_IS_SCALAR

#define JB_ROOT_IS_SCALAR (   jbp_)    ((*(uint32 *) VARDATA(jbp_) & JB_FSCALAR) != 0)

Definition at line 222 of file jsonb.h.

◆ 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_HAS_OFF(je_)
Definition: jsonb.h:154
#define JBE_OFFLENFLD(je_)
Definition: jsonb.h:153

Definition at line 164 of file jsonb.h.

◆ JBE_HAS_OFF

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

Definition at line 154 of file jsonb.h.

◆ JBE_ISBOOL

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

Definition at line 161 of file jsonb.h.

◆ JBE_ISBOOL_FALSE

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

Definition at line 160 of file jsonb.h.

◆ JBE_ISBOOL_TRUE

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

Definition at line 159 of file jsonb.h.

◆ JBE_ISCONTAINER

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

Definition at line 157 of file jsonb.h.

◆ JBE_ISNULL

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

Definition at line 158 of file jsonb.h.

◆ JBE_ISNUMERIC

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

Definition at line 156 of file jsonb.h.

◆ JBE_ISSTRING

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

Definition at line 155 of file jsonb.h.

◆ JBE_OFFLENFLD

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

Definition at line 153 of file jsonb.h.

◆ JENTRY_HAS_OFF

#define JENTRY_HAS_OFF   0x80000000

Definition at line 142 of file jsonb.h.

◆ JENTRY_ISBOOL_FALSE

#define JENTRY_ISBOOL_FALSE   0x20000000

Definition at line 147 of file jsonb.h.

◆ JENTRY_ISBOOL_TRUE

#define JENTRY_ISBOOL_TRUE   0x30000000

Definition at line 148 of file jsonb.h.

◆ JENTRY_ISCONTAINER

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

Definition at line 150 of file jsonb.h.

◆ JENTRY_ISNULL

#define JENTRY_ISNULL   0x40000000

Definition at line 149 of file jsonb.h.

◆ JENTRY_ISNUMERIC

#define JENTRY_ISNUMERIC   0x10000000

Definition at line 146 of file jsonb.h.

◆ JENTRY_ISSTRING

#define JENTRY_ISSTRING   0x00000000

Definition at line 145 of file jsonb.h.

◆ JENTRY_OFFLENMASK

#define JENTRY_OFFLENMASK   0x0FFFFFFF

Definition at line 140 of file jsonb.h.

◆ JENTRY_TYPEMASK

#define JENTRY_TYPEMASK   0x70000000

Definition at line 141 of file jsonb.h.

◆ JGIN_MAXLENGTH

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

Definition at line 68 of file jsonb.h.

◆ JGINFLAG_BOOL

#define JGINFLAG_BOOL   0x03 /* boolean value */

Definition at line 64 of file jsonb.h.

◆ JGINFLAG_HASHED

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

Definition at line 67 of file jsonb.h.

◆ JGINFLAG_KEY

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

Definition at line 62 of file jsonb.h.

◆ JGINFLAG_NULL

#define JGINFLAG_NULL   0x02 /* null value */

Definition at line 63 of file jsonb.h.

◆ JGINFLAG_NUM

#define JGINFLAG_NUM   0x04 /* numeric value */

Definition at line 65 of file jsonb.h.

◆ JGINFLAG_STR

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

Definition at line 66 of file jsonb.h.

◆ JsonbContainsStrategyNumber

#define JsonbContainsStrategyNumber   7

Definition at line 33 of file jsonb.h.

◆ JsonbExistsAllStrategyNumber

#define JsonbExistsAllStrategyNumber   11

Definition at line 36 of file jsonb.h.

◆ JsonbExistsAnyStrategyNumber

#define JsonbExistsAnyStrategyNumber   10

Definition at line 35 of file jsonb.h.

◆ JsonbExistsStrategyNumber

#define JsonbExistsStrategyNumber   9

Definition at line 34 of file jsonb.h.

◆ JsonbJsonpathExistsStrategyNumber

#define JsonbJsonpathExistsStrategyNumber   15

Definition at line 37 of file jsonb.h.

◆ JsonbJsonpathPredicateStrategyNumber

#define JsonbJsonpathPredicateStrategyNumber   16

Definition at line 38 of file jsonb.h.

◆ JsonContainerIsArray

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

Definition at line 211 of file jsonb.h.

◆ JsonContainerIsObject

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

Definition at line 210 of file jsonb.h.

◆ JsonContainerIsScalar

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

Definition at line 209 of file jsonb.h.

◆ JsonContainerSize

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

Definition at line 208 of file jsonb.h.

◆ PG_GETARG_JSONB_P

#define PG_GETARG_JSONB_P (   x)    DatumGetJsonbP(PG_GETARG_DATUM(x))

Definition at line 418 of file jsonb.h.

◆ PG_GETARG_JSONB_P_COPY

#define PG_GETARG_JSONB_P_COPY (   x)    DatumGetJsonbPCopy(PG_GETARG_DATUM(x))

Definition at line 419 of file jsonb.h.

◆ PG_RETURN_JSONB_P

#define PG_RETURN_JSONB_P (   x)    PG_RETURN_POINTER(x)

Definition at line 420 of file jsonb.h.

Typedef Documentation

◆ JEntry

typedef uint32 JEntry

Definition at line 138 of file jsonb.h.

◆ JsonbContainer

◆ JsonbInState

typedef struct JsonbInState JsonbInState

◆ JsonbIterator

typedef struct JsonbIterator JsonbIterator

◆ JsonbPair

typedef struct JsonbPair JsonbPair

Definition at line 71 of file jsonb.h.

◆ JsonbParseState

Definition at line 73 of file jsonb.h.

◆ JsonbValue

typedef struct JsonbValue JsonbValue

Definition at line 72 of file jsonb.h.

Enumeration Type Documentation

◆ jbvType

enum jbvType
Enumerator
jbvNull 
jbvString 
jbvNumeric 
jbvBool 
jbvArray 
jbvObject 
jbvBinary 
jbvDatetime 

Definition at line 227 of file jsonb.h.

228{
229 /* Scalar types */
230 jbvNull = 0x0,
231 jbvString,
233 jbvBool,
234 /* Composite types */
235 jbvArray = 0x10,
236 jbvObject,
237 /* Binary (i.e. struct Jsonb) jbvArray/jbvObject */
238 jbvBinary,
239
240 /*
241 * Virtual types.
242 *
243 * These types are used only for in-memory JSON processing and serialized
244 * into JSON strings when outputted to json/jsonb.
245 */
246 jbvDatetime = 0x20,
247};
@ jbvObject
Definition: jsonb.h:236
@ jbvNumeric
Definition: jsonb.h:232
@ jbvArray
Definition: jsonb.h:235
@ jbvBinary
Definition: jsonb.h:238
@ jbvString
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{
23 WJB_KEY,
JsonbIteratorToken
Definition: jsonb.h:21
@ WJB_KEY
Definition: jsonb.h:23
@ WJB_DONE
Definition: jsonb.h:22
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_VALUE
Definition: jsonb.h:24
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_ELEM
Definition: jsonb.h:25
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26

◆ JsonbIterState

Enumerator
JBI_ARRAY_START 
JBI_ARRAY_ELEM 
JBI_OBJECT_START 
JBI_OBJECT_KEY 
JBI_OBJECT_VALUE 

Definition at line 359 of file jsonb.h.

360{
JsonbIterState
Definition: jsonb.h:360
@ JBI_OBJECT_VALUE
Definition: jsonb.h:365
@ JBI_ARRAY_START
Definition: jsonb.h:361
@ JBI_ARRAY_ELEM
Definition: jsonb.h:362
@ JBI_OBJECT_START
Definition: jsonb.h:363
@ JBI_OBJECT_KEY
Definition: jsonb.h:364

Function Documentation

◆ compareJsonbContainers()

int compareJsonbContainers ( JsonbContainer a,
JsonbContainer b 
)

Definition at line 194 of file jsonb_util.c.

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

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

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

◆ DatumGetJsonbP()

◆ DatumGetJsonbPCopy()

static Jsonb * DatumGetJsonbPCopy ( Datum  d)
inlinestatic

Definition at line 407 of file jsonb.h.

408{
409 return (Jsonb *) PG_DETOAST_DATUM_COPY(d);
410}
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242

References PG_DETOAST_DATUM_COPY.

◆ findJsonbValueFromContainer()

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

Definition at line 348 of file jsonb_util.c.

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

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

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

◆ getIthJsonbValueFromContainer()

JsonbValue * getIthJsonbValueFromContainer ( JsonbContainer container,
uint32  i 
)

Definition at line 472 of file jsonb_util.c.

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

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

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

◆ getJsonbLength()

uint32 getJsonbLength ( const JsonbContainer jc,
int  index 
)

Definition at line 162 of file jsonb_util.c.

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

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

Referenced by fillJsonbValue(), and getKeyJsonValueFromContainer().

◆ getJsonbOffset()

uint32 getJsonbOffset ( const JsonbContainer jc,
int  index 
)

Definition at line 137 of file jsonb_util.c.

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

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

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

◆ getKeyJsonValueFromContainer()

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

Definition at line 402 of file jsonb_util.c.

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

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

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

◆ jsonb_build_array_worker()

Datum jsonb_build_array_worker ( int  nargs,
const Datum args,
const bool *  nulls,
const Oid types,
bool  absent_on_null 
)

Definition at line 1247 of file jsonb.c.

1249{
1250 int i;
1251 JsonbInState result;
1252
1253 memset(&result, 0, sizeof(JsonbInState));
1254
1255 pushJsonbValue(&result, WJB_BEGIN_ARRAY, NULL);
1256
1257 for (i = 0; i < nargs; i++)
1258 {
1259 if (absent_on_null && nulls[i])
1260 continue;
1261
1262 add_jsonb(args[i], nulls[i], &result, types[i], false);
1263 }
1264
1265 pushJsonbValue(&result, WJB_END_ARRAY, NULL);
1266
1267 return JsonbPGetDatum(JsonbValueToJsonb(result.result));
1268}
struct typedefs * types
Definition: ecpg.c:30
static void add_jsonb(Datum val, bool is_null, JsonbInState *result, Oid val_type, bool key_scalar)
Definition: jsonb.c:1053
static Datum JsonbPGetDatum(const Jsonb *p)
Definition: jsonb.h:413
void pushJsonbValue(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:583
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:96
JsonbValue * result
Definition: jsonb.h:333

References add_jsonb(), generate_unaccent_rules::args, i, JsonbPGetDatum(), JsonbValueToJsonb(), pushJsonbValue(), JsonbInState::result, types, WJB_BEGIN_ARRAY, and WJB_END_ARRAY.

Referenced by ExecEvalJsonConstructor(), and jsonb_build_array().

◆ jsonb_build_object_worker()

Datum jsonb_build_object_worker ( int  nargs,
const Datum args,
const bool *  nulls,
const Oid types,
bool  absent_on_null,
bool  unique_keys 
)

Definition at line 1162 of file jsonb.c.

1164{
1165 int i;
1166 JsonbInState result;
1167
1168 if (nargs % 2 != 0)
1169 ereport(ERROR,
1170 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1171 errmsg("argument list must have even number of elements"),
1172 /* translator: %s is a SQL function name */
1173 errhint("The arguments of %s must consist of alternating keys and values.",
1174 "jsonb_build_object()")));
1175
1176 memset(&result, 0, sizeof(JsonbInState));
1177
1178 pushJsonbValue(&result, WJB_BEGIN_OBJECT, NULL);
1179 result.parseState->unique_keys = unique_keys;
1180 result.parseState->skip_nulls = absent_on_null;
1181
1182 for (i = 0; i < nargs; i += 2)
1183 {
1184 /* process key */
1185 bool skip;
1186
1187 if (nulls[i])
1188 ereport(ERROR,
1189 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1190 errmsg("argument %d: key must not be null", i + 1)));
1191
1192 /* skip null values if absent_on_null */
1193 skip = absent_on_null && nulls[i + 1];
1194
1195 /* we need to save skipped keys for the key uniqueness check */
1196 if (skip && !unique_keys)
1197 continue;
1198
1199 add_jsonb(args[i], false, &result, types[i], true);
1200
1201 /* process value */
1202 add_jsonb(args[i + 1], nulls[i + 1], &result, types[i + 1], false);
1203 }
1204
1205 pushJsonbValue(&result, WJB_END_OBJECT, NULL);
1206
1207 return JsonbPGetDatum(JsonbValueToJsonb(result.result));
1208}
int errhint(const char *fmt,...)
Definition: elog.c:1330
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ereport(elevel,...)
Definition: elog.h:150
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:108
JsonbParseState * parseState
Definition: jsonb.h:337
bool unique_keys
Definition: jsonb.h:351
bool skip_nulls
Definition: jsonb.h:352

References add_jsonb(), generate_unaccent_rules::args, ereport, errcode(), errhint(), errmsg(), ERROR, i, JsonbPGetDatum(), JsonbValueToJsonb(), JsonbInState::parseState, pushJsonbValue(), JsonbInState::result, skip, JsonbParseState::skip_nulls, types, JsonbParseState::unique_keys, WJB_BEGIN_OBJECT, and WJB_END_OBJECT.

Referenced by ExecEvalJsonConstructor(), and jsonb_build_object().

◆ jsonb_get_element()

Datum jsonb_get_element ( Jsonb jb,
const Datum path,
int  npath,
bool *  isnull,
bool  as_text 
)

Definition at line 1531 of file jsonfuncs.c.

1532{
1533 JsonbContainer *container = &jb->root;
1534 JsonbValue *jbvp = NULL;
1535 int i;
1536 bool have_object = false,
1537 have_array = false;
1538
1539 *isnull = false;
1540
1541 /* Identify whether we have object, array, or scalar at top-level */
1542 if (JB_ROOT_IS_OBJECT(jb))
1543 have_object = true;
1544 else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1545 have_array = true;
1546 else
1547 {
1549 /* Extract the scalar value, if it is what we'll return */
1550 if (npath <= 0)
1551 jbvp = getIthJsonbValueFromContainer(container, 0);
1552 }
1553
1554 /*
1555 * If the array is empty, return the entire LHS object, on the grounds
1556 * that we should do zero field or element extractions. For the
1557 * non-scalar case we can just hand back the object without much work. For
1558 * the scalar case, fall through and deal with the value below the loop.
1559 * (This inconsistency arises because there's no easy way to generate a
1560 * JsonbValue directly for root-level containers.)
1561 */
1562 if (npath <= 0 && jbvp == NULL)
1563 {
1564 if (as_text)
1565 {
1567 container,
1568 VARSIZE(jb))));
1569 }
1570 else
1571 {
1572 /* not text mode - just hand back the jsonb */
1574 }
1575 }
1576
1577 for (i = 0; i < npath; i++)
1578 {
1579 if (have_object)
1580 {
1581 text *subscr = DatumGetTextPP(path[i]);
1582
1583 jbvp = getKeyJsonValueFromContainer(container,
1584 VARDATA_ANY(subscr),
1585 VARSIZE_ANY_EXHDR(subscr),
1586 NULL);
1587 }
1588 else if (have_array)
1589 {
1590 int lindex;
1591 uint32 index;
1592 char *indextext = TextDatumGetCString(path[i]);
1593 char *endptr;
1594
1595 errno = 0;
1596 lindex = strtoint(indextext, &endptr, 10);
1597 if (endptr == indextext || *endptr != '\0' || errno != 0)
1598 {
1599 *isnull = true;
1600 return PointerGetDatum(NULL);
1601 }
1602
1603 if (lindex >= 0)
1604 {
1605 index = (uint32) lindex;
1606 }
1607 else
1608 {
1609 /* Handle negative subscript */
1610 uint32 nelements;
1611
1612 /* Container must be array, but make sure */
1613 if (!JsonContainerIsArray(container))
1614 elog(ERROR, "not a jsonb array");
1615
1616 nelements = JsonContainerSize(container);
1617
1618 if (lindex == INT_MIN || -lindex > nelements)
1619 {
1620 *isnull = true;
1621 return PointerGetDatum(NULL);
1622 }
1623 else
1624 index = nelements + lindex;
1625 }
1626
1627 jbvp = getIthJsonbValueFromContainer(container, index);
1628 }
1629 else
1630 {
1631 /* scalar, extraction yields a null */
1632 *isnull = true;
1633 return PointerGetDatum(NULL);
1634 }
1635
1636 if (jbvp == NULL)
1637 {
1638 *isnull = true;
1639 return PointerGetDatum(NULL);
1640 }
1641 else if (i == npath - 1)
1642 break;
1643
1644 if (jbvp->type == jbvBinary)
1645 {
1646 container = jbvp->val.binary.data;
1647 have_object = JsonContainerIsObject(container);
1648 have_array = JsonContainerIsArray(container);
1649 Assert(!JsonContainerIsScalar(container));
1650 }
1651 else
1652 {
1653 Assert(IsAJsonbScalar(jbvp));
1654 have_object = false;
1655 have_array = false;
1656 }
1657 }
1658
1659 if (as_text)
1660 {
1661 if (jbvp->type == jbvNull)
1662 {
1663 *isnull = true;
1664 return PointerGetDatum(NULL);
1665 }
1666
1667 return PointerGetDatum(JsonbValueAsText(jbvp));
1668 }
1669 else
1670 {
1671 Jsonb *res = JsonbValueToJsonb(jbvp);
1672
1673 /* not text mode - just hand back the jsonb */
1674 PG_RETURN_JSONB_P(res);
1675 }
1676}
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define DatumGetTextPP(X)
Definition: fmgr.h:292
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:466
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:209
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:223
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:299
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:420
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:224
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:222
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:472
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1802
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
int strtoint(const char *restrict str, char **restrict endptr, int base)
Definition: string.c:50
JsonbContainer root
Definition: jsonb.h:217
Definition: c.h:706
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition: varatt.h:472
static Size VARSIZE(const void *PTR)
Definition: varatt.h:298
static char * VARDATA_ANY(const void *PTR)
Definition: varatt.h:486
text * cstring_to_text(const char *s)
Definition: varlena.c:181

References Assert(), cstring_to_text(), DatumGetTextPP, elog, ERROR, getIthJsonbValueFromContainer(), getKeyJsonValueFromContainer(), i, IsAJsonbScalar, JB_ROOT_IS_ARRAY, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, jbvBinary, jbvNull, JsonbToCString(), JsonbValueAsText(), JsonbValueToJsonb(), JsonContainerIsArray, JsonContainerIsObject, JsonContainerIsScalar, JsonContainerSize, PG_RETURN_JSONB_P, PointerGetDatum(), Jsonb::root, strtoint(), TextDatumGetCString, JsonbValue::type, JsonbValue::val, VARDATA_ANY(), VARSIZE(), and VARSIZE_ANY_EXHDR().

Referenced by get_jsonb_path_all(), jsonb_subscript_fetch(), and jsonb_subscript_fetch_old().

◆ jsonb_set_element()

Datum jsonb_set_element ( Jsonb jb,
const Datum path,
int  path_len,
JsonbValue newval 
)

Definition at line 1679 of file jsonfuncs.c.

1681{
1682 JsonbInState state = {0};
1683 JsonbIterator *it;
1684 bool *path_nulls = palloc0_array(bool, path_len);
1685
1686 if (newval->type == jbvArray && newval->val.array.rawScalar)
1687 *newval = newval->val.array.elems[0];
1688
1689 it = JsonbIteratorInit(&jb->root);
1690
1691 setPath(&it, path, path_nulls, path_len, &state, 0, newval,
1694
1695 pfree(path_nulls);
1696
1698}
#define palloc0_array(type, count)
Definition: fe_memutils.h:77
#define newval
#define JB_PATH_CREATE
Definition: jsonfuncs.c:44
#define JB_PATH_CONSISTENT_POSITION
Definition: jsonfuncs.c:52
#define JB_PATH_FILL_GAPS
Definition: jsonfuncs.c:51
static void setPath(JsonbIterator **it, const Datum *path_elems, const bool *path_nulls, int path_len, JsonbInState *st, int level, JsonbValue *newval, int op_type)
Definition: jsonfuncs.c:5177
Definition: regguts.h:323

References JB_PATH_CONSISTENT_POSITION, JB_PATH_CREATE, JB_PATH_FILL_GAPS, jbvArray, JsonbIteratorInit(), JsonbValueToJsonb(), newval, palloc0_array, pfree(), PG_RETURN_JSONB_P, Jsonb::root, and setPath().

Referenced by jsonb_subscript_assign().

◆ JsonbDeepContains()

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

Definition at line 1189 of file jsonb_util.c.

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

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

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

◆ JsonbExtractScalar()

bool JsonbExtractScalar ( JsonbContainer jbc,
JsonbValue res 
)

Definition at line 1778 of file jsonb.c.

1779{
1780 JsonbIterator *it;
1782 JsonbValue tmp;
1783
1785 {
1786 /* inform caller about actual type of container */
1787 res->type = (JsonContainerIsArray(jbc)) ? jbvArray : jbvObject;
1788 return false;
1789 }
1790
1791 /*
1792 * A root scalar is stored as an array of one element, so we get the array
1793 * and then its first (and only) member.
1794 */
1795 it = JsonbIteratorInit(jbc);
1796
1797 tok = JsonbIteratorNext(&it, &tmp, true);
1798 Assert(tok == WJB_BEGIN_ARRAY);
1799 Assert(tmp.val.array.nElems == 1 && tmp.val.array.rawScalar);
1800
1801 tok = JsonbIteratorNext(&it, res, true);
1802 Assert(tok == WJB_ELEM);
1803 Assert(IsAJsonbScalar(res));
1804
1805 tok = JsonbIteratorNext(&it, &tmp, true);
1806 Assert(tok == WJB_END_ARRAY);
1807
1808 tok = JsonbIteratorNext(&it, &tmp, true);
1809 Assert(tok == WJB_DONE);
1810
1811 return true;
1812}
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:229

References Assert(), IsAJsonbScalar, jbvArray, jbvObject, JsonbIteratorInit(), JsonbIteratorNext(), JsonContainerIsArray, JsonContainerIsScalar, PG_USED_FOR_ASSERTS_ONLY, JsonbValue::type, JsonbValue::val, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, and WJB_END_ARRAY.

Referenced by executeJsonPath(), jsonb_bool(), jsonb_float4(), jsonb_float8(), jsonb_int2(), jsonb_int4(), jsonb_int8(), jsonb_numeric(), JsonbContainerTypeName(), JsonbUnquote(), JsonItemFromDatum(), and JsonPathValue().

◆ JsonbHashScalarValue()

void JsonbHashScalarValue ( const JsonbValue scalarVal,
uint32 hash 
)

Definition at line 1443 of file jsonb_util.c.

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

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

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

◆ JsonbHashScalarValueExtended()

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

Definition at line 1486 of file jsonb_util.c.

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

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

Referenced by jsonb_hash_extended().

◆ JsonbIteratorInit()

◆ JsonbIteratorNext()

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

Definition at line 973 of file jsonb_util.c.

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

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

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

◆ JsonbPGetDatum()

◆ JsonbToCString()

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

Definition at line 466 of file jsonb.c.

467{
468 return JsonbToCStringWorker(out, in, estimated_len, false);
469}
static char * JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
Definition: jsonb.c:484

References JsonbToCStringWorker().

Referenced by jsonb_get_element(), jsonb_out(), jsonb_send(), JsonbUnquote(), JsonbValueAsText(), and populate_scalar().

◆ JsonbToCStringIndent()

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

Definition at line 475 of file jsonb.c.

476{
477 return JsonbToCStringWorker(out, in, estimated_len, true);
478}

References JsonbToCStringWorker().

Referenced by jsonb_pretty().

◆ JsonbToJsonbValue()

void JsonbToJsonbValue ( Jsonb jsonb,
JsonbValue val 
)

Definition at line 76 of file jsonb_util.c.

77{
78 val->type = jbvBinary;
79 val->val.binary.data = &jsonb->root;
80 val->val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
81}
#define VARHDRSZ
Definition: c.h:711

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

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

◆ JsonbTypeName()

const char * JsonbTypeName ( JsonbValue val)

Definition at line 173 of file jsonb.c.

174{
175 switch (val->type)
176 {
177 case jbvBinary:
178 return JsonbContainerTypeName(val->val.binary.data);
179 case jbvObject:
180 return "object";
181 case jbvArray:
182 return "array";
183 case jbvNumeric:
184 return "number";
185 case jbvString:
186 return "string";
187 case jbvBool:
188 return "boolean";
189 case jbvNull:
190 return "null";
191 case jbvDatetime:
192 switch (val->val.datetime.typid)
193 {
194 case DATEOID:
195 return "date";
196 case TIMEOID:
197 return "time without time zone";
198 case TIMETZOID:
199 return "time with time zone";
200 case TIMESTAMPOID:
201 return "timestamp without time zone";
202 case TIMESTAMPTZOID:
203 return "timestamp with time zone";
204 default:
205 elog(ERROR, "unrecognized jsonb value datetime type: %d",
206 val->val.datetime.typid);
207 }
208 return "unknown";
209 default:
210 elog(ERROR, "unrecognized jsonb value type: %d", val->type);
211 return "unknown";
212 }
213}
static const char * JsonbContainerTypeName(JsonbContainer *jbc)
Definition: jsonb.c:152

References elog, ERROR, jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, JsonbContainerTypeName(), and val.

Referenced by executeItemOptUnwrapTarget(), and JsonbContainerTypeName().

◆ JsonbUnquote()

char * JsonbUnquote ( Jsonb jb)

Definition at line 2039 of file jsonb.c.

2040{
2041 if (JB_ROOT_IS_SCALAR(jb))
2042 {
2043 JsonbValue v;
2044
2045 (void) JsonbExtractScalar(&jb->root, &v);
2046
2047 if (v.type == jbvString)
2048 return pnstrdup(v.val.string.val, v.val.string.len);
2049 else if (v.type == jbvBool)
2050 return pstrdup(v.val.boolean ? "true" : "false");
2051 else if (v.type == jbvNumeric)
2053 PointerGetDatum(v.val.numeric)));
2054 else if (v.type == jbvNull)
2055 return pstrdup("null");
2056 else
2057 {
2058 elog(ERROR, "unrecognized jsonb value type %d", v.type);
2059 return NULL;
2060 }
2061 }
2062 else
2063 return JsonbToCString(NULL, &jb->root, VARSIZE(jb));
2064}
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:799
bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1778
char * pstrdup(const char *in)
Definition: mcxt.c:1759
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1770
static char * DatumGetCString(Datum X)
Definition: postgres.h:345

References DatumGetCString(), DirectFunctionCall1, elog, ERROR, JB_ROOT_IS_SCALAR, jbvBool, jbvNull, jbvNumeric, jbvString, JsonbExtractScalar(), JsonbToCString(), numeric_out(), pnstrdup(), PointerGetDatum(), pstrdup(), Jsonb::root, JsonbValue::type, JsonbValue::val, and VARSIZE().

Referenced by json_populate_type().

◆ JsonbValueToJsonb()

Jsonb * JsonbValueToJsonb ( JsonbValue val)

Definition at line 96 of file jsonb_util.c.

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

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

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

◆ pushJsonbValue()

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

Definition at line 583 of file jsonb_util.c.

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

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

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

◆ to_jsonb_is_immutable()

bool to_jsonb_is_immutable ( Oid  typoid)

Definition at line 1086 of file jsonb.c.

1087{
1088 JsonTypeCategory tcategory;
1089 Oid outfuncoid;
1090
1091 json_categorize_type(typoid, true, &tcategory, &outfuncoid);
1092
1093 switch (tcategory)
1094 {
1095 case JSONTYPE_NULL:
1096 case JSONTYPE_BOOL:
1097 case JSONTYPE_JSON:
1098 case JSONTYPE_JSONB:
1099 return true;
1100
1101 case JSONTYPE_DATE:
1102 case JSONTYPE_TIMESTAMP:
1104 return false;
1105
1106 case JSONTYPE_ARRAY:
1107 return false; /* TODO recurse into elements */
1108
1109 case JSONTYPE_COMPOSITE:
1110 return false; /* TODO recurse into fields */
1111
1112 case JSONTYPE_NUMERIC:
1113 case JSONTYPE_CAST:
1114 case JSONTYPE_OTHER:
1115 return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
1116 }
1117
1118 return false; /* not reached */
1119}
void json_categorize_type(Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonfuncs.c:5968
JsonTypeCategory
Definition: jsonfuncs.h:69
@ JSONTYPE_JSON
Definition: jsonfuncs.h:76
@ JSONTYPE_NULL
Definition: jsonfuncs.h:70
@ JSONTYPE_TIMESTAMP
Definition: jsonfuncs.h:74
@ JSONTYPE_NUMERIC
Definition: jsonfuncs.h:72
@ JSONTYPE_DATE
Definition: jsonfuncs.h:73
@ JSONTYPE_BOOL
Definition: jsonfuncs.h:71
@ JSONTYPE_OTHER
Definition: jsonfuncs.h:81
@ JSONTYPE_CAST
Definition: jsonfuncs.h:80
@ JSONTYPE_COMPOSITE
Definition: jsonfuncs.h:79
@ JSONTYPE_ARRAY
Definition: jsonfuncs.h:78
@ JSONTYPE_TIMESTAMPTZ
Definition: jsonfuncs.h:75
@ JSONTYPE_JSONB
Definition: jsonfuncs.h:77
char func_volatile(Oid funcid)
Definition: lsyscache.c:1945
unsigned int Oid
Definition: postgres_ext.h:32

References func_volatile(), json_categorize_type(), JSONTYPE_ARRAY, JSONTYPE_BOOL, JSONTYPE_CAST, JSONTYPE_COMPOSITE, JSONTYPE_DATE, JSONTYPE_JSON, JSONTYPE_JSONB, JSONTYPE_NULL, JSONTYPE_NUMERIC, JSONTYPE_OTHER, JSONTYPE_TIMESTAMP, and JSONTYPE_TIMESTAMPTZ.

Referenced by contain_mutable_functions_walker().