codekingpro/portable-devtools
116k
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 