Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* 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
|
2014-04-02 20:30:08 +02:00
|
|
|
* deserialized representation, that can easily support using the "val"
|
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
|
|
|
* 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;
|
2014-04-02 20:30:08 +02:00
|
|
|
} val;
|
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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__ */
|