postgresql/src/include/utils/jsonb.h

321 lines
10 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* jsonb.h
* Declarations for jsonb data type support.
*
* Copyright (c) 1996-2014, PostgreSQL Global Development Group
*
* src/include/utils/jsonb.h
*
*-------------------------------------------------------------------------
*/
#ifndef __JSONB_H__
#define __JSONB_H__
#include "lib/stringinfo.h"
#include "utils/array.h"
#include "utils/numeric.h"
/*
* JB_CMASK is used to extract count of items
*
* It's not possible to get more than 2^28 items into an Jsonb.
*/
#define JB_CMASK 0x0FFFFFFF
#define JB_FSCALAR 0x10000000
#define JB_FOBJECT 0x20000000
#define JB_FARRAY 0x40000000
/* Get information on varlena Jsonb */
#define JB_ROOT_COUNT(jbp_) ( *(uint32*) VARDATA(jbp_) & JB_CMASK)
#define JB_ROOT_IS_SCALAR(jbp_) ( *(uint32*) VARDATA(jbp_) & JB_FSCALAR)
#define JB_ROOT_IS_OBJECT(jbp_) ( *(uint32*) VARDATA(jbp_) & JB_FOBJECT)
#define JB_ROOT_IS_ARRAY(jbp_) ( *(uint32*) VARDATA(jbp_) & JB_FARRAY)
/* Jentry macros */
#define JENTRY_POSMASK 0x0FFFFFFF
#define JENTRY_ISFIRST 0x80000000
#define JENTRY_TYPEMASK (~(JENTRY_POSMASK | JENTRY_ISFIRST))
#define JENTRY_ISSTRING 0x00000000
#define JENTRY_ISNUMERIC 0x10000000
#define JENTRY_ISNEST 0x20000000
#define JENTRY_ISNULL 0x40000000
#define JENTRY_ISBOOL (JENTRY_ISNUMERIC | JENTRY_ISNEST)
#define JENTRY_ISFALSE JENTRY_ISBOOL
#define JENTRY_ISTRUE (JENTRY_ISBOOL | 0x40000000)
/* Note possible multiple evaluations, also access to prior array element */
#define JBE_ISFIRST(je_) (((je_).header & JENTRY_ISFIRST) != 0)
#define JBE_ISSTRING(je_) (((je_).header & JENTRY_TYPEMASK) == JENTRY_ISSTRING)
#define JBE_ISNUMERIC(je_) (((je_).header & JENTRY_TYPEMASK) == JENTRY_ISNUMERIC)
#define JBE_ISNEST(je_) (((je_).header & JENTRY_TYPEMASK) == JENTRY_ISNEST)
#define JBE_ISNULL(je_) (((je_).header & JENTRY_TYPEMASK) == JENTRY_ISNULL)
#define JBE_ISBOOL(je_) (((je_).header & JENTRY_TYPEMASK & JENTRY_ISBOOL) == JENTRY_ISBOOL)
#define JBE_ISBOOL_TRUE(je_) (((je_).header & JENTRY_TYPEMASK) == JENTRY_ISTRUE)
#define JBE_ISBOOL_FALSE(je_) (JBE_ISBOOL(je_) && !JBE_ISBOOL_TRUE(je_))
/* Get offset for Jentry */
#define JBE_ENDPOS(je_) ((je_).header & JENTRY_POSMASK)
#define JBE_OFF(je_) (JBE_ISFIRST(je_) ? 0 : JBE_ENDPOS((&(je_))[-1]))
#define JBE_LEN(je_) (JBE_ISFIRST(je_) ? \
JBE_ENDPOS(je_) \
: JBE_ENDPOS(je_) - JBE_ENDPOS((&(je_))[-1]))
/* Flags indicating a stage of sequential Jsonb processing */
#define WJB_DONE 0x000
#define WJB_KEY 0x001
#define WJB_VALUE 0x002
#define WJB_ELEM 0x004
#define WJB_BEGIN_ARRAY 0x008
#define WJB_END_ARRAY 0x010
#define WJB_BEGIN_OBJECT 0x020
#define WJB_END_OBJECT 0x040
/*
* When using a GIN index for jsonb, we choose to index both keys and values.
* The storage format is text, with K, or V prepended to the string to indicate
* key/element or value/element.
*
* Jsonb Keys and string array elements are treated equivalently when
* serialized to text index storage. One day we may wish to create an opclass
* that only indexes values, but for now keys and values are stored in GIN
* indexes in a way that doesn't really consider their relationship to each
* other.
*/
#define JKEYELEM 'K'
#define JVAL 'V'
#define JsonbContainsStrategyNumber 7
#define JsonbExistsStrategyNumber 9
#define JsonbExistsAnyStrategyNumber 10
#define JsonbExistsAllStrategyNumber 11
/* Convenience macros */
#define DatumGetJsonb(d) ((Jsonb *) PG_DETOAST_DATUM(d))
#define JsonbGetDatum(p) PointerGetDatum(p)
#define PG_GETARG_JSONB(x) DatumGetJsonb(PG_GETARG_DATUM(x))
#define PG_RETURN_JSONB(x) PG_RETURN_POINTER(x)
typedef struct JsonbPair JsonbPair;
typedef struct JsonbValue JsonbValue;
typedef char *JsonbSuperHeader;
/*
* Jsonbs are varlena objects, so must meet the varlena convention that the
* first int32 of the object contains the total object size in bytes. Be sure
* to use VARSIZE() and SET_VARSIZE() to access it, though!
*
* Jsonb is the on-disk representation, in contrast to the in-memory JsonbValue
* representation. Often, JsonbValues are just shims through which a Jsonb
* buffer is accessed, but they can also be deep copied and passed around.
*
* We have an abstraction called a "superheader". This is a pointer that
* conventionally points to the first item after our 4-byte uncompressed
* varlena header, from which we can read flags using bitwise operations.
*
* Frequently, we pass a superheader reference to a function, and it doesn't
* matter if it points to just after the start of a Jsonb, or to a temp buffer.
*/
typedef struct
{
int32 vl_len_; /* varlena header (do not touch directly!) */
uint32 superheader;
/* (array of JEntry follows, size determined using uint32 superheader) */
} Jsonb;
/*
* JEntry: there is one of these for each key _and_ value for objects. Arrays
* have one per element.
*
* The position offset points to the _end_ so that we can get the length by
* subtraction from the previous entry. The JENTRY_ISFIRST flag indicates if
* there is a previous entry.
*/
typedef struct
{
uint32 header; /* Shares some flags with superheader */
} JEntry;
#define IsAJsonbScalar(jsonbval) ((jsonbval)->type >= jbvNull && \
(jsonbval)->type <= jbvBool)
/*
* JsonbValue: In-memory representation of Jsonb. This is a convenient
* deserialized representation, that can easily support using the "val"
* union across underlying types during manipulation. The Jsonb on-disk
* representation has various alignment considerations.
*/
struct JsonbValue
{
enum
{
/* Scalar types */
jbvNull = 0x0,
jbvString,
jbvNumeric,
jbvBool,
/* Composite types */
jbvArray = 0x10,
jbvObject,
/* Binary (i.e. struct Jsonb) jbvArray/jbvObject */
jbvBinary
} type; /* Influences sort order */
int estSize; /* Estimated size of node (including subnodes) */
union
{
Numeric numeric;
bool boolean;
struct
{
int len;
char *val; /* Not necessarily null-terminated */
} string; /* String primitive type */
struct
{
int nElems;
JsonbValue *elems;
bool rawScalar; /* Top-level "raw scalar" array? */
} array; /* Array container type */
struct
{
int nPairs; /* 1 pair, 2 elements */
JsonbPair *pairs;
} object; /* Associative container type */
struct
{
int len;
char *data;
} binary;
} val;
};
/*
* Pair within an Object.
*
* Pairs with duplicate keys are de-duplicated. We store the order for the
* benefit of doing so in a well-defined way with respect to the original
* observed order (which is "last observed wins"). This is only used briefly
* when originally constructing a Jsonb.
*/
struct JsonbPair
{
JsonbValue key; /* Must be a jbvString */
JsonbValue value; /* May be of any type */
uint32 order; /* preserves order of pairs with equal keys */
};
/* Conversion state used when parsing Jsonb from text, or for type coercion */
typedef struct JsonbParseState
{
JsonbValue contVal;
Size size;
struct JsonbParseState *next;
} JsonbParseState;
/*
* JsonbIterator holds details of the type for each iteration. It also stores a
* Jsonb varlena buffer, which can be directly accessed in some contexts.
*/
typedef enum
{
jbi_start = 0x0,
jbi_key,
jbi_value,
jbi_elem
} JsonbIterState;
typedef struct JsonbIterator
{
/* Jsonb varlena buffer (may or may not be root) */
char *buffer;
/* Current value */
uint32 containerType; /* Never of value JB_FSCALAR, since scalars
* will appear in pseudo-arrays */
uint32 nElems; /* Number of elements in metaArray (will be
* nPairs for objects) */
bool isScalar; /* Pseudo-array scalar value? */
JEntry *meta;
/* Current item in buffer (up to nElems, but must * 2 for objects) */
int i;
/*
* Data proper. Note that this points just past end of "meta" array. We
* use its metadata (Jentrys) with JBE_OFF() macro to find appropriate
* offsets into this array.
*/
char *dataProper;
/* Private state */
JsonbIterState state;
struct JsonbIterator *parent;
} JsonbIterator;
/* I/O routines */
extern Datum jsonb_in(PG_FUNCTION_ARGS);
extern Datum jsonb_out(PG_FUNCTION_ARGS);
extern Datum jsonb_recv(PG_FUNCTION_ARGS);
extern Datum jsonb_send(PG_FUNCTION_ARGS);
extern Datum jsonb_typeof(PG_FUNCTION_ARGS);
/* Indexing-related ops */
extern Datum jsonb_exists(PG_FUNCTION_ARGS);
extern Datum jsonb_exists_any(PG_FUNCTION_ARGS);
extern Datum jsonb_exists_all(PG_FUNCTION_ARGS);
extern Datum jsonb_contains(PG_FUNCTION_ARGS);
extern Datum jsonb_contained(PG_FUNCTION_ARGS);
extern Datum jsonb_ne(PG_FUNCTION_ARGS);
extern Datum jsonb_lt(PG_FUNCTION_ARGS);
extern Datum jsonb_gt(PG_FUNCTION_ARGS);
extern Datum jsonb_le(PG_FUNCTION_ARGS);
extern Datum jsonb_ge(PG_FUNCTION_ARGS);
extern Datum jsonb_eq(PG_FUNCTION_ARGS);
extern Datum jsonb_cmp(PG_FUNCTION_ARGS);
extern Datum jsonb_hash(PG_FUNCTION_ARGS);
/* GIN support functions */
extern Datum gin_compare_jsonb(PG_FUNCTION_ARGS);
extern Datum gin_extract_jsonb(PG_FUNCTION_ARGS);
extern Datum gin_extract_jsonb_query(PG_FUNCTION_ARGS);
extern Datum gin_consistent_jsonb(PG_FUNCTION_ARGS);
extern Datum gin_triconsistent_jsonb(PG_FUNCTION_ARGS);
/* GIN hash opclass functions */
extern Datum gin_extract_jsonb_hash(PG_FUNCTION_ARGS);
extern Datum gin_extract_jsonb_query_hash(PG_FUNCTION_ARGS);
extern Datum gin_consistent_jsonb_hash(PG_FUNCTION_ARGS);
extern Datum gin_triconsistent_jsonb_hash(PG_FUNCTION_ARGS);
/* Support functions */
extern int compareJsonbSuperHeaderValue(JsonbSuperHeader a,
JsonbSuperHeader b);
extern JsonbValue *findJsonbValueFromSuperHeader(JsonbSuperHeader sheader,
uint32 flags,
uint32 *lowbound,
JsonbValue *key);
extern JsonbValue *getIthJsonbValueFromSuperHeader(JsonbSuperHeader sheader,
uint32 i);
extern JsonbValue *pushJsonbValue(JsonbParseState **pstate, int seq,
JsonbValue *scalarVal);
extern JsonbIterator *JsonbIteratorInit(JsonbSuperHeader buffer);
extern int JsonbIteratorNext(JsonbIterator **it, JsonbValue *val,
bool skipNested);
extern Jsonb *JsonbValueToJsonb(JsonbValue *val);
extern bool JsonbDeepContains(JsonbIterator **val,
JsonbIterator **mContained);
extern JsonbValue *arrayToJsonbSortedArray(ArrayType *a);
extern void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash);
/* jsonb.c support function */
extern char *JsonbToCString(StringInfo out, JsonbSuperHeader in,
int estimated_len);
#endif /* __JSONB_H__ */