Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes16kdownloads
jsonb.h440 linesDownload Raw Back to utils
1/*-------------------------------------------------------------------------2 *3 * jsonb.h4 *	  Declarations for jsonb data type support.5 *6 * Copyright (c) 1996-2023, PostgreSQL Global Development Group7 *8 * src/include/utils/jsonb.h9 *10 *-------------------------------------------------------------------------11 */12#ifndef __JSONB_H__13#define __JSONB_H__14 15#include "lib/stringinfo.h"16#include "utils/array.h"17#include "utils/numeric.h"18 19/* Tokens used when sequentially processing a jsonb value */20typedef enum21{22	WJB_DONE,23	WJB_KEY,24	WJB_VALUE,25	WJB_ELEM,26	WJB_BEGIN_ARRAY,27	WJB_END_ARRAY,28	WJB_BEGIN_OBJECT,29	WJB_END_OBJECT30} JsonbIteratorToken;31 32/* Strategy numbers for GIN index opclasses */33#define JsonbContainsStrategyNumber		734#define JsonbExistsStrategyNumber		935#define JsonbExistsAnyStrategyNumber	1036#define JsonbExistsAllStrategyNumber	1137#define JsonbJsonpathExistsStrategyNumber		1538#define JsonbJsonpathPredicateStrategyNumber	1639 40 41/*42 * In the standard jsonb_ops GIN opclass for jsonb, we choose to index both43 * keys and values.  The storage format is text.  The first byte of the text44 * string distinguishes whether this is a key (always a string), null value,45 * boolean value, numeric value, or string value.  However, array elements46 * that are strings are marked as though they were keys; this imprecision47 * supports the definition of the "exists" operator, which treats array48 * elements like keys.  The remainder of the text string is empty for a null49 * value, "t" or "f" for a boolean value, a normalized print representation of50 * a numeric value, or the text of a string value.  However, if the length of51 * this text representation would exceed JGIN_MAXLENGTH bytes, we instead hash52 * the text representation and store an 8-hex-digit representation of the53 * uint32 hash value, marking the prefix byte with an additional bit to54 * distinguish that this has happened.  Hashing long strings saves space and55 * ensures that we won't overrun the maximum entry length for a GIN index.56 * (But JGIN_MAXLENGTH is quite a bit shorter than GIN's limit.  It's chosen57 * to ensure that the on-disk text datum will have a short varlena header.)58 * Note that when any hashed item appears in a query, we must recheck index59 * matches against the heap tuple; currently, this costs nothing because we60 * must always recheck for other reasons.61 */62#define JGINFLAG_KEY	0x01	/* key (or string array element) */63#define JGINFLAG_NULL	0x02	/* null value */64#define JGINFLAG_BOOL	0x03	/* boolean value */65#define JGINFLAG_NUM	0x04	/* numeric value */66#define JGINFLAG_STR	0x05	/* string value (if not an array element) */67#define JGINFLAG_HASHED 0x10	/* OR'd into flag if value was hashed */68#define JGIN_MAXLENGTH	125		/* max length of text part before hashing */69 70typedef struct JsonbPair JsonbPair;71typedef struct JsonbValue JsonbValue;72 73/*74 * Jsonbs are varlena objects, so must meet the varlena convention that the75 * first int32 of the object contains the total object size in bytes.  Be sure76 * to use VARSIZE() and SET_VARSIZE() to access it, though!77 *78 * Jsonb is the on-disk representation, in contrast to the in-memory JsonbValue79 * representation.  Often, JsonbValues are just shims through which a Jsonb80 * buffer is accessed, but they can also be deep copied and passed around.81 *82 * Jsonb is a tree structure. Each node in the tree consists of a JEntry83 * header and a variable-length content (possibly of zero size).  The JEntry84 * header indicates what kind of a node it is, e.g. a string or an array,85 * and provides the length of its variable-length portion.86 *87 * The JEntry and the content of a node are not stored physically together.88 * Instead, the container array or object has an array that holds the JEntrys89 * of all the child nodes, followed by their variable-length portions.90 *91 * The root node is an exception; it has no parent array or object that could92 * hold its JEntry. Hence, no JEntry header is stored for the root node.  It93 * is implicitly known that the root node must be an array or an object,94 * so we can get away without the type indicator as long as we can distinguish95 * the two.  For that purpose, both an array and an object begin with a uint3296 * header field, which contains an JB_FOBJECT or JB_FARRAY flag.  When a naked97 * scalar value needs to be stored as a Jsonb value, what we actually store is98 * an array with one element, with the flags in the array's header field set99 * to JB_FSCALAR | JB_FARRAY.100 *101 * Overall, the Jsonb struct requires 4-bytes alignment. Within the struct,102 * the variable-length portion of some node types is aligned to a 4-byte103 * boundary, while others are not. When alignment is needed, the padding is104 * in the beginning of the node that requires it. For example, if a numeric105 * node is stored after a string node, so that the numeric node begins at106 * offset 3, the variable-length portion of the numeric node will begin with107 * one padding byte so that the actual numeric data is 4-byte aligned.108 */109 110/*111 * JEntry format.112 *113 * The least significant 28 bits store either the data length of the entry,114 * or its end+1 offset from the start of the variable-length portion of the115 * containing object.  The next three bits store the type of the entry, and116 * the high-order bit tells whether the least significant bits store a length117 * or an offset.118 *119 * The reason for the offset-or-length complication is to compromise between120 * access speed and data compressibility.  In the initial design each JEntry121 * always stored an offset, but this resulted in JEntry arrays with horrible122 * compressibility properties, so that TOAST compression of a JSONB did not123 * work well.  Storing only lengths would greatly improve compressibility,124 * but it makes random access into large arrays expensive (O(N) not O(1)).125 * So what we do is store an offset in every JB_OFFSET_STRIDE'th JEntry and126 * a length in the rest.  This results in reasonably compressible data (as127 * long as the stride isn't too small).  We may have to examine as many as128 * JB_OFFSET_STRIDE JEntrys in order to find out the offset or length of any129 * given item, but that's still O(1) no matter how large the container is.130 *131 * We could avoid eating a flag bit for this purpose if we were to store132 * the stride in the container header, or if we were willing to treat the133 * stride as an unchangeable constant.  Neither of those options is very134 * attractive though.135 */136typedef uint32 JEntry;137 138#define JENTRY_OFFLENMASK		0x0FFFFFFF139#define JENTRY_TYPEMASK			0x70000000140#define JENTRY_HAS_OFF			0x80000000141 142/* values stored in the type bits */143#define JENTRY_ISSTRING			0x00000000144#define JENTRY_ISNUMERIC		0x10000000145#define JENTRY_ISBOOL_FALSE		0x20000000146#define JENTRY_ISBOOL_TRUE		0x30000000147#define JENTRY_ISNULL			0x40000000148#define JENTRY_ISCONTAINER		0x50000000	/* array or object */149 150/* Access macros.  Note possible multiple evaluations */151#define JBE_OFFLENFLD(je_)		((je_) & JENTRY_OFFLENMASK)152#define JBE_HAS_OFF(je_)		(((je_) & JENTRY_HAS_OFF) != 0)153#define JBE_ISSTRING(je_)		(((je_) & JENTRY_TYPEMASK) == JENTRY_ISSTRING)154#define JBE_ISNUMERIC(je_)		(((je_) & JENTRY_TYPEMASK) == JENTRY_ISNUMERIC)155#define JBE_ISCONTAINER(je_)	(((je_) & JENTRY_TYPEMASK) == JENTRY_ISCONTAINER)156#define JBE_ISNULL(je_)			(((je_) & JENTRY_TYPEMASK) == JENTRY_ISNULL)157#define JBE_ISBOOL_TRUE(je_)	(((je_) & JENTRY_TYPEMASK) == JENTRY_ISBOOL_TRUE)158#define JBE_ISBOOL_FALSE(je_)	(((je_) & JENTRY_TYPEMASK) == JENTRY_ISBOOL_FALSE)159#define JBE_ISBOOL(je_)			(JBE_ISBOOL_TRUE(je_) || JBE_ISBOOL_FALSE(je_))160 161/* Macro for advancing an offset variable to the next JEntry */162#define JBE_ADVANCE_OFFSET(offset, je) \163	do { \164		JEntry	je_ = (je); \165		if (JBE_HAS_OFF(je_)) \166			(offset) = JBE_OFFLENFLD(je_); \167		else \168			(offset) += JBE_OFFLENFLD(je_); \169	} while(0)170 171/*172 * We store an offset, not a length, every JB_OFFSET_STRIDE children.173 * Caution: this macro should only be referenced when creating a JSONB174 * value.  When examining an existing value, pay attention to the HAS_OFF175 * bits instead.  This allows changes in the offset-placement heuristic176 * without breaking on-disk compatibility.177 */178#define JB_OFFSET_STRIDE		32179 180/*181 * A jsonb array or object node, within a Jsonb Datum.182 *183 * An array has one child for each element, stored in array order.184 *185 * An object has two children for each key/value pair.  The keys all appear186 * first, in key sort order; then the values appear, in an order matching the187 * key order.  This arrangement keeps the keys compact in memory, making a188 * search for a particular key more cache-friendly.189 */190typedef struct JsonbContainer191{192	uint32		header;			/* number of elements or key/value pairs, and193								 * flags */194	JEntry		children[FLEXIBLE_ARRAY_MEMBER];195 196	/* the data for each child node follows. */197} JsonbContainer;198 199/* flags for the header-field in JsonbContainer */200#define JB_CMASK				0x0FFFFFFF	/* mask for count field */201#define JB_FSCALAR				0x10000000	/* flag bits */202#define JB_FOBJECT				0x20000000203#define JB_FARRAY				0x40000000204 205/* convenience macros for accessing a JsonbContainer struct */206#define JsonContainerSize(jc)		((jc)->header & JB_CMASK)207#define JsonContainerIsScalar(jc)	(((jc)->header & JB_FSCALAR) != 0)208#define JsonContainerIsObject(jc)	(((jc)->header & JB_FOBJECT) != 0)209#define JsonContainerIsArray(jc)	(((jc)->header & JB_FARRAY) != 0)210 211/* The top-level on-disk format for a jsonb datum. */212typedef struct213{214	int32		vl_len_;		/* varlena header (do not touch directly!) */215	JsonbContainer root;216} Jsonb;217 218/* convenience macros for accessing the root container in a Jsonb datum */219#define JB_ROOT_COUNT(jbp_)		(*(uint32 *) VARDATA(jbp_) & JB_CMASK)220#define JB_ROOT_IS_SCALAR(jbp_) ((*(uint32 *) VARDATA(jbp_) & JB_FSCALAR) != 0)221#define JB_ROOT_IS_OBJECT(jbp_) ((*(uint32 *) VARDATA(jbp_) & JB_FOBJECT) != 0)222#define JB_ROOT_IS_ARRAY(jbp_)	((*(uint32 *) VARDATA(jbp_) & JB_FARRAY) != 0)223 224 225enum jbvType226{227	/* Scalar types */228	jbvNull = 0x0,229	jbvString,230	jbvNumeric,231	jbvBool,232	/* Composite types */233	jbvArray = 0x10,234	jbvObject,235	/* Binary (i.e. struct Jsonb) jbvArray/jbvObject */236	jbvBinary,237 238	/*239	 * Virtual types.240	 *241	 * These types are used only for in-memory JSON processing and serialized242	 * into JSON strings when outputted to json/jsonb.243	 */244	jbvDatetime = 0x20,245};246 247/*248 * JsonbValue:	In-memory representation of Jsonb.  This is a convenient249 * deserialized representation, that can easily support using the "val"250 * union across underlying types during manipulation.  The Jsonb on-disk251 * representation has various alignment considerations.252 */253struct JsonbValue254{255	enum jbvType type;			/* Influences sort order */256 257	union258	{259		Numeric numeric;260		bool		boolean;261		struct262		{263			int			len;264			char	   *val;	/* Not necessarily null-terminated */265		}			string;		/* String primitive type */266 267		struct268		{269			int			nElems;270			JsonbValue *elems;271			bool		rawScalar;	/* Top-level "raw scalar" array? */272		}			array;		/* Array container type */273 274		struct275		{276			int			nPairs; /* 1 pair, 2 elements */277			JsonbPair  *pairs;278		}			object;		/* Associative container type */279 280		struct281		{282			int			len;283			JsonbContainer *data;284		}			binary;		/* Array or object, in on-disk format */285 286		struct287		{288			Datum		value;289			Oid			typid;290			int32		typmod;291			int			tz;		/* Numeric time zone, in seconds, for292								 * TimestampTz data type */293		}			datetime;294	}			val;295};296 297#define IsAJsonbScalar(jsonbval)	(((jsonbval)->type >= jbvNull && \298									  (jsonbval)->type <= jbvBool) || \299									  (jsonbval)->type == jbvDatetime)300 301/*302 * Key/value pair within an Object.303 *304 * This struct type is only used briefly while constructing a Jsonb; it is305 * *not* the on-disk representation.306 *307 * Pairs with duplicate keys are de-duplicated.  We store the originally308 * observed pair ordering for the purpose of removing duplicates in a309 * well-defined way (which is "last observed wins").310 */311struct JsonbPair312{313	JsonbValue	key;			/* Must be a jbvString */314	JsonbValue	value;			/* May be of any type */315	uint32		order;			/* Pair's index in original sequence */316};317 318/* Conversion state used when parsing Jsonb from text, or for type coercion */319typedef struct JsonbParseState320{321	JsonbValue	contVal;322	Size		size;323	struct JsonbParseState *next;324	bool		unique_keys;	/* Check object key uniqueness */325	bool		skip_nulls;		/* Skip null object fields */326} JsonbParseState;327 328/*329 * JsonbIterator holds details of the type for each iteration. It also stores a330 * Jsonb varlena buffer, which can be directly accessed in some contexts.331 */332typedef enum333{334	JBI_ARRAY_START,335	JBI_ARRAY_ELEM,336	JBI_OBJECT_START,337	JBI_OBJECT_KEY,338	JBI_OBJECT_VALUE339} JsonbIterState;340 341typedef struct JsonbIterator342{343	/* Container being iterated */344	JsonbContainer *container;345	uint32		nElems;			/* Number of elements in children array (will346								 * be nPairs for objects) */347	bool		isScalar;		/* Pseudo-array scalar value? */348	JEntry	   *children;		/* JEntrys for child nodes */349	/* Data proper.  This points to the beginning of the variable-length data */350	char	   *dataProper;351 352	/* Current item in buffer (up to nElems) */353	int			curIndex;354 355	/* Data offset corresponding to current item */356	uint32		curDataOffset;357 358	/*359	 * If the container is an object, we want to return keys and values360	 * alternately; so curDataOffset points to the current key, and361	 * curValueOffset points to the current value.362	 */363	uint32		curValueOffset;364 365	/* Private state */366	JsonbIterState state;367 368	struct JsonbIterator *parent;369} JsonbIterator;370 371 372/* Convenience macros */373static inline Jsonb *374DatumGetJsonbP(Datum d)375{376	return (Jsonb *) PG_DETOAST_DATUM(d);377}378 379static inline Jsonb *380DatumGetJsonbPCopy(Datum d)381{382	return (Jsonb *) PG_DETOAST_DATUM_COPY(d);383}384 385static inline Datum386JsonbPGetDatum(const Jsonb *p)387{388	return PointerGetDatum(p);389}390 391#define PG_GETARG_JSONB_P(x)	DatumGetJsonbP(PG_GETARG_DATUM(x))392#define PG_GETARG_JSONB_P_COPY(x)	DatumGetJsonbPCopy(PG_GETARG_DATUM(x))393#define PG_RETURN_JSONB_P(x)	PG_RETURN_POINTER(x)394 395/* Support functions */396extern uint32 getJsonbOffset(const JsonbContainer *jc, int index);397extern uint32 getJsonbLength(const JsonbContainer *jc, int index);398extern int	compareJsonbContainers(JsonbContainer *a, JsonbContainer *b);399extern JsonbValue *findJsonbValueFromContainer(JsonbContainer *container,400											   uint32 flags,401											   JsonbValue *key);402extern JsonbValue *getKeyJsonValueFromContainer(JsonbContainer *container,403												const char *keyVal, int keyLen,404												JsonbValue *res);405extern JsonbValue *getIthJsonbValueFromContainer(JsonbContainer *container,406												 uint32 i);407extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,408								  JsonbIteratorToken seq, JsonbValue *jbval);409extern JsonbIterator *JsonbIteratorInit(JsonbContainer *container);410extern JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val,411											bool skipNested);412extern void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val);413extern Jsonb *JsonbValueToJsonb(JsonbValue *val);414extern bool JsonbDeepContains(JsonbIterator **val,415							  JsonbIterator **mContained);416extern void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash);417extern void JsonbHashScalarValueExtended(const JsonbValue *scalarVal,418										 uint64 *hash, uint64 seed);419 420/* jsonb.c support functions */421extern char *JsonbToCString(StringInfo out, JsonbContainer *in,422							int estimated_len);423extern char *JsonbToCStringIndent(StringInfo out, JsonbContainer *in,424								  int estimated_len);425extern bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res);426extern const char *JsonbTypeName(JsonbValue *val);427 428extern Datum jsonb_set_element(Jsonb *jb, Datum *path, int path_len,429							   JsonbValue *newval);430extern Datum jsonb_get_element(Jsonb *jb, Datum *path, int npath,431							   bool *isnull, bool as_text);432extern bool to_jsonb_is_immutable(Oid typoid);433extern Datum jsonb_build_object_worker(int nargs, Datum *args, bool *nulls,434									   Oid *types, bool absent_on_null,435									   bool unique_keys);436extern Datum jsonb_build_array_worker(int nargs, Datum *args, bool *nulls,437									  Oid *types, bool absent_on_null);438 439#endif							/* __JSONB_H__ */440 
codekingpro/portable-devtools · Team Ai