summaryrefslogtreecommitdiff
path: root/src/include/utils/jsonb.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/utils/jsonb.h')
-rw-r--r--src/include/utils/jsonb.h320
1 files changed, 320 insertions, 0 deletions
diff --git a/src/include/utils/jsonb.h b/src/include/utils/jsonb.h
new file mode 100644
index 00000000000..a70cbd59400
--- /dev/null
+++ b/src/include/utils/jsonb.h
@@ -0,0 +1,320 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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__ */