Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes16kdownloads
array.h483 linesDownload Raw Back to utils
1/*-------------------------------------------------------------------------2 *3 * array.h4 *	  Declarations for Postgres arrays.5 *6 * A standard varlena array has the following internal structure:7 *	  <vl_len_>		- standard varlena header word8 *	  <ndim>		- number of dimensions of the array9 *	  <dataoffset>	- offset to stored data, or 0 if no nulls bitmap10 *	  <elemtype>	- element type OID11 *	  <dimensions>	- length of each array axis (C array of int)12 *	  <lower bnds>	- lower boundary of each dimension (C array of int)13 *	  <null bitmap> - bitmap showing locations of nulls (OPTIONAL)14 *	  <actual data> - whatever is the stored data15 *16 * The <dimensions> and <lower bnds> arrays each have ndim elements.17 *18 * The <null bitmap> may be omitted if the array contains no NULL elements.19 * If it is absent, the <dataoffset> field is zero and the offset to the20 * stored data must be computed on-the-fly.  If the bitmap is present,21 * <dataoffset> is nonzero and is equal to the offset from the array start22 * to the first data element (including any alignment padding).  The bitmap23 * follows the same conventions as tuple null bitmaps, ie, a 1 indicates24 * a non-null entry and the LSB of each bitmap byte is used first.25 *26 * The actual data starts on a MAXALIGN boundary.  Individual items in the27 * array are aligned as specified by the array element type.  They are28 * stored in row-major order (last subscript varies most rapidly).29 *30 * NOTE: it is important that array elements of toastable datatypes NOT be31 * toasted, since the tupletoaster won't know they are there.  (We could32 * support compressed toasted items; only out-of-line items are dangerous.33 * However, it seems preferable to store such items uncompressed and allow34 * the toaster to compress the whole array as one input.)35 *36 *37 * The OIDVECTOR and INT2VECTOR datatypes are storage-compatible with38 * generic arrays, but they support only one-dimensional arrays with no39 * nulls (and no null bitmap).  They don't support being toasted, either.40 *41 * There are also some "fixed-length array" datatypes, such as NAME and42 * POINT.  These are simply a sequence of a fixed number of items each43 * of a fixed-length datatype, with no overhead; the item size must be44 * a multiple of its alignment requirement, because we do no padding.45 * We support subscripting on these types, but array_in() and array_out()46 * only work with varlena arrays.47 *48 * In addition, arrays are a major user of the "expanded object" TOAST49 * infrastructure.  This allows a varlena array to be converted to a50 * separate representation that may include "deconstructed" Datum/isnull51 * arrays holding the elements.52 *53 *54 * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group55 * Portions Copyright (c) 1994, Regents of the University of California56 *57 * src/include/utils/array.h58 *59 *-------------------------------------------------------------------------60 */61#ifndef ARRAY_H62#define ARRAY_H63 64#include "fmgr.h"65#include "utils/expandeddatum.h"66 67/* avoid including execnodes.h here */68struct ExprState;69struct ExprContext;70 71 72/*73 * Maximum number of array subscripts (arbitrary limit)74 */75#define MAXDIM 676 77/*78 * Maximum number of elements in an array.  We limit this to at most about a79 * quarter billion elements, so that it's not necessary to check for overflow80 * in quite so many places --- for instance when palloc'ing Datum arrays.81 */82#define MaxArraySize ((Size) (MaxAllocSize / sizeof(Datum)))83 84/*85 * Arrays are varlena objects, so must meet the varlena convention that86 * the first int32 of the object contains the total object size in bytes.87 * Be sure to use VARSIZE() and SET_VARSIZE() to access it, though!88 *89 * CAUTION: if you change the header for ordinary arrays you will also90 * need to change the headers for oidvector and int2vector!91 */92typedef struct ArrayType93{94	int32		vl_len_;		/* varlena header (do not touch directly!) */95	int			ndim;			/* # of dimensions */96	int32		dataoffset;		/* offset to data, or 0 if no bitmap */97	Oid			elemtype;		/* element type OID */98} ArrayType;99 100/*101 * An expanded array is contained within a private memory context (as102 * all expanded objects must be) and has a control structure as below.103 *104 * The expanded array might contain a regular "flat" array if that was the105 * original input and we've not modified it significantly.  Otherwise, the106 * contents are represented by Datum/isnull arrays plus dimensionality and107 * type information.  We could also have both forms, if we've deconstructed108 * the original array for access purposes but not yet changed it.  For pass-109 * by-reference element types, the Datums would point into the flat array in110 * this situation.  Once we start modifying array elements, new pass-by-ref111 * elements are separately palloc'd within the memory context.112 */113#define EA_MAGIC 689375833		/* ID for debugging crosschecks */114 115typedef struct ExpandedArrayHeader116{117	/* Standard header for expanded objects */118	ExpandedObjectHeader hdr;119 120	/* Magic value identifying an expanded array (for debugging only) */121	int			ea_magic;122 123	/* Dimensionality info (always valid) */124	int			ndims;			/* # of dimensions */125	int		   *dims;			/* array dimensions */126	int		   *lbound;			/* index lower bounds for each dimension */127 128	/* Element type info (always valid) */129	Oid			element_type;	/* element type OID */130	int16		typlen;			/* needed info about element datatype */131	bool		typbyval;132	char		typalign;133 134	/*135	 * If we have a Datum-array representation of the array, it's kept here;136	 * else dvalues/dnulls are NULL.  The dvalues and dnulls arrays are always137	 * palloc'd within the object private context, but may change size from138	 * time to time.  For pass-by-ref element types, dvalues entries might139	 * point either into the fstartptr..fendptr area, or to separately140	 * palloc'd chunks.  Elements should always be fully detoasted, as they141	 * are in the standard flat representation.142	 *143	 * Even when dvalues is valid, dnulls can be NULL if there are no null144	 * elements.145	 */146	Datum	   *dvalues;		/* array of Datums */147	bool	   *dnulls;			/* array of is-null flags for Datums */148	int			dvalueslen;		/* allocated length of above arrays */149	int			nelems;			/* number of valid entries in above arrays */150 151	/*152	 * flat_size is the current space requirement for the flat equivalent of153	 * the expanded array, if known; otherwise it's 0.  We store this to make154	 * consecutive calls of get_flat_size cheap.155	 */156	Size		flat_size;157 158	/*159	 * fvalue points to the flat representation if it is valid, else it is160	 * NULL.  If we have or ever had a flat representation then161	 * fstartptr/fendptr point to the start and end+1 of its data area; this162	 * is so that we can tell which Datum pointers point into the flat163	 * representation rather than being pointers to separately palloc'd data.164	 */165	ArrayType  *fvalue;			/* must be a fully detoasted array */166	char	   *fstartptr;		/* start of its data area */167	char	   *fendptr;		/* end+1 of its data area */168} ExpandedArrayHeader;169 170/*171 * Functions that can handle either a "flat" varlena array or an expanded172 * array use this union to work with their input.  Don't refer to "flt";173 * instead, cast to ArrayType.  This struct nominally requires 8-byte174 * alignment on 64-bit, but it's often used for an ArrayType having 4-byte175 * alignment.  UBSan complains about referencing "flt" in such cases.176 */177typedef union AnyArrayType178{179	ArrayType	flt;180	ExpandedArrayHeader xpn;181} AnyArrayType;182 183/*184 * working state for accumArrayResult() and friends185 * note that the input must be scalars (legal array elements)186 */187typedef struct ArrayBuildState188{189	MemoryContext mcontext;		/* where all the temp stuff is kept */190	Datum	   *dvalues;		/* array of accumulated Datums */191	bool	   *dnulls;			/* array of is-null flags for Datums */192	int			alen;			/* allocated length of above arrays */193	int			nelems;			/* number of valid entries in above arrays */194	Oid			element_type;	/* data type of the Datums */195	int16		typlen;			/* needed info about datatype */196	bool		typbyval;197	char		typalign;198	bool		private_cxt;	/* use private memory context */199} ArrayBuildState;200 201/*202 * working state for accumArrayResultArr() and friends203 * note that the input must be arrays, and the same array type is returned204 */205typedef struct ArrayBuildStateArr206{207	MemoryContext mcontext;		/* where all the temp stuff is kept */208	char	   *data;			/* accumulated data */209	bits8	   *nullbitmap;		/* bitmap of is-null flags, or NULL if none */210	int			abytes;			/* allocated length of "data" */211	int			nbytes;			/* number of bytes used so far */212	int			aitems;			/* allocated length of bitmap (in elements) */213	int			nitems;			/* total number of elements in result */214	int			ndims;			/* current dimensions of result */215	int			dims[MAXDIM];216	int			lbs[MAXDIM];217	Oid			array_type;		/* data type of the arrays */218	Oid			element_type;	/* data type of the array elements */219	bool		private_cxt;	/* use private memory context */220} ArrayBuildStateArr;221 222/*223 * working state for accumArrayResultAny() and friends224 * these functions handle both cases225 */226typedef struct ArrayBuildStateAny227{228	/* Exactly one of these is not NULL: */229	ArrayBuildState *scalarstate;230	ArrayBuildStateArr *arraystate;231} ArrayBuildStateAny;232 233/*234 * structure to cache type metadata needed for array manipulation235 */236typedef struct ArrayMetaState237{238	Oid			element_type;239	int16		typlen;240	bool		typbyval;241	char		typalign;242	char		typdelim;243	Oid			typioparam;244	Oid			typiofunc;245	FmgrInfo	proc;246} ArrayMetaState;247 248/*249 * private state needed by array_map (here because caller must provide it)250 */251typedef struct ArrayMapState252{253	ArrayMetaState inp_extra;254	ArrayMetaState ret_extra;255} ArrayMapState;256 257/* ArrayIteratorData is private in arrayfuncs.c */258typedef struct ArrayIteratorData *ArrayIterator;259 260/* fmgr macros for regular varlena array objects */261#define DatumGetArrayTypeP(X)		  ((ArrayType *) PG_DETOAST_DATUM(X))262#define DatumGetArrayTypePCopy(X)	  ((ArrayType *) PG_DETOAST_DATUM_COPY(X))263#define PG_GETARG_ARRAYTYPE_P(n)	  DatumGetArrayTypeP(PG_GETARG_DATUM(n))264#define PG_GETARG_ARRAYTYPE_P_COPY(n) DatumGetArrayTypePCopy(PG_GETARG_DATUM(n))265#define PG_RETURN_ARRAYTYPE_P(x)	  PG_RETURN_POINTER(x)266 267/* fmgr macros for expanded array objects */268#define PG_GETARG_EXPANDED_ARRAY(n)  DatumGetExpandedArray(PG_GETARG_DATUM(n))269#define PG_GETARG_EXPANDED_ARRAYX(n, metacache) \270	DatumGetExpandedArrayX(PG_GETARG_DATUM(n), metacache)271#define PG_RETURN_EXPANDED_ARRAY(x)  PG_RETURN_DATUM(EOHPGetRWDatum(&(x)->hdr))272 273/* fmgr macros for AnyArrayType (ie, get either varlena or expanded form) */274#define PG_GETARG_ANY_ARRAY_P(n)	DatumGetAnyArrayP(PG_GETARG_DATUM(n))275 276/*277 * Access macros for varlena array header fields.278 *279 * ARR_DIMS returns a pointer to an array of array dimensions (number of280 * elements along the various array axes).281 *282 * ARR_LBOUND returns a pointer to an array of array lower bounds.283 *284 * That is: if the third axis of an array has elements 5 through 8, then285 * ARR_DIMS(a)[2] == 4 and ARR_LBOUND(a)[2] == 5.286 *287 * Unlike C, the default lower bound is 1.288 */289#define ARR_SIZE(a)				VARSIZE(a)290#define ARR_NDIM(a)				((a)->ndim)291#define ARR_HASNULL(a)			((a)->dataoffset != 0)292#define ARR_ELEMTYPE(a)			((a)->elemtype)293 294#define ARR_DIMS(a) \295		((int *) (((char *) (a)) + sizeof(ArrayType)))296#define ARR_LBOUND(a) \297		((int *) (((char *) (a)) + sizeof(ArrayType) + \298				  sizeof(int) * ARR_NDIM(a)))299 300#define ARR_NULLBITMAP(a) \301		(ARR_HASNULL(a) ? \302		 (bits8 *) (((char *) (a)) + sizeof(ArrayType) + \303					2 * sizeof(int) * ARR_NDIM(a)) \304		 : (bits8 *) NULL)305 306/*307 * The total array header size (in bytes) for an array with the specified308 * number of dimensions and total number of items.309 */310#define ARR_OVERHEAD_NONULLS(ndims) \311		MAXALIGN(sizeof(ArrayType) + 2 * sizeof(int) * (ndims))312#define ARR_OVERHEAD_WITHNULLS(ndims, nitems) \313		MAXALIGN(sizeof(ArrayType) + 2 * sizeof(int) * (ndims) + \314				 ((nitems) + 7) / 8)315 316#define ARR_DATA_OFFSET(a) \317		(ARR_HASNULL(a) ? (a)->dataoffset : ARR_OVERHEAD_NONULLS(ARR_NDIM(a)))318 319/*320 * Returns a pointer to the actual array data.321 */322#define ARR_DATA_PTR(a) \323		(((char *) (a)) + ARR_DATA_OFFSET(a))324 325/*326 * Macros for working with AnyArrayType inputs.  Beware multiple references!327 */328#define AARR_NDIM(a) \329	(VARATT_IS_EXPANDED_HEADER(a) ? \330	 (a)->xpn.ndims : ARR_NDIM((ArrayType *) (a)))331#define AARR_HASNULL(a) \332	(VARATT_IS_EXPANDED_HEADER(a) ? \333	 ((a)->xpn.dvalues != NULL ? (a)->xpn.dnulls != NULL : ARR_HASNULL((a)->xpn.fvalue)) : \334	 ARR_HASNULL((ArrayType *) (a)))335#define AARR_ELEMTYPE(a) \336	(VARATT_IS_EXPANDED_HEADER(a) ? \337	 (a)->xpn.element_type : ARR_ELEMTYPE((ArrayType *) (a)))338#define AARR_DIMS(a) \339	(VARATT_IS_EXPANDED_HEADER(a) ? \340	 (a)->xpn.dims : ARR_DIMS((ArrayType *) (a)))341#define AARR_LBOUND(a) \342	(VARATT_IS_EXPANDED_HEADER(a) ? \343	 (a)->xpn.lbound : ARR_LBOUND((ArrayType *) (a)))344 345 346/*347 * GUC parameter348 */349extern PGDLLIMPORT bool Array_nulls;350 351/*352 * prototypes for functions defined in arrayfuncs.c353 */354extern void CopyArrayEls(ArrayType *array,355						 Datum *values,356						 bool *nulls,357						 int nitems,358						 int typlen,359						 bool typbyval,360						 char typalign,361						 bool freedata);362 363extern Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx,364							   int arraytyplen, int elmlen, bool elmbyval, char elmalign,365							   bool *isNull);366extern Datum array_set_element(Datum arraydatum, int nSubscripts, int *indx,367							   Datum dataValue, bool isNull,368							   int arraytyplen, int elmlen, bool elmbyval, char elmalign);369extern Datum array_get_slice(Datum arraydatum, int nSubscripts,370							 int *upperIndx, int *lowerIndx,371							 bool *upperProvided, bool *lowerProvided,372							 int arraytyplen, int elmlen, bool elmbyval, char elmalign);373extern Datum array_set_slice(Datum arraydatum, int nSubscripts,374							 int *upperIndx, int *lowerIndx,375							 bool *upperProvided, bool *lowerProvided,376							 Datum srcArrayDatum, bool isNull,377							 int arraytyplen, int elmlen, bool elmbyval, char elmalign);378 379extern Datum array_ref(ArrayType *array, int nSubscripts, int *indx,380					   int arraytyplen, int elmlen, bool elmbyval, char elmalign,381					   bool *isNull);382extern ArrayType *array_set(ArrayType *array, int nSubscripts, int *indx,383							Datum dataValue, bool isNull,384							int arraytyplen, int elmlen, bool elmbyval, char elmalign);385 386extern Datum array_map(Datum arrayd,387					   struct ExprState *exprstate, struct ExprContext *econtext,388					   Oid retType, ArrayMapState *amstate);389 390extern void array_bitmap_copy(bits8 *destbitmap, int destoffset,391							  const bits8 *srcbitmap, int srcoffset,392							  int nitems);393 394extern ArrayType *construct_array(Datum *elems, int nelems,395								  Oid elmtype,396								  int elmlen, bool elmbyval, char elmalign);397extern ArrayType *construct_array_builtin(Datum *elems, int nelems, Oid elmtype);398extern ArrayType *construct_md_array(Datum *elems,399									 bool *nulls,400									 int ndims,401									 int *dims,402									 int *lbs,403									 Oid elmtype, int elmlen, bool elmbyval, char elmalign);404extern ArrayType *construct_empty_array(Oid elmtype);405extern ExpandedArrayHeader *construct_empty_expanded_array(Oid element_type,406														   MemoryContext parentcontext,407														   ArrayMetaState *metacache);408extern void deconstruct_array(ArrayType *array,409							  Oid elmtype,410							  int elmlen, bool elmbyval, char elmalign,411							  Datum **elemsp, bool **nullsp, int *nelemsp);412extern void deconstruct_array_builtin(ArrayType *array,413									  Oid elmtype,414									  Datum **elemsp, bool **nullsp, int *nelemsp);415extern bool array_contains_nulls(ArrayType *array);416 417extern ArrayBuildState *initArrayResult(Oid element_type,418										MemoryContext rcontext, bool subcontext);419extern ArrayBuildState *initArrayResultWithSize(Oid element_type,420												MemoryContext rcontext,421												bool subcontext, int initsize);422extern ArrayBuildState *accumArrayResult(ArrayBuildState *astate,423										 Datum dvalue, bool disnull,424										 Oid element_type,425										 MemoryContext rcontext);426extern Datum makeArrayResult(ArrayBuildState *astate,427							 MemoryContext rcontext);428extern Datum makeMdArrayResult(ArrayBuildState *astate, int ndims,429							   int *dims, int *lbs, MemoryContext rcontext, bool release);430 431extern ArrayBuildStateArr *initArrayResultArr(Oid array_type, Oid element_type,432											  MemoryContext rcontext, bool subcontext);433extern ArrayBuildStateArr *accumArrayResultArr(ArrayBuildStateArr *astate,434											   Datum dvalue, bool disnull,435											   Oid array_type,436											   MemoryContext rcontext);437extern Datum makeArrayResultArr(ArrayBuildStateArr *astate,438								MemoryContext rcontext, bool release);439 440extern ArrayBuildStateAny *initArrayResultAny(Oid input_type,441											  MemoryContext rcontext, bool subcontext);442extern ArrayBuildStateAny *accumArrayResultAny(ArrayBuildStateAny *astate,443											   Datum dvalue, bool disnull,444											   Oid input_type,445											   MemoryContext rcontext);446extern Datum makeArrayResultAny(ArrayBuildStateAny *astate,447								MemoryContext rcontext, bool release);448 449extern ArrayIterator array_create_iterator(ArrayType *arr, int slice_ndim, ArrayMetaState *mstate);450extern bool array_iterate(ArrayIterator iterator, Datum *value, bool *isnull);451extern void array_free_iterator(ArrayIterator iterator);452 453/*454 * prototypes for functions defined in arrayutils.c455 */456 457extern int	ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx);458extern int	ArrayGetOffset0(int n, const int *tup, const int *scale);459extern int	ArrayGetNItems(int ndim, const int *dims);460extern int	ArrayGetNItemsSafe(int ndim, const int *dims,461							   struct Node *escontext);462extern void ArrayCheckBounds(int ndim, const int *dims, const int *lb);463extern bool ArrayCheckBoundsSafe(int ndim, const int *dims, const int *lb,464								 struct Node *escontext);465extern void mda_get_range(int n, int *span, const int *st, const int *endp);466extern void mda_get_prod(int n, const int *range, int *prod);467extern void mda_get_offset_values(int n, int *dist, const int *prod, const int *span);468extern int	mda_next_tuple(int n, int *curr, const int *span);469extern int32 *ArrayGetIntegerTypmods(ArrayType *arr, int *n);470 471/*472 * prototypes for functions defined in array_expanded.c473 */474extern Datum expand_array(Datum arraydatum, MemoryContext parentcontext,475						  ArrayMetaState *metacache);476extern ExpandedArrayHeader *DatumGetExpandedArray(Datum d);477extern ExpandedArrayHeader *DatumGetExpandedArrayX(Datum d,478												   ArrayMetaState *metacache);479extern AnyArrayType *DatumGetAnyArrayP(Datum d);480extern void deconstruct_expanded_array(ExpandedArrayHeader *eah);481 482#endif							/* ARRAY_H */483 
codekingpro/portable-devtools · Team Ai