mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-06 19:56:56 +02:00
321 lines
10 KiB
C
321 lines
10 KiB
C
|
/*-------------------------------------------------------------------------
|
||
|
*
|
||
|
* 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 anonymous
|
||
|
* 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;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* 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__ */
|