PostgreSQL Source Code git master
array.h File Reference
#include "fmgr.h"
#include "utils/expandeddatum.h"
Include dependency graph for array.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ArrayType
 
struct  ExpandedArrayHeader
 
union  AnyArrayType
 
struct  ArrayBuildState
 
struct  ArrayBuildStateArr
 
struct  ArrayBuildStateAny
 
struct  ArrayMetaState
 
struct  ArrayMapState
 

Macros

#define MAXDIM   6
 
#define MaxArraySize   ((Size) (MaxAllocSize / sizeof(Datum)))
 
#define EA_MAGIC   689375833 /* ID for debugging crosschecks */
 
#define DatumGetArrayTypeP(X)   ((ArrayType *) PG_DETOAST_DATUM(X))
 
#define DatumGetArrayTypePCopy(X)   ((ArrayType *) PG_DETOAST_DATUM_COPY(X))
 
#define PG_GETARG_ARRAYTYPE_P(n)   DatumGetArrayTypeP(PG_GETARG_DATUM(n))
 
#define PG_GETARG_ARRAYTYPE_P_COPY(n)   DatumGetArrayTypePCopy(PG_GETARG_DATUM(n))
 
#define PG_RETURN_ARRAYTYPE_P(x)   PG_RETURN_POINTER(x)
 
#define PG_GETARG_EXPANDED_ARRAY(n)   DatumGetExpandedArray(PG_GETARG_DATUM(n))
 
#define PG_GETARG_EXPANDED_ARRAYX(n, metacache)    DatumGetExpandedArrayX(PG_GETARG_DATUM(n), metacache)
 
#define PG_RETURN_EXPANDED_ARRAY(x)   PG_RETURN_DATUM(EOHPGetRWDatum(&(x)->hdr))
 
#define PG_GETARG_ANY_ARRAY_P(n)   DatumGetAnyArrayP(PG_GETARG_DATUM(n))
 
#define ARR_SIZE(a)   VARSIZE(a)
 
#define ARR_NDIM(a)   ((a)->ndim)
 
#define ARR_HASNULL(a)   ((a)->dataoffset != 0)
 
#define ARR_ELEMTYPE(a)   ((a)->elemtype)
 
#define ARR_DIMS(a)    ((int *) (((char *) (a)) + sizeof(ArrayType)))
 
#define ARR_LBOUND(a)
 
#define ARR_NULLBITMAP(a)
 
#define ARR_OVERHEAD_NONULLS(ndims)    MAXALIGN(sizeof(ArrayType) + 2 * sizeof(int) * (ndims))
 
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
 
#define ARR_DATA_OFFSET(a)    (ARR_HASNULL(a) ? (a)->dataoffset : ARR_OVERHEAD_NONULLS(ARR_NDIM(a)))
 
#define ARR_DATA_PTR(a)    (((char *) (a)) + ARR_DATA_OFFSET(a))
 
#define AARR_NDIM(a)
 
#define AARR_HASNULL(a)
 
#define AARR_ELEMTYPE(a)
 
#define AARR_DIMS(a)
 
#define AARR_LBOUND(a)
 

Typedefs

typedef struct ArrayType ArrayType
 
typedef struct ExpandedArrayHeader ExpandedArrayHeader
 
typedef union AnyArrayType AnyArrayType
 
typedef struct ArrayBuildState ArrayBuildState
 
typedef struct ArrayBuildStateArr ArrayBuildStateArr
 
typedef struct ArrayBuildStateAny ArrayBuildStateAny
 
typedef struct ArrayMetaState ArrayMetaState
 
typedef struct ArrayMapState ArrayMapState
 
typedef struct ArrayIteratorDataArrayIterator
 

Functions

void CopyArrayEls (ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
 
Datum array_get_element (Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
Datum array_set_element (Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_get_slice (Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_set_slice (Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, Datum srcArrayDatum, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_ref (ArrayType *array, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
ArrayTypearray_set (ArrayType *array, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_map (Datum arrayd, struct ExprState *exprstate, struct ExprContext *econtext, Oid retType, ArrayMapState *amstate)
 
void array_bitmap_copy (bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
 
ArrayTypeconstruct_array (Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
 
ArrayTypeconstruct_array_builtin (Datum *elems, int nelems, Oid elmtype)
 
ArrayTypeconstruct_md_array (Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
 
ArrayTypeconstruct_empty_array (Oid elmtype)
 
ExpandedArrayHeaderconstruct_empty_expanded_array (Oid element_type, MemoryContext parentcontext, ArrayMetaState *metacache)
 
void deconstruct_array (ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
 
void deconstruct_array_builtin (ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
 
bool array_contains_nulls (ArrayType *array)
 
ArrayBuildStateinitArrayResult (Oid element_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateinitArrayResultWithSize (Oid element_type, MemoryContext rcontext, bool subcontext, int initsize)
 
ArrayBuildStateaccumArrayResult (ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
 
Datum makeArrayResult (ArrayBuildState *astate, MemoryContext rcontext)
 
Datum makeMdArrayResult (ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
 
ArrayBuildStateArrinitArrayResultArr (Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateArraccumArrayResultArr (ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
 
Datum makeArrayResultArr (ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
 
ArrayBuildStateAnyinitArrayResultAny (Oid input_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateAnyaccumArrayResultAny (ArrayBuildStateAny *astate, Datum dvalue, bool disnull, Oid input_type, MemoryContext rcontext)
 
Datum makeArrayResultAny (ArrayBuildStateAny *astate, MemoryContext rcontext, bool release)
 
ArrayIterator array_create_iterator (ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
 
bool array_iterate (ArrayIterator iterator, Datum *value, bool *isnull)
 
void array_free_iterator (ArrayIterator iterator)
 
int ArrayGetOffset (int n, const int *dim, const int *lb, const int *indx)
 
int ArrayGetNItems (int ndim, const int *dims)
 
int ArrayGetNItemsSafe (int ndim, const int *dims, struct Node *escontext)
 
void ArrayCheckBounds (int ndim, const int *dims, const int *lb)
 
bool ArrayCheckBoundsSafe (int ndim, const int *dims, const int *lb, struct Node *escontext)
 
void mda_get_range (int n, int *span, const int *st, const int *endp)
 
void mda_get_prod (int n, const int *range, int *prod)
 
void mda_get_offset_values (int n, int *dist, const int *prod, const int *span)
 
int mda_next_tuple (int n, int *curr, const int *span)
 
int32ArrayGetIntegerTypmods (ArrayType *arr, int *n)
 
Datum expand_array (Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
 
ExpandedArrayHeaderDatumGetExpandedArray (Datum d)
 
ExpandedArrayHeaderDatumGetExpandedArrayX (Datum d, ArrayMetaState *metacache)
 
AnyArrayTypeDatumGetAnyArrayP (Datum d)
 
void deconstruct_expanded_array (ExpandedArrayHeader *eah)
 

Variables

PGDLLIMPORT bool Array_nulls
 

Macro Definition Documentation

◆ AARR_DIMS

#define AARR_DIMS (   a)
Value:
(a)->xpn.dims : ARR_DIMS((ArrayType *) (a)))
#define ARR_DIMS(a)
Definition: array.h:294
#define VARATT_IS_EXPANDED_HEADER(PTR)
int a
Definition: isn.c:68

Definition at line 338 of file array.h.

◆ AARR_ELEMTYPE

#define AARR_ELEMTYPE (   a)
Value:
(a)->xpn.element_type : ARR_ELEMTYPE((ArrayType *) (a)))
#define ARR_ELEMTYPE(a)
Definition: array.h:292

Definition at line 335 of file array.h.

◆ AARR_HASNULL

#define AARR_HASNULL (   a)
Value:
((a)->xpn.dvalues != NULL ? (a)->xpn.dnulls != NULL : ARR_HASNULL((a)->xpn.fvalue)) : \
#define ARR_HASNULL(a)
Definition: array.h:291

Definition at line 331 of file array.h.

◆ AARR_LBOUND

#define AARR_LBOUND (   a)
Value:
(a)->xpn.lbound : ARR_LBOUND((ArrayType *) (a)))
#define ARR_LBOUND(a)
Definition: array.h:296

Definition at line 341 of file array.h.

◆ AARR_NDIM

#define AARR_NDIM (   a)
Value:
(a)->xpn.ndims : ARR_NDIM((ArrayType *) (a)))
#define ARR_NDIM(a)
Definition: array.h:290

Definition at line 328 of file array.h.

◆ ARR_DATA_OFFSET

#define ARR_DATA_OFFSET (   a)     (ARR_HASNULL(a) ? (a)->dataoffset : ARR_OVERHEAD_NONULLS(ARR_NDIM(a)))

Definition at line 316 of file array.h.

◆ ARR_DATA_PTR

#define ARR_DATA_PTR (   a)     (((char *) (a)) + ARR_DATA_OFFSET(a))

Definition at line 322 of file array.h.

◆ ARR_DIMS

#define ARR_DIMS (   a)     ((int *) (((char *) (a)) + sizeof(ArrayType)))

Definition at line 294 of file array.h.

◆ ARR_ELEMTYPE

#define ARR_ELEMTYPE (   a)    ((a)->elemtype)

Definition at line 292 of file array.h.

◆ ARR_HASNULL

#define ARR_HASNULL (   a)    ((a)->dataoffset != 0)

Definition at line 291 of file array.h.

◆ ARR_LBOUND

#define ARR_LBOUND (   a)
Value:
((int *) (((char *) (a)) + sizeof(ArrayType) + \
sizeof(int) * ARR_NDIM(a)))
struct ArrayType ArrayType

Definition at line 296 of file array.h.

◆ ARR_NDIM

#define ARR_NDIM (   a)    ((a)->ndim)

Definition at line 290 of file array.h.

◆ ARR_NULLBITMAP

#define ARR_NULLBITMAP (   a)
Value:
(ARR_HASNULL(a) ? \
(bits8 *) (((char *) (a)) + sizeof(ArrayType) + \
2 * sizeof(int) * ARR_NDIM(a)) \
: (bits8 *) NULL)
uint8 bits8
Definition: c.h:495

Definition at line 300 of file array.h.

◆ ARR_OVERHEAD_NONULLS

#define ARR_OVERHEAD_NONULLS (   ndims)     MAXALIGN(sizeof(ArrayType) + 2 * sizeof(int) * (ndims))

Definition at line 310 of file array.h.

◆ ARR_OVERHEAD_WITHNULLS

#define ARR_OVERHEAD_WITHNULLS (   ndims,
  nitems 
)
Value:
MAXALIGN(sizeof(ArrayType) + 2 * sizeof(int) * (ndims) + \
((nitems) + 7) / 8)
#define MAXALIGN(LEN)
Definition: c.h:768
#define nitems(x)
Definition: indent.h:31

Definition at line 312 of file array.h.

◆ ARR_SIZE

#define ARR_SIZE (   a)    VARSIZE(a)

Definition at line 289 of file array.h.

◆ DatumGetArrayTypeP

#define DatumGetArrayTypeP (   X)    ((ArrayType *) PG_DETOAST_DATUM(X))

Definition at line 261 of file array.h.

◆ DatumGetArrayTypePCopy

#define DatumGetArrayTypePCopy (   X)    ((ArrayType *) PG_DETOAST_DATUM_COPY(X))

Definition at line 262 of file array.h.

◆ EA_MAGIC

#define EA_MAGIC   689375833 /* ID for debugging crosschecks */

Definition at line 113 of file array.h.

◆ MaxArraySize

#define MaxArraySize   ((Size) (MaxAllocSize / sizeof(Datum)))

Definition at line 82 of file array.h.

◆ MAXDIM

#define MAXDIM   6

Definition at line 75 of file array.h.

◆ PG_GETARG_ANY_ARRAY_P

#define PG_GETARG_ANY_ARRAY_P (   n)    DatumGetAnyArrayP(PG_GETARG_DATUM(n))

Definition at line 274 of file array.h.

◆ PG_GETARG_ARRAYTYPE_P

#define PG_GETARG_ARRAYTYPE_P (   n)    DatumGetArrayTypeP(PG_GETARG_DATUM(n))

Definition at line 263 of file array.h.

◆ PG_GETARG_ARRAYTYPE_P_COPY

#define PG_GETARG_ARRAYTYPE_P_COPY (   n)    DatumGetArrayTypePCopy(PG_GETARG_DATUM(n))

Definition at line 264 of file array.h.

◆ PG_GETARG_EXPANDED_ARRAY

#define PG_GETARG_EXPANDED_ARRAY (   n)    DatumGetExpandedArray(PG_GETARG_DATUM(n))

Definition at line 268 of file array.h.

◆ PG_GETARG_EXPANDED_ARRAYX

#define PG_GETARG_EXPANDED_ARRAYX (   n,
  metacache 
)     DatumGetExpandedArrayX(PG_GETARG_DATUM(n), metacache)

Definition at line 269 of file array.h.

◆ PG_RETURN_ARRAYTYPE_P

#define PG_RETURN_ARRAYTYPE_P (   x)    PG_RETURN_POINTER(x)

Definition at line 265 of file array.h.

◆ PG_RETURN_EXPANDED_ARRAY

#define PG_RETURN_EXPANDED_ARRAY (   x)    PG_RETURN_DATUM(EOHPGetRWDatum(&(x)->hdr))

Definition at line 271 of file array.h.

Typedef Documentation

◆ AnyArrayType

typedef union AnyArrayType AnyArrayType

◆ ArrayBuildState

◆ ArrayBuildStateAny

◆ ArrayBuildStateArr

◆ ArrayIterator

Definition at line 258 of file array.h.

◆ ArrayMapState

typedef struct ArrayMapState ArrayMapState

◆ ArrayMetaState

◆ ArrayType

typedef struct ArrayType ArrayType

◆ ExpandedArrayHeader

Function Documentation

◆ accumArrayResult()

ArrayBuildState * accumArrayResult ( ArrayBuildState astate,
Datum  dvalue,
bool  disnull,
Oid  element_type,
MemoryContext  rcontext 
)

Definition at line 5350 of file arrayfuncs.c.

5354{
5355 MemoryContext oldcontext;
5356
5357 if (astate == NULL)
5358 {
5359 /* First time through --- initialize */
5360 astate = initArrayResult(element_type, rcontext, true);
5361 }
5362 else
5363 {
5364 Assert(astate->element_type == element_type);
5365 }
5366
5367 oldcontext = MemoryContextSwitchTo(astate->mcontext);
5368
5369 /* enlarge dvalues[]/dnulls[] if needed */
5370 if (astate->nelems >= astate->alen)
5371 {
5372 astate->alen *= 2;
5373 /* give an array-related error if we go past MaxAllocSize */
5374 if (!AllocSizeIsValid(astate->alen * sizeof(Datum)))
5375 ereport(ERROR,
5376 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5377 errmsg("array size exceeds the maximum allowed (%d)",
5378 (int) MaxAllocSize)));
5379 astate->dvalues = (Datum *)
5380 repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5381 astate->dnulls = (bool *)
5382 repalloc(astate->dnulls, astate->alen * sizeof(bool));
5383 }
5384
5385 /*
5386 * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5387 * it's varlena. (You might think that detoasting is not needed here
5388 * because construct_md_array can detoast the array elements later.
5389 * However, we must not let construct_md_array modify the ArrayBuildState
5390 * because that would mean array_agg_finalfn damages its input, which is
5391 * verboten. Also, this way frequently saves one copying step.)
5392 */
5393 if (!disnull && !astate->typbyval)
5394 {
5395 if (astate->typlen == -1)
5396 dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5397 else
5398 dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5399 }
5400
5401 astate->dvalues[astate->nelems] = dvalue;
5402 astate->dnulls[astate->nelems] = disnull;
5403 astate->nelems++;
5404
5405 MemoryContextSwitchTo(oldcontext);
5406
5407 return astate;
5408}
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5293
#define Assert(condition)
Definition: c.h:815
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define MaxAllocSize
Definition: fe_memutils.h:22
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
#define AllocSizeIsValid(size)
Definition: memutils.h:42
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
bool * dnulls
Definition: array.h:191
bool typbyval
Definition: array.h:196
MemoryContext mcontext
Definition: array.h:189
int16 typlen
Definition: array.h:195
Oid element_type
Definition: array.h:194
Datum * dvalues
Definition: array.h:190

References ArrayBuildState::alen, AllocSizeIsValid, Assert, datumCopy(), ArrayBuildState::dnulls, ArrayBuildState::dvalues, ArrayBuildState::element_type, ereport, errcode(), errmsg(), ERROR, initArrayResult(), MaxAllocSize, ArrayBuildState::mcontext, MemoryContextSwitchTo(), ArrayBuildState::nelems, PG_DETOAST_DATUM_COPY, PointerGetDatum(), repalloc(), ArrayBuildState::typbyval, and ArrayBuildState::typlen.

Referenced by accumArrayResultAny(), array_agg_transfn(), array_positions(), array_to_datum_internal(), brin_minmax_multi_summary_out(), daitch_mokotoff_coding(), dblink_get_connections(), find_or_create_child_node(), multirange_agg_transfn(), optionListToArray(), parse_ident(), pg_get_statisticsobjdef_expressions(), pg_stats_ext_mcvlist_items(), PLySequence_ToArray_recurse(), populate_array_element(), range_agg_transfn(), regexp_split_to_array(), serialize_expr_stats(), split_text_accum_result(), transformRelOptions(), and tuple_data_split_internal().

◆ accumArrayResultAny()

ArrayBuildStateAny * accumArrayResultAny ( ArrayBuildStateAny astate,
Datum  dvalue,
bool  disnull,
Oid  input_type,
MemoryContext  rcontext 
)

Definition at line 5827 of file arrayfuncs.c.

5831{
5832 if (astate == NULL)
5833 astate = initArrayResultAny(input_type, rcontext, true);
5834
5835 if (astate->scalarstate)
5836 (void) accumArrayResult(astate->scalarstate,
5837 dvalue, disnull,
5838 input_type, rcontext);
5839 else
5840 (void) accumArrayResultArr(astate->arraystate,
5841 dvalue, disnull,
5842 input_type, rcontext);
5843
5844 return astate;
5845}
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5350
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5782
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5550
ArrayBuildStateArr * arraystate
Definition: array.h:230
ArrayBuildState * scalarstate
Definition: array.h:229

References accumArrayResult(), accumArrayResultArr(), ArrayBuildStateAny::arraystate, initArrayResultAny(), and ArrayBuildStateAny::scalarstate.

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

◆ accumArrayResultArr()

ArrayBuildStateArr * accumArrayResultArr ( ArrayBuildStateArr astate,
Datum  dvalue,
bool  disnull,
Oid  array_type,
MemoryContext  rcontext 
)

Definition at line 5550 of file arrayfuncs.c.

5554{
5555 ArrayType *arg;
5556 MemoryContext oldcontext;
5557 int *dims,
5558 *lbs,
5559 ndims,
5560 nitems,
5561 ndatabytes;
5562 char *data;
5563 int i;
5564
5565 /*
5566 * We disallow accumulating null subarrays. Another plausible definition
5567 * is to ignore them, but callers that want that can just skip calling
5568 * this function.
5569 */
5570 if (disnull)
5571 ereport(ERROR,
5572 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5573 errmsg("cannot accumulate null arrays")));
5574
5575 /* Detoast input array in caller's context */
5576 arg = DatumGetArrayTypeP(dvalue);
5577
5578 if (astate == NULL)
5579 astate = initArrayResultArr(array_type, InvalidOid, rcontext, true);
5580 else
5581 Assert(astate->array_type == array_type);
5582
5583 oldcontext = MemoryContextSwitchTo(astate->mcontext);
5584
5585 /* Collect this input's dimensions */
5586 ndims = ARR_NDIM(arg);
5587 dims = ARR_DIMS(arg);
5588 lbs = ARR_LBOUND(arg);
5590 nitems = ArrayGetNItems(ndims, dims);
5591 ndatabytes = ARR_SIZE(arg) - ARR_DATA_OFFSET(arg);
5592
5593 if (astate->ndims == 0)
5594 {
5595 /* First input; check/save the dimensionality info */
5596
5597 /* Should we allow empty inputs and just produce an empty output? */
5598 if (ndims == 0)
5599 ereport(ERROR,
5600 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5601 errmsg("cannot accumulate empty arrays")));
5602 if (ndims + 1 > MAXDIM)
5603 ereport(ERROR,
5604 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5605 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5606 ndims + 1, MAXDIM)));
5607
5608 /*
5609 * The output array will have n+1 dimensions, with the ones after the
5610 * first matching the input's dimensions.
5611 */
5612 astate->ndims = ndims + 1;
5613 astate->dims[0] = 0;
5614 memcpy(&astate->dims[1], dims, ndims * sizeof(int));
5615 astate->lbs[0] = 1;
5616 memcpy(&astate->lbs[1], lbs, ndims * sizeof(int));
5617
5618 /* Allocate at least enough data space for this item */
5619 astate->abytes = pg_nextpower2_32(Max(1024, ndatabytes + 1));
5620 astate->data = (char *) palloc(astate->abytes);
5621 }
5622 else
5623 {
5624 /* Second or later input: must match first input's dimensionality */
5625 if (astate->ndims != ndims + 1)
5626 ereport(ERROR,
5627 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5628 errmsg("cannot accumulate arrays of different dimensionality")));
5629 for (i = 0; i < ndims; i++)
5630 {
5631 if (astate->dims[i + 1] != dims[i] || astate->lbs[i + 1] != lbs[i])
5632 ereport(ERROR,
5633 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5634 errmsg("cannot accumulate arrays of different dimensionality")));
5635 }
5636
5637 /* Enlarge data space if needed */
5638 if (astate->nbytes + ndatabytes > astate->abytes)
5639 {
5640 astate->abytes = Max(astate->abytes * 2,
5641 astate->nbytes + ndatabytes);
5642 astate->data = (char *) repalloc(astate->data, astate->abytes);
5643 }
5644 }
5645
5646 /*
5647 * Copy the data portion of the sub-array. Note we assume that the
5648 * advertised data length of the sub-array is properly aligned. We do not
5649 * have to worry about detoasting elements since whatever's in the
5650 * sub-array should be OK already.
5651 */
5652 memcpy(astate->data + astate->nbytes, data, ndatabytes);
5653 astate->nbytes += ndatabytes;
5654
5655 /* Deal with null bitmap if needed */
5656 if (astate->nullbitmap || ARR_HASNULL(arg))
5657 {
5658 int newnitems = astate->nitems + nitems;
5659
5660 if (astate->nullbitmap == NULL)
5661 {
5662 /*
5663 * First input with nulls; we must retrospectively handle any
5664 * previous inputs by marking all their items non-null.
5665 */
5666 astate->aitems = pg_nextpower2_32(Max(256, newnitems + 1));
5667 astate->nullbitmap = (bits8 *) palloc((astate->aitems + 7) / 8);
5668 array_bitmap_copy(astate->nullbitmap, 0,
5669 NULL, 0,
5670 astate->nitems);
5671 }
5672 else if (newnitems > astate->aitems)
5673 {
5674 astate->aitems = Max(astate->aitems * 2, newnitems);
5675 astate->nullbitmap = (bits8 *)
5676 repalloc(astate->nullbitmap, (astate->aitems + 7) / 8);
5677 }
5678 array_bitmap_copy(astate->nullbitmap, astate->nitems,
5679 ARR_NULLBITMAP(arg), 0,
5680 nitems);
5681 }
5682
5683 astate->nitems += nitems;
5684 astate->dims[0] += 1;
5685
5686 MemoryContextSwitchTo(oldcontext);
5687
5688 /* Release detoasted copy if any */
5689 if ((Pointer) arg != DatumGetPointer(dvalue))
5690 pfree(arg);
5691
5692 return astate;
5693}
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define MAXDIM
Definition: array.h:75
#define ARR_NULLBITMAP(a)
Definition: array.h:300
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_SIZE(a)
Definition: array.h:289
#define ARR_DATA_OFFSET(a)
Definition: array.h:316
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5504
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4966
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:57
#define Max(x, y)
Definition: c.h:955
char * Pointer
Definition: c.h:479
int i
Definition: isn.c:72
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
void * arg
static uint32 pg_nextpower2_32(uint32 num)
Definition: pg_bitutils.h:189
const void * data
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
#define InvalidOid
Definition: postgres_ext.h:37
bits8 * nullbitmap
Definition: array.h:209
int lbs[MAXDIM]
Definition: array.h:216
MemoryContext mcontext
Definition: array.h:207
int dims[MAXDIM]
Definition: array.h:215

References ArrayBuildStateArr::abytes, ArrayBuildStateArr::aitems, arg, ARR_DATA_OFFSET, ARR_DATA_PTR, ARR_DIMS, ARR_HASNULL, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_SIZE, array_bitmap_copy(), ArrayBuildStateArr::array_type, ArrayGetNItems(), Assert, ArrayBuildStateArr::data, data, DatumGetArrayTypeP, DatumGetPointer(), ArrayBuildStateArr::dims, ereport, errcode(), errmsg(), ERROR, i, initArrayResultArr(), InvalidOid, ArrayBuildStateArr::lbs, Max, MAXDIM, ArrayBuildStateArr::mcontext, MemoryContextSwitchTo(), ArrayBuildStateArr::nbytes, ArrayBuildStateArr::ndims, ArrayBuildStateArr::nitems, nitems, ArrayBuildStateArr::nullbitmap, palloc(), pfree(), pg_nextpower2_32(), and repalloc().

Referenced by accumArrayResultAny(), and array_agg_array_transfn().

◆ array_bitmap_copy()

void array_bitmap_copy ( bits8 destbitmap,
int  destoffset,
const bits8 srcbitmap,
int  srcoffset,
int  nitems 
)

Definition at line 4966 of file arrayfuncs.c.

4969{
4970 int destbitmask,
4971 destbitval,
4972 srcbitmask,
4973 srcbitval;
4974
4975 Assert(destbitmap);
4976 if (nitems <= 0)
4977 return; /* don't risk fetch off end of memory */
4978 destbitmap += destoffset / 8;
4979 destbitmask = 1 << (destoffset % 8);
4980 destbitval = *destbitmap;
4981 if (srcbitmap)
4982 {
4983 srcbitmap += srcoffset / 8;
4984 srcbitmask = 1 << (srcoffset % 8);
4985 srcbitval = *srcbitmap;
4986 while (nitems-- > 0)
4987 {
4988 if (srcbitval & srcbitmask)
4989 destbitval |= destbitmask;
4990 else
4991 destbitval &= ~destbitmask;
4992 destbitmask <<= 1;
4993 if (destbitmask == 0x100)
4994 {
4995 *destbitmap++ = destbitval;
4996 destbitmask = 1;
4997 if (nitems > 0)
4998 destbitval = *destbitmap;
4999 }
5000 srcbitmask <<= 1;
5001 if (srcbitmask == 0x100)
5002 {
5003 srcbitmap++;
5004 srcbitmask = 1;
5005 if (nitems > 0)
5006 srcbitval = *srcbitmap;
5007 }
5008 }
5009 if (destbitmask != 1)
5010 *destbitmap = destbitval;
5011 }
5012 else
5013 {
5014 while (nitems-- > 0)
5015 {
5016 destbitval |= destbitmask;
5017 destbitmask <<= 1;
5018 if (destbitmask == 0x100)
5019 {
5020 *destbitmap++ = destbitval;
5021 destbitmask = 1;
5022 if (nitems > 0)
5023 destbitval = *destbitmap;
5024 }
5025 }
5026 if (destbitmask != 1)
5027 *destbitmap = destbitval;
5028 }
5029}

References Assert, and nitems.

Referenced by accumArrayResultArr(), array_agg_array_combine(), array_cat(), array_extract_slice(), array_insert_slice(), array_set_element(), array_set_slice(), ExecEvalArrayExpr(), and makeArrayResultArr().

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

Definition at line 3767 of file arrayfuncs.c.

3768{
3769 int nelems;
3770 bits8 *bitmap;
3771 int bitmask;
3772
3773 /* Easy answer if there's no null bitmap */
3774 if (!ARR_HASNULL(array))
3775 return false;
3776
3777 nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3778
3779 bitmap = ARR_NULLBITMAP(array);
3780
3781 /* check whole bytes of the bitmap byte-at-a-time */
3782 while (nelems >= 8)
3783 {
3784 if (*bitmap != 0xFF)
3785 return true;
3786 bitmap++;
3787 nelems -= 8;
3788 }
3789
3790 /* check last partial byte */
3791 bitmask = 1;
3792 while (nelems > 0)
3793 {
3794 if ((*bitmap & bitmask) == 0)
3795 return true;
3796 bitmask <<= 1;
3797 nelems--;
3798 }
3799
3800 return false;
3801}

References ARR_DIMS, ARR_HASNULL, ARR_NDIM, ARR_NULLBITMAP, and ArrayGetNItems().

Referenced by _arrq_cons(), _lca(), _lt_q_regex(), _ltree_compress(), array_fill_internal(), array_iterator(), array_position_common(), array_positions(), ArrayGetIntegerTypmods(), arrq_cons(), cube_a_f8(), cube_a_f8_f8(), cube_subset(), get_jsonb_path_all(), get_path_all(), getWeights(), lt_q_regex(), pg_isolation_test_session_is_blocked(), pg_logical_slot_get_changes_guts(), sanity_check_array(), sanity_check_tid_array(), stats_check_arg_array(), text_to_stavalues(), width_bucket_array(), and worker_spi_launch().

◆ array_create_iterator()

ArrayIterator array_create_iterator ( ArrayType arr,
int  slice_ndim,
ArrayMetaState mstate 
)

Definition at line 4597 of file arrayfuncs.c.

4598{
4599 ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4600
4601 /*
4602 * Sanity-check inputs --- caller should have got this right already
4603 */
4604 Assert(PointerIsValid(arr));
4605 if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4606 elog(ERROR, "invalid arguments to array_create_iterator");
4607
4608 /*
4609 * Remember basic info about the array and its element type
4610 */
4611 iterator->arr = arr;
4612 iterator->nullbitmap = ARR_NULLBITMAP(arr);
4613 iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4614
4615 if (mstate != NULL)
4616 {
4617 Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4618
4619 iterator->typlen = mstate->typlen;
4620 iterator->typbyval = mstate->typbyval;
4621 iterator->typalign = mstate->typalign;
4622 }
4623 else
4625 &iterator->typlen,
4626 &iterator->typbyval,
4627 &iterator->typalign);
4628
4629 /*
4630 * Remember the slicing parameters.
4631 */
4632 iterator->slice_ndim = slice_ndim;
4633
4634 if (slice_ndim > 0)
4635 {
4636 /*
4637 * Get pointers into the array's dims and lbound arrays to represent
4638 * the dims/lbound arrays of a slice. These are the same as the
4639 * rightmost N dimensions of the array.
4640 */
4641 iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4642 iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4643
4644 /*
4645 * Compute number of elements in a slice.
4646 */
4647 iterator->slice_len = ArrayGetNItems(slice_ndim,
4648 iterator->slice_dims);
4649
4650 /*
4651 * Create workspace for building sub-arrays.
4652 */
4653 iterator->slice_values = (Datum *)
4654 palloc(iterator->slice_len * sizeof(Datum));
4655 iterator->slice_nulls = (bool *)
4656 palloc(iterator->slice_len * sizeof(bool));
4657 }
4658
4659 /*
4660 * Initialize our data pointer and linear element number. These will
4661 * advance through the array during array_iterate().
4662 */
4663 iterator->data_ptr = ARR_DATA_PTR(arr);
4664 iterator->current_item = 0;
4665
4666 return iterator;
4667}
#define PointerIsValid(pointer)
Definition: c.h:720
#define elog(elevel,...)
Definition: elog.h:225
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2298
void * palloc0(Size size)
Definition: mcxt.c:1347
ArrayType * arr
Definition: arrayfuncs.c:71
bool * slice_nulls
Definition: arrayfuncs.c:84
Datum * slice_values
Definition: arrayfuncs.c:83
bits8 * nullbitmap
Definition: arrayfuncs.c:72
char typalign
Definition: array.h:241
int16 typlen
Definition: array.h:239
Oid element_type
Definition: array.h:238
bool typbyval
Definition: array.h:240

References ArrayIteratorData::arr, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), Assert, ArrayIteratorData::current_item, ArrayIteratorData::data_ptr, ArrayMetaState::element_type, elog, ERROR, get_typlenbyvalalign(), ArrayIteratorData::nitems, ArrayIteratorData::nullbitmap, palloc(), palloc0(), PointerIsValid, ArrayIteratorData::slice_dims, ArrayIteratorData::slice_lbound, ArrayIteratorData::slice_len, ArrayIteratorData::slice_ndim, ArrayIteratorData::slice_nulls, ArrayIteratorData::slice_values, ArrayIteratorData::typalign, ArrayMetaState::typalign, ArrayIteratorData::typbyval, ArrayMetaState::typbyval, ArrayIteratorData::typlen, and ArrayMetaState::typlen.

Referenced by array_position_common(), array_positions(), and exec_stmt_foreach_a().

◆ array_free_iterator()

void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4759 of file arrayfuncs.c.

4760{
4761 if (iterator->slice_ndim > 0)
4762 {
4763 pfree(iterator->slice_values);
4764 pfree(iterator->slice_nulls);
4765 }
4766 pfree(iterator);
4767}

References pfree(), ArrayIteratorData::slice_ndim, ArrayIteratorData::slice_nulls, and ArrayIteratorData::slice_values.

Referenced by array_position_common(), and array_positions().

◆ array_get_element()

Datum array_get_element ( Datum  arraydatum,
int  nSubscripts,
int *  indx,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign,
bool *  isNull 
)

Definition at line 1820 of file arrayfuncs.c.

1828{
1829 int i,
1830 ndim,
1831 *dim,
1832 *lb,
1833 offset,
1834 fixedDim[1],
1835 fixedLb[1];
1836 char *arraydataptr,
1837 *retptr;
1838 bits8 *arraynullsptr;
1839
1840 if (arraytyplen > 0)
1841 {
1842 /*
1843 * fixed-length arrays -- these are assumed to be 1-d, 0-based
1844 */
1845 ndim = 1;
1846 fixedDim[0] = arraytyplen / elmlen;
1847 fixedLb[0] = 0;
1848 dim = fixedDim;
1849 lb = fixedLb;
1850 arraydataptr = (char *) DatumGetPointer(arraydatum);
1851 arraynullsptr = NULL;
1852 }
1853 else if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(arraydatum)))
1854 {
1855 /* expanded array: let's do this in a separate function */
1856 return array_get_element_expanded(arraydatum,
1857 nSubscripts,
1858 indx,
1859 arraytyplen,
1860 elmlen,
1861 elmbyval,
1862 elmalign,
1863 isNull);
1864 }
1865 else
1866 {
1867 /* detoast array if necessary, producing normal varlena input */
1868 ArrayType *array = DatumGetArrayTypeP(arraydatum);
1869
1870 ndim = ARR_NDIM(array);
1871 dim = ARR_DIMS(array);
1872 lb = ARR_LBOUND(array);
1873 arraydataptr = ARR_DATA_PTR(array);
1874 arraynullsptr = ARR_NULLBITMAP(array);
1875 }
1876
1877 /*
1878 * Return NULL for invalid subscript
1879 */
1880 if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
1881 {
1882 *isNull = true;
1883 return (Datum) 0;
1884 }
1885 for (i = 0; i < ndim; i++)
1886 {
1887 if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
1888 {
1889 *isNull = true;
1890 return (Datum) 0;
1891 }
1892 }
1893
1894 /*
1895 * Calculate the element number
1896 */
1897 offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
1898
1899 /*
1900 * Check for NULL array element
1901 */
1902 if (array_get_isnull(arraynullsptr, offset))
1903 {
1904 *isNull = true;
1905 return (Datum) 0;
1906 }
1907
1908 /*
1909 * OK, get the element
1910 */
1911 *isNull = false;
1912 retptr = array_seek(arraydataptr, 0, arraynullsptr, offset,
1913 elmlen, elmbyval, elmalign);
1914 return ArrayCast(retptr, elmbyval, elmlen);
1915}
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4781
static Datum array_get_element_expanded(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1921
static Datum ArrayCast(char *value, bool byval, int len)
Definition: arrayfuncs.c:4816
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4866
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:32
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: varatt.h:298

References ARR_DATA_PTR, ARR_DIMS, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, array_get_element_expanded(), array_get_isnull(), array_seek(), ArrayCast(), ArrayGetOffset(), DatumGetArrayTypeP, DatumGetPointer(), i, MAXDIM, and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by array_ref(), array_subscript_fetch(), array_subscript_fetch_old(), ATExecAlterColumnType(), and RelationBuildTupleDesc().

◆ array_get_slice()

Datum array_get_slice ( Datum  arraydatum,
int  nSubscripts,
int *  upperIndx,
int *  lowerIndx,
bool *  upperProvided,
bool *  lowerProvided,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 2030 of file arrayfuncs.c.

2040{
2041 ArrayType *array;
2042 ArrayType *newarray;
2043 int i,
2044 ndim,
2045 *dim,
2046 *lb,
2047 *newlb;
2048 int fixedDim[1],
2049 fixedLb[1];
2050 Oid elemtype;
2051 char *arraydataptr;
2052 bits8 *arraynullsptr;
2053 int32 dataoffset;
2054 int bytes,
2055 span[MAXDIM];
2056
2057 if (arraytyplen > 0)
2058 {
2059 /*
2060 * fixed-length arrays -- currently, cannot slice these because parser
2061 * labels output as being of the fixed-length array type! Code below
2062 * shows how we could support it if the parser were changed to label
2063 * output as a suitable varlena array type.
2064 */
2065 ereport(ERROR,
2066 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2067 errmsg("slices of fixed-length arrays not implemented")));
2068
2069 /*
2070 * fixed-length arrays -- these are assumed to be 1-d, 0-based
2071 *
2072 * XXX where would we get the correct ELEMTYPE from?
2073 */
2074 ndim = 1;
2075 fixedDim[0] = arraytyplen / elmlen;
2076 fixedLb[0] = 0;
2077 dim = fixedDim;
2078 lb = fixedLb;
2079 elemtype = InvalidOid; /* XXX */
2080 arraydataptr = (char *) DatumGetPointer(arraydatum);
2081 arraynullsptr = NULL;
2082 }
2083 else
2084 {
2085 /* detoast input array if necessary */
2086 array = DatumGetArrayTypeP(arraydatum);
2087
2088 ndim = ARR_NDIM(array);
2089 dim = ARR_DIMS(array);
2090 lb = ARR_LBOUND(array);
2091 elemtype = ARR_ELEMTYPE(array);
2092 arraydataptr = ARR_DATA_PTR(array);
2093 arraynullsptr = ARR_NULLBITMAP(array);
2094 }
2095
2096 /*
2097 * Check provided subscripts. A slice exceeding the current array limits
2098 * is silently truncated to the array limits. If we end up with an empty
2099 * slice, return an empty array.
2100 */
2101 if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
2102 return PointerGetDatum(construct_empty_array(elemtype));
2103
2104 for (i = 0; i < nSubscripts; i++)
2105 {
2106 if (!lowerProvided[i] || lowerIndx[i] < lb[i])
2107 lowerIndx[i] = lb[i];
2108 if (!upperProvided[i] || upperIndx[i] >= (dim[i] + lb[i]))
2109 upperIndx[i] = dim[i] + lb[i] - 1;
2110 if (lowerIndx[i] > upperIndx[i])
2111 return PointerGetDatum(construct_empty_array(elemtype));
2112 }
2113 /* fill any missing subscript positions with full array range */
2114 for (; i < ndim; i++)
2115 {
2116 lowerIndx[i] = lb[i];
2117 upperIndx[i] = dim[i] + lb[i] - 1;
2118 if (lowerIndx[i] > upperIndx[i])
2119 return PointerGetDatum(construct_empty_array(elemtype));
2120 }
2121
2122 mda_get_range(ndim, span, lowerIndx, upperIndx);
2123
2124 bytes = array_slice_size(arraydataptr, arraynullsptr,
2125 ndim, dim, lb,
2126 lowerIndx, upperIndx,
2127 elmlen, elmbyval, elmalign);
2128
2129 /*
2130 * Currently, we put a null bitmap in the result if the source has one;
2131 * could be smarter ...
2132 */
2133 if (arraynullsptr)
2134 {
2135 dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, ArrayGetNItems(ndim, span));
2136 bytes += dataoffset;
2137 }
2138 else
2139 {
2140 dataoffset = 0; /* marker for no null bitmap */
2141 bytes += ARR_OVERHEAD_NONULLS(ndim);
2142 }
2143
2144 newarray = (ArrayType *) palloc0(bytes);
2145 SET_VARSIZE(newarray, bytes);
2146 newarray->ndim = ndim;
2147 newarray->dataoffset = dataoffset;
2148 newarray->elemtype = elemtype;
2149 memcpy(ARR_DIMS(newarray), span, ndim * sizeof(int));
2150
2151 /*
2152 * Lower bounds of the new array are set to 1. Formerly (before 7.3) we
2153 * copied the given lowerIndx values ... but that seems confusing.
2154 */
2155 newlb = ARR_LBOUND(newarray);
2156 for (i = 0; i < ndim; i++)
2157 newlb[i] = 1;
2158
2159 array_extract_slice(newarray,
2160 ndim, dim, lb,
2161 arraydataptr, arraynullsptr,
2162 lowerIndx, upperIndx,
2163 elmlen, elmbyval, elmalign);
2164
2165 return PointerGetDatum(newarray);
2166}
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:312
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:310
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3580
static int array_slice_size(char *arraydataptr, bits8 *arraynullsptr, int ndim, int *dim, int *lb, int *st, int *endp, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:5037
static void array_extract_slice(ArrayType *newarray, int ndim, int *dim, int *lb, char *arraydataptr, bits8 *arraynullsptr, int *st, int *endp, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:5097
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:153
int32_t int32
Definition: c.h:484
unsigned int Oid
Definition: postgres_ext.h:32
Oid elemtype
Definition: array.h:97
int ndim
Definition: array.h:95
int32 dataoffset
Definition: array.h:96
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_extract_slice(), array_slice_size(), ArrayGetNItems(), construct_empty_array(), ArrayType::dataoffset, DatumGetArrayTypeP, DatumGetPointer(), ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, InvalidOid, MAXDIM, mda_get_range(), ArrayType::ndim, palloc0(), PointerGetDatum(), and SET_VARSIZE.

Referenced by array_subscript_fetch_old_slice(), array_subscript_fetch_slice(), and trim_array().

◆ array_iterate()

bool array_iterate ( ArrayIterator  iterator,
Datum value,
bool *  isnull 
)

Definition at line 4676 of file arrayfuncs.c.

4677{
4678 /* Done if we have reached the end of the array */
4679 if (iterator->current_item >= iterator->nitems)
4680 return false;
4681
4682 if (iterator->slice_ndim == 0)
4683 {
4684 /*
4685 * Scalar case: return one element.
4686 */
4687 if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4688 {
4689 *isnull = true;
4690 *value = (Datum) 0;
4691 }
4692 else
4693 {
4694 /* non-NULL, so fetch the individual Datum to return */
4695 char *p = iterator->data_ptr;
4696
4697 *isnull = false;
4698 *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4699
4700 /* Move our data pointer forward to the next element */
4701 p = att_addlength_pointer(p, iterator->typlen, p);
4702 p = (char *) att_align_nominal(p, iterator->typalign);
4703 iterator->data_ptr = p;
4704 }
4705 }
4706 else
4707 {
4708 /*
4709 * Slice case: build and return an array of the requested size.
4710 */
4711 ArrayType *result;
4712 Datum *values = iterator->slice_values;
4713 bool *nulls = iterator->slice_nulls;
4714 char *p = iterator->data_ptr;
4715 int i;
4716
4717 for (i = 0; i < iterator->slice_len; i++)
4718 {
4719 if (array_get_isnull(iterator->nullbitmap,
4720 iterator->current_item++))
4721 {
4722 nulls[i] = true;
4723 values[i] = (Datum) 0;
4724 }
4725 else
4726 {
4727 nulls[i] = false;
4728 values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4729
4730 /* Move our data pointer forward to the next element */
4731 p = att_addlength_pointer(p, iterator->typlen, p);
4732 p = (char *) att_align_nominal(p, iterator->typalign);
4733 }
4734 }
4735
4736 iterator->data_ptr = p;
4737
4738 result = construct_md_array(values,
4739 nulls,
4740 iterator->slice_ndim,
4741 iterator->slice_dims,
4742 iterator->slice_lbound,
4743 ARR_ELEMTYPE(iterator->arr),
4744 iterator->typlen,
4745 iterator->typbyval,
4746 iterator->typalign);
4747
4748 *isnull = false;
4749 *value = PointerGetDatum(result);
4750 }
4751
4752 return true;
4753}
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3494
static Datum values[MAXATTR]
Definition: bootstrap.c:151
static struct @162 value
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:150
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:185
static Datum fetch_att(const void *T, bool attbyval, int attlen)
Definition: tupmacs.h:53

References ArrayIteratorData::arr, ARR_ELEMTYPE, array_get_isnull(), att_addlength_pointer, att_align_nominal, construct_md_array(), ArrayIteratorData::current_item, ArrayIteratorData::data_ptr, fetch_att(), i, ArrayIteratorData::nitems, ArrayIteratorData::nullbitmap, PointerGetDatum(), ArrayIteratorData::slice_dims, ArrayIteratorData::slice_lbound, ArrayIteratorData::slice_len, ArrayIteratorData::slice_ndim, ArrayIteratorData::slice_nulls, ArrayIteratorData::slice_values, ArrayIteratorData::typalign, ArrayIteratorData::typbyval, ArrayIteratorData::typlen, value, and values.

Referenced by array_position_common(), array_positions(), and exec_stmt_foreach_a().

◆ array_map()

Datum array_map ( Datum  arrayd,
struct ExprState exprstate,
struct ExprContext econtext,
Oid  retType,
ArrayMapState amstate 
)

Definition at line 3201 of file arrayfuncs.c.

3204{
3205 AnyArrayType *v = DatumGetAnyArrayP(arrayd);
3206 ArrayType *result;
3207 Datum *values;
3208 bool *nulls;
3209 int *dim;
3210 int ndim;
3211 int nitems;
3212 int i;
3213 int32 nbytes = 0;
3214 int32 dataoffset;
3215 bool hasnulls;
3216 Oid inpType;
3217 int inp_typlen;
3218 bool inp_typbyval;
3219 char inp_typalign;
3220 int typlen;
3221 bool typbyval;
3222 char typalign;
3223 array_iter iter;
3224 ArrayMetaState *inp_extra;
3225 ArrayMetaState *ret_extra;
3226 Datum *transform_source = exprstate->innermost_caseval;
3227 bool *transform_source_isnull = exprstate->innermost_casenull;
3228
3229 inpType = AARR_ELEMTYPE(v);
3230 ndim = AARR_NDIM(v);
3231 dim = AARR_DIMS(v);
3232 nitems = ArrayGetNItems(ndim, dim);
3233
3234 /* Check for empty array */
3235 if (nitems <= 0)
3236 {
3237 /* Return empty array */
3238 return PointerGetDatum(construct_empty_array(retType));
3239 }
3240
3241 /*
3242 * We arrange to look up info about input and return element types only
3243 * once per series of calls, assuming the element type doesn't change
3244 * underneath us.
3245 */
3246 inp_extra = &amstate->inp_extra;
3247 ret_extra = &amstate->ret_extra;
3248
3249 if (inp_extra->element_type != inpType)
3250 {
3251 get_typlenbyvalalign(inpType,
3252 &inp_extra->typlen,
3253 &inp_extra->typbyval,
3254 &inp_extra->typalign);
3255 inp_extra->element_type = inpType;
3256 }
3257 inp_typlen = inp_extra->typlen;
3258 inp_typbyval = inp_extra->typbyval;
3259 inp_typalign = inp_extra->typalign;
3260
3261 if (ret_extra->element_type != retType)
3262 {
3263 get_typlenbyvalalign(retType,
3264 &ret_extra->typlen,
3265 &ret_extra->typbyval,
3266 &ret_extra->typalign);
3267 ret_extra->element_type = retType;
3268 }
3269 typlen = ret_extra->typlen;
3270 typbyval = ret_extra->typbyval;
3271 typalign = ret_extra->typalign;
3272
3273 /* Allocate temporary arrays for new values */
3274 values = (Datum *) palloc(nitems * sizeof(Datum));
3275 nulls = (bool *) palloc(nitems * sizeof(bool));
3276
3277 /* Loop over source data */
3278 array_iter_setup(&iter, v);
3279 hasnulls = false;
3280
3281 for (i = 0; i < nitems; i++)
3282 {
3283 /* Get source element, checking for NULL */
3284 *transform_source =
3285 array_iter_next(&iter, transform_source_isnull, i,
3286 inp_typlen, inp_typbyval, inp_typalign);
3287
3288 /* Apply the given expression to source element */
3289 values[i] = ExecEvalExpr(exprstate, econtext, &nulls[i]);
3290
3291 if (nulls[i])
3292 hasnulls = true;
3293 else
3294 {
3295 /* Ensure data is not toasted */
3296 if (typlen == -1)
3298 /* Update total result size */
3299 nbytes = att_addlength_datum(nbytes, typlen, values[i]);
3300 nbytes = att_align_nominal(nbytes, typalign);
3301 /* check for overflow of total request */
3302 if (!AllocSizeIsValid(nbytes))
3303 ereport(ERROR,
3304 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3305 errmsg("array size exceeds the maximum allowed (%d)",
3306 (int) MaxAllocSize)));
3307 }
3308 }
3309
3310 /* Allocate and fill the result array */
3311 if (hasnulls)
3312 {
3313 dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3314 nbytes += dataoffset;
3315 }
3316 else
3317 {
3318 dataoffset = 0; /* marker for no null bitmap */
3319 nbytes += ARR_OVERHEAD_NONULLS(ndim);
3320 }
3321 result = (ArrayType *) palloc0(nbytes);
3322 SET_VARSIZE(result, nbytes);
3323 result->ndim = ndim;
3324 result->dataoffset = dataoffset;
3325 result->elemtype = retType;
3326 memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
3327 memcpy(ARR_LBOUND(result), AARR_LBOUND(v), ndim * sizeof(int));
3328
3329 CopyArrayEls(result,
3330 values, nulls, nitems,
3331 typlen, typbyval, typalign,
3332 false);
3333
3334 /*
3335 * Note: do not risk trying to pfree the results of the called expression
3336 */
3337 pfree(values);
3338 pfree(nulls);
3339
3340 return PointerGetDatum(result);
3341}
#define AARR_DIMS(a)
Definition: array.h:338
#define AARR_ELEMTYPE(a)
Definition: array.h:335
#define AARR_LBOUND(a)
Definition: array.h:341
#define AARR_NDIM(a)
Definition: array.h:328
AnyArrayType * DatumGetAnyArrayP(Datum d)
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:961
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:346
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240
char typalign
Definition: pg_type.h:176
ArrayMetaState inp_extra
Definition: array.h:253
ArrayMetaState ret_extra
Definition: array.h:254
bool * innermost_casenull
Definition: execnodes.h:138
Datum * innermost_caseval
Definition: execnodes.h:137
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:173

References AARR_DIMS, AARR_ELEMTYPE, AARR_LBOUND, AARR_NDIM, AllocSizeIsValid, ARR_DIMS, ARR_LBOUND, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_iter_next(), array_iter_setup(), ArrayGetNItems(), att_addlength_datum, att_align_nominal, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, DatumGetAnyArrayP(), ArrayMetaState::element_type, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, ExecEvalExpr(), get_typlenbyvalalign(), i, ExprState::innermost_casenull, ExprState::innermost_caseval, ArrayMapState::inp_extra, MaxAllocSize, ArrayType::ndim, nitems, palloc(), palloc0(), pfree(), PG_DETOAST_DATUM, PointerGetDatum(), ArrayMapState::ret_extra, SET_VARSIZE, typalign, ArrayMetaState::typalign, ArrayMetaState::typbyval, ArrayMetaState::typlen, and values.

Referenced by ExecEvalArrayCoerce().

◆ array_ref()

Datum array_ref ( ArrayType array,
int  nSubscripts,
int *  indx,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign,
bool *  isNull 
)

Definition at line 3146 of file arrayfuncs.c.

3149{
3150 return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3151 arraytyplen, elmlen, elmbyval, elmalign,
3152 isNull);
3153}
Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1820

References array_get_element(), and PointerGetDatum().

Referenced by GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), pg_get_functiondef(), and TransformGUCArray().

◆ array_set()

ArrayType * array_set ( ArrayType array,
int  nSubscripts,
int *  indx,
Datum  dataValue,
bool  isNull,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 3163 of file arrayfuncs.c.

3166{
3168 nSubscripts, indx,
3169 dataValue, isNull,
3170 arraytyplen,
3171 elmlen, elmbyval, elmalign));
3172}
Datum array_set_element(Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:2201

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum().

Referenced by GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), and pg_extension_config_dump().

◆ array_set_element()

Datum array_set_element ( Datum  arraydatum,
int  nSubscripts,
int *  indx,
Datum  dataValue,
bool  isNull,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 2201 of file arrayfuncs.c.

2210{
2211 ArrayType *array;
2212 ArrayType *newarray;
2213 int i,
2214 ndim,
2215 dim[MAXDIM],
2216 lb[MAXDIM],
2217 offset;
2218 char *elt_ptr;
2219 bool newhasnulls;
2220 bits8 *oldnullbitmap;
2221 int oldnitems,
2222 newnitems,
2223 olddatasize,
2224 newsize,
2225 olditemlen,
2226 newitemlen,
2227 overheadlen,
2228 oldoverheadlen,
2229 addedbefore,
2230 addedafter,
2231 lenbefore,
2232 lenafter;
2233
2234 if (arraytyplen > 0)
2235 {
2236 /*
2237 * fixed-length arrays -- these are assumed to be 1-d, 0-based. We
2238 * cannot extend them, either.
2239 */
2240 char *resultarray;
2241
2242 if (nSubscripts != 1)
2243 ereport(ERROR,
2244 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2245 errmsg("wrong number of array subscripts")));
2246
2247 if (indx[0] < 0 || indx[0] >= arraytyplen / elmlen)
2248 ereport(ERROR,
2249 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2250 errmsg("array subscript out of range")));
2251
2252 if (isNull)
2253 ereport(ERROR,
2254 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2255 errmsg("cannot assign null value to an element of a fixed-length array")));
2256
2257 resultarray = (char *) palloc(arraytyplen);
2258 memcpy(resultarray, DatumGetPointer(arraydatum), arraytyplen);
2259 elt_ptr = (char *) resultarray + indx[0] * elmlen;
2260 ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elt_ptr);
2261 return PointerGetDatum(resultarray);
2262 }
2263
2264 if (nSubscripts <= 0 || nSubscripts > MAXDIM)
2265 ereport(ERROR,
2266 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2267 errmsg("wrong number of array subscripts")));
2268
2269 /* make sure item to be inserted is not toasted */
2270 if (elmlen == -1 && !isNull)
2271 dataValue = PointerGetDatum(PG_DETOAST_DATUM(dataValue));
2272
2274 {
2275 /* expanded array: let's do this in a separate function */
2276 return array_set_element_expanded(arraydatum,
2277 nSubscripts,
2278 indx,
2279 dataValue,
2280 isNull,
2281 arraytyplen,
2282 elmlen,
2283 elmbyval,
2284 elmalign);
2285 }
2286
2287 /* detoast input array if necessary */
2288 array = DatumGetArrayTypeP(arraydatum);
2289
2290 ndim = ARR_NDIM(array);
2291
2292 /*
2293 * if number of dims is zero, i.e. an empty array, create an array with
2294 * nSubscripts dimensions, and set the lower bounds to the supplied
2295 * subscripts
2296 */
2297 if (ndim == 0)
2298 {
2299 Oid elmtype = ARR_ELEMTYPE(array);
2300
2301 for (i = 0; i < nSubscripts; i++)
2302 {
2303 dim[i] = 1;
2304 lb[i] = indx[i];
2305 }
2306
2307 return PointerGetDatum(construct_md_array(&dataValue, &isNull,
2308 nSubscripts, dim, lb,
2309 elmtype,
2310 elmlen, elmbyval, elmalign));
2311 }
2312
2313 if (ndim != nSubscripts)
2314 ereport(ERROR,
2315 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2316 errmsg("wrong number of array subscripts")));
2317
2318 /* copy dim/lb since we may modify them */
2319 memcpy(dim, ARR_DIMS(array), ndim * sizeof(int));
2320 memcpy(lb, ARR_LBOUND(array), ndim * sizeof(int));
2321
2322 newhasnulls = (ARR_HASNULL(array) || isNull);
2323 addedbefore = addedafter = 0;
2324
2325 /*
2326 * Check subscripts. We assume the existing subscripts passed
2327 * ArrayCheckBounds, so that dim[i] + lb[i] can be computed without
2328 * overflow. But we must beware of other overflows in our calculations of
2329 * new dim[] values.
2330 */
2331 if (ndim == 1)
2332 {
2333 if (indx[0] < lb[0])
2334 {
2335 /* addedbefore = lb[0] - indx[0]; */
2336 /* dim[0] += addedbefore; */
2337 if (pg_sub_s32_overflow(lb[0], indx[0], &addedbefore) ||
2338 pg_add_s32_overflow(dim[0], addedbefore, &dim[0]))
2339 ereport(ERROR,
2340 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2341 errmsg("array size exceeds the maximum allowed (%d)",
2342 (int) MaxArraySize)));
2343 lb[0] = indx[0];
2344 if (addedbefore > 1)
2345 newhasnulls = true; /* will insert nulls */
2346 }
2347 if (indx[0] >= (dim[0] + lb[0]))
2348 {
2349 /* addedafter = indx[0] - (dim[0] + lb[0]) + 1; */
2350 /* dim[0] += addedafter; */
2351 if (pg_sub_s32_overflow(indx[0], dim[0] + lb[0], &addedafter) ||
2352 pg_add_s32_overflow(addedafter, 1, &addedafter) ||
2353 pg_add_s32_overflow(dim[0], addedafter, &dim[0]))
2354 ereport(ERROR,
2355 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2356 errmsg("array size exceeds the maximum allowed (%d)",
2357 (int) MaxArraySize)));
2358 if (addedafter > 1)
2359 newhasnulls = true; /* will insert nulls */
2360 }
2361 }
2362 else
2363 {
2364 /*
2365 * XXX currently we do not support extending multi-dimensional arrays
2366 * during assignment
2367 */
2368 for (i = 0; i < ndim; i++)
2369 {
2370 if (indx[i] < lb[i] ||
2371 indx[i] >= (dim[i] + lb[i]))
2372 ereport(ERROR,
2373 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2374 errmsg("array subscript out of range")));
2375 }
2376 }
2377
2378 /* This checks for overflow of the array dimensions */
2379 newnitems = ArrayGetNItems(ndim, dim);
2380 ArrayCheckBounds(ndim, dim, lb);
2381
2382 /*
2383 * Compute sizes of items and areas to copy
2384 */
2385 if (newhasnulls)
2386 overheadlen = ARR_OVERHEAD_WITHNULLS(ndim, newnitems);
2387 else
2388 overheadlen = ARR_OVERHEAD_NONULLS(ndim);
2389 oldnitems = ArrayGetNItems(ndim, ARR_DIMS(array));
2390 oldnullbitmap = ARR_NULLBITMAP(array);
2391 oldoverheadlen = ARR_DATA_OFFSET(array);
2392 olddatasize = ARR_SIZE(array) - oldoverheadlen;
2393 if (addedbefore)
2394 {
2395 offset = 0;
2396 lenbefore = 0;
2397 olditemlen = 0;
2398 lenafter = olddatasize;
2399 }
2400 else if (addedafter)
2401 {
2402 offset = oldnitems;
2403 lenbefore = olddatasize;
2404 olditemlen = 0;
2405 lenafter = 0;
2406 }
2407 else
2408 {
2409 offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
2410 elt_ptr = array_seek(ARR_DATA_PTR(array), 0, oldnullbitmap, offset,
2411 elmlen, elmbyval, elmalign);
2412 lenbefore = (int) (elt_ptr - ARR_DATA_PTR(array));
2413 if (array_get_isnull(oldnullbitmap, offset))
2414 olditemlen = 0;
2415 else
2416 {
2417 olditemlen = att_addlength_pointer(0, elmlen, elt_ptr);
2418 olditemlen = att_align_nominal(olditemlen, elmalign);
2419 }
2420 lenafter = (int) (olddatasize - lenbefore - olditemlen);
2421 }
2422
2423 if (isNull)
2424 newitemlen = 0;
2425 else
2426 {
2427 newitemlen = att_addlength_datum(0, elmlen, dataValue);
2428 newitemlen = att_align_nominal(newitemlen, elmalign);
2429 }
2430
2431 newsize = overheadlen + lenbefore + newitemlen + lenafter;
2432
2433 /*
2434 * OK, create the new array and fill in header/dimensions
2435 */
2436 newarray = (ArrayType *) palloc0(newsize);
2437 SET_VARSIZE(newarray, newsize);
2438 newarray->ndim = ndim;
2439 newarray->dataoffset = newhasnulls ? overheadlen : 0;
2440 newarray->elemtype = ARR_ELEMTYPE(array);
2441 memcpy(ARR_DIMS(newarray), dim, ndim * sizeof(int));
2442 memcpy(ARR_LBOUND(newarray), lb, ndim * sizeof(int));
2443
2444 /*
2445 * Fill in data
2446 */
2447 memcpy((char *) newarray + overheadlen,
2448 (char *) array + oldoverheadlen,
2449 lenbefore);
2450 if (!isNull)
2451 ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign,
2452 (char *) newarray + overheadlen + lenbefore);
2453 memcpy((char *) newarray + overheadlen + lenbefore + newitemlen,
2454 (char *) array + oldoverheadlen + lenbefore + olditemlen,
2455 lenafter);
2456
2457 /*
2458 * Fill in nulls bitmap if needed
2459 *
2460 * Note: it's possible we just replaced the last NULL with a non-NULL, and
2461 * could get rid of the bitmap. Seems not worth testing for though.
2462 */
2463 if (newhasnulls)
2464 {
2465 bits8 *newnullbitmap = ARR_NULLBITMAP(newarray);
2466
2467 /* palloc0 above already marked any inserted positions as nulls */
2468 /* Fix the inserted value */
2469 if (addedafter)
2470 array_set_isnull(newnullbitmap, newnitems - 1, isNull);
2471 else
2472 array_set_isnull(newnullbitmap, offset, isNull);
2473 /* Fix the copied range(s) */
2474 if (addedbefore)
2475 array_bitmap_copy(newnullbitmap, addedbefore,
2476 oldnullbitmap, 0,
2477 oldnitems);
2478 else
2479 {
2480 array_bitmap_copy(newnullbitmap, 0,
2481 oldnullbitmap, 0,
2482 offset);
2483 if (addedafter == 0)
2484 array_bitmap_copy(newnullbitmap, offset + 1,
2485 oldnullbitmap, offset + 1,
2486 oldnitems - offset - 1);
2487 }
2488 }
2489
2490 return PointerGetDatum(newarray);
2491}
#define MaxArraySize
Definition: array.h:82
static Datum array_set_element_expanded(Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:2501
static void array_set_isnull(bits8 *nullbitmap, int offset, bool isNull)
Definition: arrayfuncs.c:4798
static int ArrayCastAndSet(Datum src, int typlen, bool typbyval, char typalign, char *dest)
Definition: arrayfuncs.c:4827
void ArrayCheckBounds(int ndim, const int *dims, const int *lb)
Definition: arrayutils.c:117
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:169
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:151

References ARR_DATA_OFFSET, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ARR_SIZE, array_bitmap_copy(), array_get_isnull(), array_seek(), array_set_element_expanded(), array_set_isnull(), ArrayCastAndSet(), ArrayCheckBounds(), ArrayGetNItems(), ArrayGetOffset(), att_addlength_datum, att_addlength_pointer, att_align_nominal, construct_md_array(), ArrayType::dataoffset, DatumGetArrayTypeP, DatumGetPointer(), ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, MaxArraySize, MAXDIM, ArrayType::ndim, palloc(), palloc0(), pg_add_s32_overflow(), PG_DETOAST_DATUM, pg_sub_s32_overflow(), PointerGetDatum(), SET_VARSIZE, and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by array_append(), array_prepend(), array_set(), and array_subscript_assign().

◆ array_set_slice()

Datum array_set_slice ( Datum  arraydatum,
int  nSubscripts,
int *  upperIndx,
int *  lowerIndx,
bool *  upperProvided,
bool *  lowerProvided,
Datum  srcArrayDatum,
bool  isNull,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 2806 of file arrayfuncs.c.

2818{
2819 ArrayType *array;
2820 ArrayType *srcArray;
2821 ArrayType *newarray;
2822 int i,
2823 ndim,
2824 dim[MAXDIM],
2825 lb[MAXDIM],
2826 span[MAXDIM];
2827 bool newhasnulls;
2828 int nitems,
2829 nsrcitems,
2830 olddatasize,
2831 newsize,
2832 olditemsize,
2833 newitemsize,
2834 overheadlen,
2835 oldoverheadlen,
2836 addedbefore,
2837 addedafter,
2838 lenbefore,
2839 lenafter,
2840 itemsbefore,
2841 itemsafter,
2842 nolditems;
2843
2844 /* Currently, assignment from a NULL source array is a no-op */
2845 if (isNull)
2846 return arraydatum;
2847
2848 if (arraytyplen > 0)
2849 {
2850 /*
2851 * fixed-length arrays -- not got round to doing this...
2852 */
2853 ereport(ERROR,
2854 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2855 errmsg("updates on slices of fixed-length arrays not implemented")));
2856 }
2857
2858 /* detoast arrays if necessary */
2859 array = DatumGetArrayTypeP(arraydatum);
2860 srcArray = DatumGetArrayTypeP(srcArrayDatum);
2861
2862 /* note: we assume srcArray contains no toasted elements */
2863
2864 ndim = ARR_NDIM(array);
2865
2866 /*
2867 * if number of dims is zero, i.e. an empty array, create an array with
2868 * nSubscripts dimensions, and set the upper and lower bounds to the
2869 * supplied subscripts
2870 */
2871 if (ndim == 0)
2872 {
2873 Datum *dvalues;
2874 bool *dnulls;
2875 int nelems;
2876 Oid elmtype = ARR_ELEMTYPE(array);
2877
2878 deconstruct_array(srcArray, elmtype, elmlen, elmbyval, elmalign,
2879 &dvalues, &dnulls, &nelems);
2880
2881 for (i = 0; i < nSubscripts; i++)
2882 {
2883 if (!upperProvided[i] || !lowerProvided[i])
2884 ereport(ERROR,
2885 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2886 errmsg("array slice subscript must provide both boundaries"),
2887 errdetail("When assigning to a slice of an empty array value,"
2888 " slice boundaries must be fully specified.")));
2889
2890 /* compute "upperIndx[i] - lowerIndx[i] + 1", detecting overflow */
2891 if (pg_sub_s32_overflow(upperIndx[i], lowerIndx[i], &dim[i]) ||
2892 pg_add_s32_overflow(dim[i], 1, &dim[i]))
2893 ereport(ERROR,
2894 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2895 errmsg("array size exceeds the maximum allowed (%d)",
2896 (int) MaxArraySize)));
2897
2898 lb[i] = lowerIndx[i];
2899 }
2900
2901 /* complain if too few source items; we ignore extras, however */
2902 if (nelems < ArrayGetNItems(nSubscripts, dim))
2903 ereport(ERROR,
2904 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2905 errmsg("source array too small")));
2906
2907 return PointerGetDatum(construct_md_array(dvalues, dnulls, nSubscripts,
2908 dim, lb, elmtype,
2909 elmlen, elmbyval, elmalign));
2910 }
2911
2912 if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
2913 ereport(ERROR,
2914 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2915 errmsg("wrong number of array subscripts")));
2916
2917 /* copy dim/lb since we may modify them */
2918 memcpy(dim, ARR_DIMS(array), ndim * sizeof(int));
2919 memcpy(lb, ARR_LBOUND(array), ndim * sizeof(int));
2920
2921 newhasnulls = (ARR_HASNULL(array) || ARR_HASNULL(srcArray));
2922 addedbefore = addedafter = 0;
2923
2924 /*
2925 * Check subscripts. We assume the existing subscripts passed
2926 * ArrayCheckBounds, so that dim[i] + lb[i] can be computed without
2927 * overflow. But we must beware of other overflows in our calculations of
2928 * new dim[] values.
2929 */
2930 if (ndim == 1)
2931 {
2932 Assert(nSubscripts == 1);
2933 if (!lowerProvided[0])
2934 lowerIndx[0] = lb[0];
2935 if (!upperProvided[0])
2936 upperIndx[0] = dim[0] + lb[0] - 1;
2937 if (lowerIndx[0] > upperIndx[0])
2938 ereport(ERROR,
2939 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2940 errmsg("upper bound cannot be less than lower bound")));
2941 if (lowerIndx[0] < lb[0])
2942 {
2943 /* addedbefore = lb[0] - lowerIndx[0]; */
2944 /* dim[0] += addedbefore; */
2945 if (pg_sub_s32_overflow(lb[0], lowerIndx[0], &addedbefore) ||
2946 pg_add_s32_overflow(dim[0], addedbefore, &dim[0]))
2947 ereport(ERROR,
2948 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2949 errmsg("array size exceeds the maximum allowed (%d)",
2950 (int) MaxArraySize)));
2951 lb[0] = lowerIndx[0];
2952 if (addedbefore > 1)
2953 newhasnulls = true; /* will insert nulls */
2954 }
2955 if (upperIndx[0] >= (dim[0] + lb[0]))
2956 {
2957 /* addedafter = upperIndx[0] - (dim[0] + lb[0]) + 1; */
2958 /* dim[0] += addedafter; */
2959 if (pg_sub_s32_overflow(upperIndx[0], dim[0] + lb[0], &addedafter) ||
2960 pg_add_s32_overflow(addedafter, 1, &addedafter) ||
2961 pg_add_s32_overflow(dim[0], addedafter, &dim[0]))
2962 ereport(ERROR,
2963 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2964 errmsg("array size exceeds the maximum allowed (%d)",
2965 (int) MaxArraySize)));
2966 if (addedafter > 1)
2967 newhasnulls = true; /* will insert nulls */
2968 }
2969 }
2970 else
2971 {
2972 /*
2973 * XXX currently we do not support extending multi-dimensional arrays
2974 * during assignment
2975 */
2976 for (i = 0; i < nSubscripts; i++)
2977 {
2978 if (!lowerProvided[i])
2979 lowerIndx[i] = lb[i];
2980 if (!upperProvided[i])
2981 upperIndx[i] = dim[i] + lb[i] - 1;
2982 if (lowerIndx[i] > upperIndx[i])
2983 ereport(ERROR,
2984 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2985 errmsg("upper bound cannot be less than lower bound")));
2986 if (lowerIndx[i] < lb[i] ||
2987 upperIndx[i] >= (dim[i] + lb[i]))
2988 ereport(ERROR,
2989 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2990 errmsg("array subscript out of range")));
2991 }
2992 /* fill any missing subscript positions with full array range */
2993 for (; i < ndim; i++)
2994 {
2995 lowerIndx[i] = lb[i];
2996 upperIndx[i] = dim[i] + lb[i] - 1;
2997 if (lowerIndx[i] > upperIndx[i])
2998 ereport(ERROR,
2999 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3000 errmsg("upper bound cannot be less than lower bound")));
3001 }
3002 }
3003
3004 /* Do this mainly to check for overflow */
3005 nitems = ArrayGetNItems(ndim, dim);
3006 ArrayCheckBounds(ndim, dim, lb);
3007
3008 /*
3009 * Make sure source array has enough entries. Note we ignore the shape of
3010 * the source array and just read entries serially.
3011 */
3012 mda_get_range(ndim, span, lowerIndx, upperIndx);
3013 nsrcitems = ArrayGetNItems(ndim, span);
3014 if (nsrcitems > ArrayGetNItems(ARR_NDIM(srcArray), ARR_DIMS(srcArray)))
3015 ereport(ERROR,
3016 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3017 errmsg("source array too small")));
3018
3019 /*
3020 * Compute space occupied by new entries, space occupied by replaced
3021 * entries, and required space for new array.
3022 */
3023 if (newhasnulls)
3024 overheadlen = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3025 else
3026 overheadlen = ARR_OVERHEAD_NONULLS(ndim);
3027 newitemsize = array_nelems_size(ARR_DATA_PTR(srcArray), 0,
3028 ARR_NULLBITMAP(srcArray), nsrcitems,
3029 elmlen, elmbyval, elmalign);
3030 oldoverheadlen = ARR_DATA_OFFSET(array);
3031 olddatasize = ARR_SIZE(array) - oldoverheadlen;
3032 if (ndim > 1)
3033 {
3034 /*
3035 * here we do not need to cope with extension of the array; it would
3036 * be a lot more complicated if we had to do so...
3037 */
3038 olditemsize = array_slice_size(ARR_DATA_PTR(array),
3039 ARR_NULLBITMAP(array),
3040 ndim, dim, lb,
3041 lowerIndx, upperIndx,
3042 elmlen, elmbyval, elmalign);
3043 lenbefore = lenafter = 0; /* keep compiler quiet */
3044 itemsbefore = itemsafter = nolditems = 0;
3045 }
3046 else
3047 {
3048 /*
3049 * here we must allow for possibility of slice larger than orig array
3050 * and/or not adjacent to orig array subscripts
3051 */
3052 int oldlb = ARR_LBOUND(array)[0];
3053 int oldub = oldlb + ARR_DIMS(array)[0] - 1;
3054 int slicelb = Max(oldlb, lowerIndx[0]);
3055 int sliceub = Min(oldub, upperIndx[0]);
3056 char *oldarraydata = ARR_DATA_PTR(array);
3057 bits8 *oldarraybitmap = ARR_NULLBITMAP(array);
3058
3059 /* count/size of old array entries that will go before the slice */
3060 itemsbefore = Min(slicelb, oldub + 1) - oldlb;
3061 lenbefore = array_nelems_size(oldarraydata, 0, oldarraybitmap,
3062 itemsbefore,
3063 elmlen, elmbyval, elmalign);
3064 /* count/size of old array entries that will be replaced by slice */
3065 if (slicelb > sliceub)
3066 {
3067 nolditems = 0;
3068 olditemsize = 0;
3069 }
3070 else
3071 {
3072 nolditems = sliceub - slicelb + 1;
3073 olditemsize = array_nelems_size(oldarraydata + lenbefore,
3074 itemsbefore, oldarraybitmap,
3075 nolditems,
3076 elmlen, elmbyval, elmalign);
3077 }
3078 /* count/size of old array entries that will go after the slice */
3079 itemsafter = oldub + 1 - Max(sliceub + 1, oldlb);
3080 lenafter = olddatasize - lenbefore - olditemsize;
3081 }
3082
3083 newsize = overheadlen + olddatasize - olditemsize + newitemsize;
3084
3085 newarray = (ArrayType *) palloc0(newsize);
3086 SET_VARSIZE(newarray, newsize);
3087 newarray->ndim = ndim;
3088 newarray->dataoffset = newhasnulls ? overheadlen : 0;
3089 newarray->elemtype = ARR_ELEMTYPE(array);
3090 memcpy(ARR_DIMS(newarray), dim, ndim * sizeof(int));
3091 memcpy(ARR_LBOUND(newarray), lb, ndim * sizeof(int));
3092
3093 if (ndim > 1)
3094 {
3095 /*
3096 * here we do not need to cope with extension of the array; it would
3097 * be a lot more complicated if we had to do so...
3098 */
3099 array_insert_slice(newarray, array, srcArray,
3100 ndim, dim, lb,
3101 lowerIndx, upperIndx,
3102 elmlen, elmbyval, elmalign);
3103 }
3104 else
3105 {
3106 /* fill in data */
3107 memcpy((char *) newarray + overheadlen,
3108 (char *) array + oldoverheadlen,
3109 lenbefore);
3110 memcpy((char *) newarray + overheadlen + lenbefore,
3111 ARR_DATA_PTR(srcArray),
3112 newitemsize);
3113 memcpy((char *) newarray + overheadlen + lenbefore + newitemsize,
3114 (char *) array + oldoverheadlen + lenbefore + olditemsize,
3115 lenafter);
3116 /* fill in nulls bitmap if needed */
3117 if (newhasnulls)
3118 {
3119 bits8 *newnullbitmap = ARR_NULLBITMAP(newarray);
3120 bits8 *oldnullbitmap = ARR_NULLBITMAP(array);
3121
3122 /* palloc0 above already marked any inserted positions as nulls */
3123 array_bitmap_copy(newnullbitmap, addedbefore,
3124 oldnullbitmap, 0,
3125 itemsbefore);
3126 array_bitmap_copy(newnullbitmap, lowerIndx[0] - lb[0],
3127 ARR_NULLBITMAP(srcArray), 0,
3128 nsrcitems);
3129 array_bitmap_copy(newnullbitmap, addedbefore + itemsbefore + nolditems,
3130 oldnullbitmap, itemsbefore + nolditems,
3131 itemsafter);
3132 }
3133 }
3134
3135 return PointerGetDatum(newarray);
3136}
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3631
static void array_insert_slice(ArrayType *destArray, ArrayType *origArray, ArrayType *srcArray, int ndim, int *dim, int *lb, int *st, int *endp, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:5170
static int array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4914
#define Min(x, y)
Definition: c.h:961
int errdetail(const char *fmt,...)
Definition: elog.c:1203

References ARR_DATA_OFFSET, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ARR_SIZE, array_bitmap_copy(), array_insert_slice(), array_nelems_size(), array_slice_size(), ArrayCheckBounds(), ArrayGetNItems(), Assert, construct_md_array(), ArrayType::dataoffset, DatumGetArrayTypeP, deconstruct_array(), ArrayType::elemtype, ereport, errcode(), errdetail(), errmsg(), ERROR, i, Max, MaxArraySize, MAXDIM, mda_get_range(), Min, ArrayType::ndim, nitems, palloc0(), pg_add_s32_overflow(), pg_sub_s32_overflow(), PointerGetDatum(), and SET_VARSIZE.

Referenced by array_subscript_assign_slice().

◆ ArrayCheckBounds()

void ArrayCheckBounds ( int  ndim,
const int *  dims,
const int *  lb 
)

Definition at line 117 of file arrayutils.c.

118{
119 (void) ArrayCheckBoundsSafe(ndim, dims, lb, NULL);
120}
bool ArrayCheckBoundsSafe(int ndim, const int *dims, const int *lb, struct Node *escontext)
Definition: arrayutils.c:127

References ArrayCheckBoundsSafe().

Referenced by array_cat(), array_fill_internal(), array_recv(), array_set_element(), array_set_element_expanded(), array_set_slice(), construct_md_array(), ExecEvalArrayExpr(), and makeArrayResultArr().

◆ ArrayCheckBoundsSafe()

bool ArrayCheckBoundsSafe ( int  ndim,
const int *  dims,
const int *  lb,
struct Node escontext 
)

Definition at line 127 of file arrayutils.c.

129{
130 int i;
131
132 for (i = 0; i < ndim; i++)
133 {
134 /* PG_USED_FOR_ASSERTS_ONLY prevents variable-isn't-read warnings */
136
137 if (pg_add_s32_overflow(dims[i], lb[i], &sum))
138 ereturn(escontext, false,
139 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
140 errmsg("array lower bound is too large: %d",
141 lb[i])));
142 }
143
144 return true;
145}
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:204
#define ereturn(context, dummy_value,...)
Definition: elog.h:277

References ereturn, errcode(), errmsg(), i, pg_add_s32_overflow(), and PG_USED_FOR_ASSERTS_ONLY.

Referenced by ArrayCheckBounds().

◆ ArrayGetIntegerTypmods()

int32 * ArrayGetIntegerTypmods ( ArrayType arr,
int *  n 
)

Definition at line 233 of file arrayutils.c.

234{
235 int32 *result;
236 Datum *elem_values;
237 int i;
238
239 if (ARR_ELEMTYPE(arr) != CSTRINGOID)
241 (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
242 errmsg("typmod array must be type cstring[]")));
243
244 if (ARR_NDIM(arr) != 1)
246 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
247 errmsg("typmod array must be one-dimensional")));
248
249 if (array_contains_nulls(arr))
251 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
252 errmsg("typmod array must not contain nulls")));
253
254 deconstruct_array_builtin(arr, CSTRINGOID, &elem_values, NULL, n);
255
256 result = (int32 *) palloc(*n * sizeof(int32));
257
258 for (i = 0; i < *n; i++)
259 result[i] = pg_strtoint32(DatumGetCString(elem_values[i]));
260
261 pfree(elem_values);
262
263 return result;
264}
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3767
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3697
int32 pg_strtoint32(const char *s)
Definition: numutils.c:383
static char * DatumGetCString(Datum X)
Definition: postgres.h:340

References ARR_ELEMTYPE, ARR_NDIM, array_contains_nulls(), DatumGetCString(), deconstruct_array_builtin(), ereport, errcode(), errmsg(), ERROR, i, palloc(), pfree(), and pg_strtoint32().

Referenced by anybit_typmodin(), anychar_typmodin(), anytime_typmodin(), anytimestamp_typmodin(), intervaltypmodin(), and numerictypmodin().

◆ ArrayGetNItems()

◆ ArrayGetNItemsSafe()

int ArrayGetNItemsSafe ( int  ndim,
const int *  dims,
struct Node escontext 
)

Definition at line 67 of file arrayutils.c.

68{
69 int32 ret;
70 int i;
71
72 if (ndim <= 0)
73 return 0;
74 ret = 1;
75 for (i = 0; i < ndim; i++)
76 {
77 int64 prod;
78
79 /* A negative dimension implies that UB-LB overflowed ... */
80 if (dims[i] < 0)
81 ereturn(escontext, -1,
82 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
83 errmsg("array size exceeds the maximum allowed (%d)",
84 (int) MaxArraySize)));
85
86 prod = (int64) ret * (int64) dims[i];
87
88 ret = (int32) prod;
89 if ((int64) ret != prod)
90 ereturn(escontext, -1,
91 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
92 errmsg("array size exceeds the maximum allowed (%d)",
93 (int) MaxArraySize)));
94 }
95 Assert(ret >= 0);
96 if ((Size) ret > MaxArraySize)
97 ereturn(escontext, -1,
98 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
99 errmsg("array size exceeds the maximum allowed (%d)",
100 (int) MaxArraySize)));
101 return (int) ret;
102}
int64_t int64
Definition: c.h:485
size_t Size
Definition: c.h:562

References Assert, ereturn, errcode(), errmsg(), i, and MaxArraySize.

Referenced by ArrayGetNItems().

◆ ArrayGetOffset()

int ArrayGetOffset ( int  n,
const int *  dim,
const int *  lb,
const int *  indx 
)

Definition at line 32 of file arrayutils.c.

33{
34 int i,
35 scale = 1,
36 offset = 0;
37
38 for (i = n - 1; i >= 0; i--)
39 {
40 offset += (indx[i] - lb[i]) * scale;
41 scale *= dim[i];
42 }
43 return offset;
44}
static int scale
Definition: pgbench.c:182

References i, and scale.

Referenced by array_extract_slice(), array_get_element(), array_get_element_expanded(), array_insert_slice(), array_set_element(), array_set_element_expanded(), and array_slice_size().

◆ construct_array()

ArrayType * construct_array ( Datum elems,
int  nelems,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 3361 of file arrayfuncs.c.

3364{
3365 int dims[1];
3366 int lbs[1];
3367
3368 dims[0] = nelems;
3369 lbs[0] = 1;
3370
3371 return construct_md_array(elems, NULL, 1, dims, lbs,
3372 elmtype, elmlen, elmbyval, elmalign);
3373}

References construct_md_array().

Referenced by ATExecAlterColumnType(), construct_array_builtin(), enum_range_internal(), match_orclause_to_indexcol(), serialize_expr_stats(), StoreAttrDefault(), and update_attstats().

◆ construct_array_builtin()

ArrayType * construct_array_builtin ( Datum elems,
int  nelems,
Oid  elmtype 
)

Definition at line 3381 of file arrayfuncs.c.

3382{
3383 int elmlen;
3384 bool elmbyval;
3385 char elmalign;
3386
3387 switch (elmtype)
3388 {
3389 case CHAROID:
3390 elmlen = 1;
3391 elmbyval = true;
3392 elmalign = TYPALIGN_CHAR;
3393 break;
3394
3395 case CSTRINGOID:
3396 elmlen = -2;
3397 elmbyval = false;
3398 elmalign = TYPALIGN_CHAR;
3399 break;
3400
3401 case FLOAT4OID:
3402 elmlen = sizeof(float4);
3403 elmbyval = true;
3404 elmalign = TYPALIGN_INT;
3405 break;
3406
3407 case FLOAT8OID:
3408 elmlen = sizeof(float8);
3409 elmbyval = FLOAT8PASSBYVAL;
3410 elmalign = TYPALIGN_DOUBLE;
3411 break;
3412
3413 case INT2OID:
3414 elmlen = sizeof(int16);
3415 elmbyval = true;
3416 elmalign = TYPALIGN_SHORT;
3417 break;
3418
3419 case INT4OID:
3420 elmlen = sizeof(int32);
3421 elmbyval = true;
3422 elmalign = TYPALIGN_INT;
3423 break;
3424
3425 case INT8OID:
3426 elmlen = sizeof(int64);
3427 elmbyval = FLOAT8PASSBYVAL;
3428 elmalign = TYPALIGN_DOUBLE;
3429 break;
3430
3431 case NAMEOID:
3432 elmlen = NAMEDATALEN;
3433 elmbyval = false;
3434 elmalign = TYPALIGN_CHAR;
3435 break;
3436
3437 case OIDOID:
3438 case REGTYPEOID:
3439 elmlen = sizeof(Oid);
3440 elmbyval = true;
3441 elmalign = TYPALIGN_INT;
3442 break;
3443
3444 case TEXTOID:
3445 elmlen = -1;
3446 elmbyval = false;
3447 elmalign = TYPALIGN_INT;
3448 break;
3449
3450 case TIDOID:
3451 elmlen = sizeof(ItemPointerData);
3452 elmbyval = false;
3453 elmalign = TYPALIGN_SHORT;
3454 break;
3455
3456 case XIDOID:
3457 elmlen = sizeof(TransactionId);
3458 elmbyval = true;
3459 elmalign = TYPALIGN_INT;
3460 break;
3461
3462 default:
3463 elog(ERROR, "type %u not supported by construct_array_builtin()", elmtype);
3464 /* keep compiler quiet */
3465 elmlen = 0;
3466 elmbyval = false;
3467 elmalign = 0;
3468 }
3469
3470 return construct_array(elems, nelems, elmtype, elmlen, elmbyval, elmalign);
3471}
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3361
double float8
Definition: c.h:587
int16_t int16
Definition: c.h:483
#define FLOAT8PASSBYVAL
Definition: c.h:592
float float4
Definition: c.h:586
uint32 TransactionId
Definition: c.h:609
struct ItemPointerData ItemPointerData
#define NAMEDATALEN

References construct_array(), elog, ERROR, FLOAT8PASSBYVAL, and NAMEDATALEN.

Referenced by AlterPolicy(), attribute_statistics_update(), bt_page_print_tuples(), build_regtype_array(), convert_requires_to_datum(), CreateConstraintEntry(), CreateFunction(), CreatePolicy(), CreateStatistics(), current_schemas(), executeItemOptUnwrapTarget(), extension_config_remove(), filter_list_to_array(), float4_accum(), float8_accum(), float8_combine(), float8_regr_accum(), float8_regr_combine(), get_environ(), get_hba_options(), GetWALBlockInfo(), gin_leafpage_items(), gin_page_opaque_info(), gist_page_opaque_info(), GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), hash_metapage_info(), heap_tuple_infomask_flags(), hstore_akeys(), int_list_to_array(), interpret_function_parameter_list(), makeMultirangeConstructors(), pg_blocking_pids(), pg_extension_config_dump(), pg_get_logical_snapshot_info(), pg_safe_snapshot_blocking_pids(), pg_settings_get_flags(), publicationListToArray(), RemoveRoleFromObjectPolicy(), serialize_expr_stats(), show_trgm(), test_rls_hooks_permissive(), test_rls_hooks_restrictive(), ts_lexize(), tsvector_to_array(), tsvector_unnest(), typenameTypeMod(), and update_attstats().

◆ construct_empty_array()

◆ construct_empty_expanded_array()

ExpandedArrayHeader * construct_empty_expanded_array ( Oid  element_type,
MemoryContext  parentcontext,
ArrayMetaState metacache 
)

Definition at line 3597 of file arrayfuncs.c.

3600{
3601 ArrayType *array = construct_empty_array(element_type);
3602 Datum d;
3603
3604 d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3605 pfree(array);
3606 return (ExpandedArrayHeader *) DatumGetEOHP(d);
3607}
Datum expand_array(Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29

References construct_empty_array(), DatumGetEOHP(), expand_array(), pfree(), and PointerGetDatum().

Referenced by fetch_array_arg_replace_nulls().

◆ construct_md_array()

ArrayType * construct_md_array ( Datum elems,
bool *  nulls,
int  ndims,
int *  dims,
int *  lbs,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 3494 of file arrayfuncs.c.

3500{
3501 ArrayType *result;
3502 bool hasnulls;
3503 int32 nbytes;
3504 int32 dataoffset;
3505 int i;
3506 int nelems;
3507
3508 if (ndims < 0) /* we do allow zero-dimension arrays */
3509 ereport(ERROR,
3510 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3511 errmsg("invalid number of dimensions: %d", ndims)));
3512 if (ndims > MAXDIM)
3513 ereport(ERROR,
3514 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3515 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
3516 ndims, MAXDIM)));
3517
3518 /* This checks for overflow of the array dimensions */
3519 nelems = ArrayGetNItems(ndims, dims);
3520 ArrayCheckBounds(ndims, dims, lbs);
3521
3522 /* if ndims <= 0 or any dims[i] == 0, return empty array */
3523 if (nelems <= 0)
3524 return construct_empty_array(elmtype);
3525
3526 /* compute required space */
3527 nbytes = 0;
3528 hasnulls = false;
3529 for (i = 0; i < nelems; i++)
3530 {
3531 if (nulls && nulls[i])
3532 {
3533 hasnulls = true;
3534 continue;
3535 }
3536 /* make sure data is not toasted */
3537 if (elmlen == -1)
3538 elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i]));
3539 nbytes = att_addlength_datum(nbytes, elmlen, elems[i]);
3540 nbytes = att_align_nominal(nbytes, elmalign);
3541 /* check for overflow of total request */
3542 if (!AllocSizeIsValid(nbytes))
3543 ereport(ERROR,
3544 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3545 errmsg("array size exceeds the maximum allowed (%d)",
3546 (int) MaxAllocSize)));
3547 }
3548
3549 /* Allocate and initialize result array */
3550 if (hasnulls)
3551 {
3552 dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nelems);
3553 nbytes += dataoffset;
3554 }
3555 else
3556 {
3557 dataoffset = 0; /* marker for no null bitmap */
3558 nbytes += ARR_OVERHEAD_NONULLS(ndims);
3559 }
3560 result = (ArrayType *) palloc0(nbytes);
3561 SET_VARSIZE(result, nbytes);
3562 result->ndim = ndims;
3563 result->dataoffset = dataoffset;
3564 result->elemtype = elmtype;
3565 memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
3566 memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
3567
3568 CopyArrayEls(result,
3569 elems, nulls, nelems,
3570 elmlen, elmbyval, elmalign,
3571 false);
3572
3573 return result;
3574}

References AllocSizeIsValid, ARR_DIMS, ARR_LBOUND, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ArrayCheckBounds(), ArrayGetNItems(), att_addlength_datum, att_align_nominal, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, MaxAllocSize, MAXDIM, ArrayType::ndim, palloc0(), PG_DETOAST_DATUM, PointerGetDatum(), and SET_VARSIZE.

Referenced by array_iterate(), array_reverse_n(), array_set_element(), array_set_slice(), array_shuffle_n(), build_regexp_match_result(), build_test_info_result(), build_test_match_result(), construct_array(), ExecEvalArrayExpr(), hstore_avals(), hstore_slice_to_array(), hstore_to_array_internal(), makeMdArrayResult(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), plpgsql_fulfill_promise(), and strlist_to_textarray().

◆ CopyArrayEls()

void CopyArrayEls ( ArrayType array,
Datum values,
bool *  nulls,
int  nitems,
int  typlen,
bool  typbyval,
char  typalign,
bool  freedata 
)

Definition at line 961 of file arrayfuncs.c.

969{
970 char *p = ARR_DATA_PTR(array);
971 bits8 *bitmap = ARR_NULLBITMAP(array);
972 int bitval = 0;
973 int bitmask = 1;
974 int i;
975
976 if (typbyval)
977 freedata = false;
978
979 for (i = 0; i < nitems; i++)
980 {
981 if (nulls && nulls[i])
982 {
983 if (!bitmap) /* shouldn't happen */
984 elog(ERROR, "null array element where not supported");
985 /* bitmap bit stays 0 */
986 }
987 else
988 {
989 bitval |= bitmask;
990 p += ArrayCastAndSet(values[i], typlen, typbyval, typalign, p);
991 if (freedata)
993 }
994 if (bitmap)
995 {
996 bitmask <<= 1;
997 if (bitmask == 0x100)
998 {
999 *bitmap++ = bitval;
1000 bitval = 0;
1001 bitmask = 1;
1002 }
1003 }
1004 }
1005
1006 if (bitmap && bitmask != 1)
1007 *bitmap = bitval;
1008}

References ARR_DATA_PTR, ARR_NULLBITMAP, ArrayCastAndSet(), DatumGetPointer(), elog, ERROR, i, nitems, pfree(), typalign, and values.

Referenced by array_in(), array_map(), array_recv(), array_replace_internal(), construct_md_array(), and EA_flatten_into().

◆ DatumGetAnyArrayP()

AnyArrayType * DatumGetAnyArrayP ( Datum  d)

Definition at line 401 of file array_expanded.c.

402{
404
405 /*
406 * If it's an expanded array (RW or RO), return the header pointer.
407 */
409 {
411 Assert(eah->ea_magic == EA_MAGIC);
412 return (AnyArrayType *) eah;
413 }
414
415 /* Else do regular detoasting as needed */
416 return (AnyArrayType *) PG_DETOAST_DATUM(d);
417}
#define EA_MAGIC
Definition: array.h:113

References Assert, DatumGetEOHP(), DatumGetPointer(), EA_MAGIC, ExpandedArrayHeader::ea_magic, PG_DETOAST_DATUM, and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by array_map().

◆ DatumGetExpandedArray()

ExpandedArrayHeader * DatumGetExpandedArray ( Datum  d)

Definition at line 352 of file array_expanded.c.

353{
354 /* If it's a writable expanded array already, just return it */
356 {
358
359 Assert(eah->ea_magic == EA_MAGIC);
360 return eah;
361 }
362
363 /* Else expand the hard way */
365 return (ExpandedArrayHeader *) DatumGetEOHP(d);
366}
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR)
Definition: varatt.h:296

References Assert, CurrentMemoryContext, DatumGetEOHP(), DatumGetPointer(), EA_MAGIC, ExpandedArrayHeader::ea_magic, expand_array(), and VARATT_IS_EXTERNAL_EXPANDED_RW.

Referenced by array_set_element_expanded(), and statext_expressions_load().

◆ DatumGetExpandedArrayX()

ExpandedArrayHeader * DatumGetExpandedArrayX ( Datum  d,
ArrayMetaState metacache 
)

Definition at line 372 of file array_expanded.c.

373{
374 /* If it's a writable expanded array already, just return it */
376 {
378
379 Assert(eah->ea_magic == EA_MAGIC);
380 /* Update cache if provided */
381 if (metacache)
382 {
383 metacache->element_type = eah->element_type;
384 metacache->typlen = eah->typlen;
385 metacache->typbyval = eah->typbyval;
386 metacache->typalign = eah->typalign;
387 }
388 return eah;
389 }
390
391 /* Else expand using caller's cache if any */
392 d = expand_array(d, CurrentMemoryContext, metacache);
393 return (ExpandedArrayHeader *) DatumGetEOHP(d);
394}

References Assert, CurrentMemoryContext, DatumGetEOHP(), DatumGetPointer(), EA_MAGIC, ExpandedArrayHeader::ea_magic, ExpandedArrayHeader::element_type, ArrayMetaState::element_type, expand_array(), ExpandedArrayHeader::typalign, ArrayMetaState::typalign, ExpandedArrayHeader::typbyval, ArrayMetaState::typbyval, ExpandedArrayHeader::typlen, ArrayMetaState::typlen, and VARATT_IS_EXTERNAL_EXPANDED_RW.

◆ deconstruct_array()

void deconstruct_array ( ArrayType array,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign,
Datum **  elemsp,
bool **  nullsp,
int *  nelemsp 
)

Definition at line 3631 of file arrayfuncs.c.

3635{
3636 Datum *elems;
3637 bool *nulls;
3638 int nelems;
3639 char *p;
3640 bits8 *bitmap;
3641 int bitmask;
3642 int i;
3643
3644 Assert(ARR_ELEMTYPE(array) == elmtype);
3645
3646 nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3647 *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
3648 if (nullsp)
3649 *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
3650 else
3651 nulls = NULL;
3652 *nelemsp = nelems;
3653
3654 p = ARR_DATA_PTR(array);
3655 bitmap = ARR_NULLBITMAP(array);
3656 bitmask = 1;
3657
3658 for (i = 0; i < nelems; i++)
3659 {
3660 /* Get source element, checking for NULL */
3661 if (bitmap && (*bitmap & bitmask) == 0)
3662 {
3663 elems[i] = (Datum) 0;
3664 if (nulls)
3665 nulls[i] = true;
3666 else
3667 ereport(ERROR,
3668 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3669 errmsg("null array element not allowed in this context")));
3670 }
3671 else
3672 {
3673 elems[i] = fetch_att(p, elmbyval, elmlen);
3674 p = att_addlength_pointer(p, elmlen, p);
3675 p = (char *) att_align_nominal(p, elmalign);
3676 }
3677
3678 /* advance bitmap pointer if any */
3679 if (bitmap)
3680 {
3681 bitmask <<= 1;
3682 if (bitmask == 0x100)
3683 {
3684 bitmap++;
3685 bitmask = 1;
3686 }
3687 }
3688 }
3689}

References ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), Assert, att_addlength_pointer, att_align_nominal, ereport, errcode(), errmsg(), ERROR, fetch_att(), i, palloc(), and palloc0().

Referenced by _bt_preprocess_array_keys(), array_contain_compare(), array_reverse_n(), array_set_slice(), array_shuffle_n(), array_to_json_internal(), array_to_jsonb_internal(), arrayconst_startup_fn(), compute_array_stats(), deconstruct_array_builtin(), deconstruct_expanded_array(), ExecIndexEvalArrayKeys(), extract_variadic_args(), get_attstatsslot(), ginarrayextract(), gincost_scalararrayopexpr(), ginqueryarrayextract(), map_sql_value_to_xml_value(), match_clause_to_partition_key(), mcelem_array_selec(), mcv_get_match_bitmap(), multirange_constructor2(), plperl_ref_from_pg_array(), satisfies_hash_partition(), scalararraysel(), and text_format().

◆ deconstruct_array_builtin()

void deconstruct_array_builtin ( ArrayType array,
Oid  elmtype,
Datum **  elemsp,
bool **  nullsp,
int *  nelemsp 
)

Definition at line 3697 of file arrayfuncs.c.

3700{
3701 int elmlen;
3702 bool elmbyval;
3703 char elmalign;
3704
3705 switch (elmtype)
3706 {
3707 case CHAROID:
3708 elmlen = 1;
3709 elmbyval = true;
3710 elmalign = TYPALIGN_CHAR;
3711 break;
3712
3713 case CSTRINGOID:
3714 elmlen = -2;
3715 elmbyval = false;
3716 elmalign = TYPALIGN_CHAR;
3717 break;
3718
3719 case FLOAT8OID:
3720 elmlen = sizeof(float8);
3721 elmbyval = FLOAT8PASSBYVAL;
3722 elmalign = TYPALIGN_DOUBLE;
3723 break;
3724
3725 case INT2OID:
3726 elmlen = sizeof(int16);
3727 elmbyval = true;
3728 elmalign = TYPALIGN_SHORT;
3729 break;
3730
3731 case OIDOID:
3732 elmlen = sizeof(Oid);
3733 elmbyval = true;
3734 elmalign = TYPALIGN_INT;
3735 break;
3736
3737 case TEXTOID:
3738 elmlen = -1;
3739 elmbyval = false;
3740 elmalign = TYPALIGN_INT;
3741 break;
3742
3743 case TIDOID:
3744 elmlen = sizeof(ItemPointerData);
3745 elmbyval = false;
3746 elmalign = TYPALIGN_SHORT;
3747 break;
3748
3749 default:
3750 elog(ERROR, "type %u not supported by deconstruct_array_builtin()", elmtype);
3751 /* keep compiler quiet */
3752 elmlen = 0;
3753 elmbyval = false;
3754 elmalign = 0;
3755 }
3756
3757 deconstruct_array(array, elmtype, elmlen, elmbyval, elmalign, elemsp, nullsp, nelemsp);
3758}

References deconstruct_array(), elog, ERROR, and FLOAT8PASSBYVAL.

Referenced by array_to_tsvector(), ArrayGetIntegerTypmods(), binary_upgrade_create_empty_extension(), build_function_result_tupdesc_d(), DecodeTextArrayToBitmapset(), decompile_column_index_array(), extension_config_remove(), generateClonedIndexStmt(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_jsonb_path_all(), get_path_all(), get_reloptions(), ghstore_consistent(), gin_extract_hstore_query(), gin_extract_jsonb_query(), hstore_from_array(), hstore_from_arrays(), hstore_slice_to_array(), hstoreArrayToPairs(), json_object(), json_object_two_arg(), jsonb_delete_array(), jsonb_delete_path(), jsonb_exists_all(), jsonb_exists_any(), jsonb_insert(), jsonb_object(), jsonb_object_two_arg(), jsonb_set(), oid_array_to_list(), parse_key_value_arrays(), parseRelOptionsInternal(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), pg_get_constraintdef_worker(), pg_get_object_address(), pg_get_publication_tables(), pg_logical_slot_get_changes_guts(), textarray_to_stringlist(), textarray_to_strvaluelist(), TidListEval(), transformRelOptions(), tsvector_delete_arr(), tsvector_filter(), tsvector_setweight_by_filter(), untransformRelOptions(), and worker_spi_launch().

◆ deconstruct_expanded_array()

void deconstruct_expanded_array ( ExpandedArrayHeader eah)

Definition at line 424 of file array_expanded.c.

425{
426 if (eah->dvalues == NULL)
427 {
429 Datum *dvalues;
430 bool *dnulls;
431 int nelems;
432
433 dnulls = NULL;
435 eah->element_type,
436 eah->typlen, eah->typbyval, eah->typalign,
437 &dvalues,
438 ARR_HASNULL(eah->fvalue) ? &dnulls : NULL,
439 &nelems);
440
441 /*
442 * Update header only after successful completion of this step. If
443 * deconstruct_array fails partway through, worst consequence is some
444 * leaked memory in the object's context. If the caller fails at a
445 * later point, that's fine, since the deconstructed representation is
446 * valid anyhow.
447 */
448 eah->dvalues = dvalues;
449 eah->dnulls = dnulls;
450 eah->dvalueslen = eah->nelems = nelems;
451 MemoryContextSwitchTo(oldcxt);
452 }
453}
ExpandedObjectHeader hdr
Definition: array.h:118
Datum * dvalues
Definition: array.h:146
ArrayType * fvalue
Definition: array.h:165
MemoryContext eoh_context

References ARR_HASNULL, deconstruct_array(), ExpandedArrayHeader::dnulls, ExpandedArrayHeader::dvalues, ExpandedArrayHeader::dvalueslen, ExpandedArrayHeader::element_type, ExpandedObjectHeader::eoh_context, ExpandedArrayHeader::fvalue, ExpandedArrayHeader::hdr, MemoryContextSwitchTo(), ExpandedArrayHeader::nelems, ExpandedArrayHeader::typalign, ExpandedArrayHeader::typbyval, and ExpandedArrayHeader::typlen.

Referenced by array_contain_compare(), array_get_element_expanded(), array_set_element_expanded(), and statext_expressions_load().

◆ expand_array()

Datum expand_array ( Datum  arraydatum,
MemoryContext  parentcontext,
ArrayMetaState metacache 
)

Definition at line 50 of file array_expanded.c.

52{
53 ArrayType *array;
55 MemoryContext objcxt;
56 MemoryContext oldcxt;
57 ArrayMetaState fakecache;
58
59 /*
60 * Allocate private context for expanded object. We start by assuming
61 * that the array won't be very large; but if it does grow a lot, don't
62 * constrain aset.c's large-context behavior.
63 */
64 objcxt = AllocSetContextCreate(parentcontext,
65 "expanded array",
67
68 /* Set up expanded array header */
69 eah = (ExpandedArrayHeader *)
71
72 EOH_init_header(&eah->hdr, &EA_methods, objcxt);
73 eah->ea_magic = EA_MAGIC;
74
75 /* If the source is an expanded array, we may be able to optimize */
77 {
79
80 Assert(oldeah->ea_magic == EA_MAGIC);
81
82 /*
83 * Update caller's cache if provided; we don't need it this time, but
84 * next call might be for a non-expanded source array. Furthermore,
85 * if the caller didn't provide a cache area, use some local storage
86 * to cache anyway, thereby avoiding a catalog lookup in the case
87 * where we fall through to the flat-copy code path.
88 */
89 if (metacache == NULL)
90 metacache = &fakecache;
91 metacache->element_type = oldeah->element_type;
92 metacache->typlen = oldeah->typlen;
93 metacache->typbyval = oldeah->typbyval;
94 metacache->typalign = oldeah->typalign;
95
96 /*
97 * If element type is pass-by-value and we have a Datum-array
98 * representation, just copy the source's metadata and Datum/isnull
99 * arrays. The original flat array, if present at all, adds no
100 * additional information so we need not copy it.
101 */
102 if (oldeah->typbyval && oldeah->dvalues != NULL)
103 {
104 copy_byval_expanded_array(eah, oldeah);
105 /* return a R/W pointer to the expanded array */
106 return EOHPGetRWDatum(&eah->hdr);
107 }
108
109 /*
110 * Otherwise, either we have only a flat representation or the
111 * elements are pass-by-reference. In either case, the best thing
112 * seems to be to copy the source as a flat representation and then
113 * deconstruct that later if necessary. For the pass-by-ref case, we
114 * could perhaps save some cycles with custom code that generates the
115 * deconstructed representation in parallel with copying the values,
116 * but it would be a lot of extra code for fairly marginal gain. So,
117 * fall through into the flat-source code path.
118 */
119 }
120
121 /*
122 * Detoast and copy source array into private context, as a flat array.
123 *
124 * Note that this coding risks leaking some memory in the private context
125 * if we have to fetch data from a TOAST table; however, experimentation
126 * says that the leak is minimal. Doing it this way saves a copy step,
127 * which seems worthwhile, especially if the array is large enough to need
128 * external storage.
129 */
130 oldcxt = MemoryContextSwitchTo(objcxt);
131 array = DatumGetArrayTypePCopy(arraydatum);
132 MemoryContextSwitchTo(oldcxt);
133
134 eah->ndims = ARR_NDIM(array);
135 /* note these pointers point into the fvalue header! */
136 eah->dims = ARR_DIMS(array);
137 eah->lbound = ARR_LBOUND(array);
138
139 /* Save array's element-type data for possible use later */
140 eah->element_type = ARR_ELEMTYPE(array);
141 if (metacache && metacache->element_type == eah->element_type)
142 {
143 /* We have a valid cache of representational data */
144 eah->typlen = metacache->typlen;
145 eah->typbyval = metacache->typbyval;
146 eah->typalign = metacache->typalign;
147 }
148 else
149 {
150 /* No, so look it up */
152 &eah->typlen,
153 &eah->typbyval,
154 &eah->typalign);
155 /* Update cache if provided */
156 if (metacache)
157 {
158 metacache->element_type = eah->element_type;
159 metacache->typlen = eah->typlen;
160 metacache->typbyval = eah->typbyval;
161 metacache->typalign = eah->typalign;
162 }
163 }
164
165 /* we don't make a deconstructed representation now */
166 eah->dvalues = NULL;
167 eah->dnulls = NULL;
168 eah->dvalueslen = 0;
169 eah->nelems = 0;
170 eah->flat_size = 0;
171
172 /* remember we have a flat representation */
173 eah->fvalue = array;
174 eah->fstartptr = ARR_DATA_PTR(array);
175 eah->fendptr = ((char *) array) + ARR_SIZE(array);
176
177 /* return a R/W pointer to the expanded array */
178 return EOHPGetRWDatum(&eah->hdr);
179}
#define DatumGetArrayTypePCopy(X)
Definition: array.h:262
static void copy_byval_expanded_array(ExpandedArrayHeader *eah, ExpandedArrayHeader *oldeah)
static const ExpandedObjectMethods EA_methods
void EOH_init_header(ExpandedObjectHeader *eohptr, const ExpandedObjectMethods *methods, MemoryContext obj_context)
Definition: expandeddatum.c:48
static Datum EOHPGetRWDatum(const struct ExpandedObjectHeader *eohptr)
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:177
char * fstartptr
Definition: array.h:166
char * fendptr
Definition: array.h:167

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, ARR_SIZE, Assert, copy_byval_expanded_array(), DatumGetArrayTypePCopy, DatumGetEOHP(), DatumGetPointer(), ExpandedArrayHeader::dims, ExpandedArrayHeader::dnulls, ExpandedArrayHeader::dvalues, ExpandedArrayHeader::dvalueslen, EA_MAGIC, ExpandedArrayHeader::ea_magic, EA_methods, ExpandedArrayHeader::element_type, ArrayMetaState::element_type, EOH_init_header(), EOHPGetRWDatum(), ExpandedArrayHeader::fendptr, ExpandedArrayHeader::flat_size, ExpandedArrayHeader::fstartptr, ExpandedArrayHeader::fvalue, get_typlenbyvalalign(), ExpandedArrayHeader::hdr, ExpandedArrayHeader::lbound, MemoryContextAlloc(), MemoryContextSwitchTo(), ExpandedArrayHeader::ndims, ExpandedArrayHeader::nelems, ExpandedArrayHeader::typalign, ArrayMetaState::typalign, ExpandedArrayHeader::typbyval, ArrayMetaState::typbyval, ExpandedArrayHeader::typlen, ArrayMetaState::typlen, and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by construct_empty_expanded_array(), DatumGetExpandedArray(), DatumGetExpandedArrayX(), exec_assign_value(), and plpgsql_exec_function().

◆ initArrayResult()

ArrayBuildState * initArrayResult ( Oid  element_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 5293 of file arrayfuncs.c.

5294{
5295 /*
5296 * When using a subcontext, we can afford to start with a somewhat larger
5297 * initial array size. Without subcontexts, we'd better hope that most of
5298 * the states stay small ...
5299 */
5300 return initArrayResultWithSize(element_type, rcontext, subcontext,
5301 subcontext ? 64 : 8);
5302}
ArrayBuildState * initArrayResultWithSize(Oid element_type, MemoryContext rcontext, bool subcontext, int initsize)
Definition: arrayfuncs.c:5310

References initArrayResultWithSize().

Referenced by accumArrayResult(), array_agg_transfn(), array_positions(), array_to_datum_internal(), daitch_mokotoff(), initArrayResultAny(), multirange_agg_transfn(), PLySequence_ToArray_recurse(), populate_array(), range_agg_transfn(), tuple_data_split_internal(), and xpath().

◆ initArrayResultAny()

ArrayBuildStateAny * initArrayResultAny ( Oid  input_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 5782 of file arrayfuncs.c.

5783{
5784 ArrayBuildStateAny *astate;
5785 Oid element_type = get_element_type(input_type);
5786
5787 if (OidIsValid(element_type))
5788 {
5789 /* Array case */
5790 ArrayBuildStateArr *arraystate;
5791
5792 arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5793 astate = (ArrayBuildStateAny *)
5794 MemoryContextAlloc(arraystate->mcontext,
5795 sizeof(ArrayBuildStateAny));
5796 astate->scalarstate = NULL;
5797 astate->arraystate = arraystate;
5798 }
5799 else
5800 {
5801 /* Scalar case */
5802 ArrayBuildState *scalarstate;
5803
5804 /* Let's just check that we have a type that can be put into arrays */
5805 Assert(OidIsValid(get_array_type(input_type)));
5806
5807 scalarstate = initArrayResult(input_type, rcontext, subcontext);
5808 astate = (ArrayBuildStateAny *)
5809 MemoryContextAlloc(scalarstate->mcontext,
5810 sizeof(ArrayBuildStateAny));
5811 astate->scalarstate = scalarstate;
5812 astate->arraystate = NULL;
5813 }
5814
5815 return astate;
5816}
#define OidIsValid(objectId)
Definition: c.h:732
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2786
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2814

References ArrayBuildStateAny::arraystate, Assert, get_array_type(), get_element_type(), initArrayResult(), initArrayResultArr(), InvalidOid, ArrayBuildState::mcontext, ArrayBuildStateArr::mcontext, MemoryContextAlloc(), OidIsValid, and ArrayBuildStateAny::scalarstate.

Referenced by accumArrayResultAny(), ExecScanSubPlan(), and ExecSetParamPlan().

◆ initArrayResultArr()

ArrayBuildStateArr * initArrayResultArr ( Oid  array_type,
Oid  element_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 5504 of file arrayfuncs.c.

5506{
5507 ArrayBuildStateArr *astate;
5508 MemoryContext arr_context = rcontext; /* by default use the parent ctx */
5509
5510 /* Lookup element type, unless element_type already provided */
5511 if (!OidIsValid(element_type))
5512 {
5513 element_type = get_element_type(array_type);
5514
5515 if (!OidIsValid(element_type))
5516 ereport(ERROR,
5517 (errcode(ERRCODE_DATATYPE_MISMATCH),
5518 errmsg("data type %s is not an array type",
5519 format_type_be(array_type))));
5520 }
5521
5522 /* Make a temporary context to hold all the junk */
5523 if (subcontext)
5524 arr_context = AllocSetContextCreate(rcontext,
5525 "accumArrayResultArr",
5527
5528 /* Note we initialize all fields to zero */
5529 astate = (ArrayBuildStateArr *)
5530 MemoryContextAllocZero(arr_context, sizeof(ArrayBuildStateArr));
5531 astate->mcontext = arr_context;
5532 astate->private_cxt = subcontext;
5533
5534 /* Save relevant datatype information */
5535 astate->array_type = array_type;
5536 astate->element_type = element_type;
5537
5538 return astate;
5539}
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1215
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
bool private_cxt
Definition: array.h:219

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ArrayBuildStateArr::array_type, ArrayBuildStateArr::element_type, ereport, errcode(), errmsg(), ERROR, format_type_be(), get_element_type(), ArrayBuildStateArr::mcontext, MemoryContextAllocZero(), OidIsValid, and ArrayBuildStateArr::private_cxt.

Referenced by accumArrayResultArr(), array_agg_array_combine(), array_agg_array_deserialize(), array_agg_array_transfn(), and initArrayResultAny().

◆ initArrayResultWithSize()

ArrayBuildState * initArrayResultWithSize ( Oid  element_type,
MemoryContext  rcontext,
bool  subcontext,
int  initsize 
)

Definition at line 5310 of file arrayfuncs.c.

5312{
5313 ArrayBuildState *astate;
5314 MemoryContext arr_context = rcontext;
5315
5316 /* Make a temporary context to hold all the junk */
5317 if (subcontext)
5318 arr_context = AllocSetContextCreate(rcontext,
5319 "accumArrayResult",
5321
5322 astate = (ArrayBuildState *)
5323 MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
5324 astate->mcontext = arr_context;
5325 astate->private_cxt = subcontext;
5326 astate->alen = initsize;
5327 astate->dvalues = (Datum *)
5328 MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
5329 astate->dnulls = (bool *)
5330 MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
5331 astate->nelems = 0;
5332 astate->element_type = element_type;
5333 get_typlenbyvalalign(element_type,
5334 &astate->typlen,
5335 &astate->typbyval,
5336 &astate->typalign);
5337
5338 return astate;
5339}
bool private_cxt
Definition: array.h:198
char typalign
Definition: array.h:197

References ArrayBuildState::alen, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ArrayBuildState::dnulls, ArrayBuildState::dvalues, ArrayBuildState::element_type, get_typlenbyvalalign(), ArrayBuildState::mcontext, MemoryContextAlloc(), ArrayBuildState::nelems, ArrayBuildState::private_cxt, ArrayBuildState::typalign, ArrayBuildState::typbyval, and ArrayBuildState::typlen.

Referenced by array_agg_combine(), array_agg_deserialize(), and initArrayResult().

◆ makeArrayResult()

Datum makeArrayResult ( ArrayBuildState astate,
MemoryContext  rcontext 
)

Definition at line 5420 of file arrayfuncs.c.

5422{
5423 int ndims;
5424 int dims[1];
5425 int lbs[1];
5426
5427 /* If no elements were presented, we want to create an empty array */
5428 ndims = (astate->nelems > 0) ? 1 : 0;
5429 dims[0] = astate->nelems;
5430 lbs[0] = 1;
5431
5432 return makeMdArrayResult(astate, ndims, dims, lbs, rcontext,
5433 astate->private_cxt);
5434}
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5452

References makeMdArrayResult(), ArrayBuildState::nelems, and ArrayBuildState::private_cxt.

Referenced by array_positions(), brin_minmax_multi_summary_out(), daitch_mokotoff(), dblink_get_connections(), optionListToArray(), parse_ident(), pg_get_statisticsobjdef_expressions(), pg_stats_ext_mcvlist_items(), regexp_split_to_array(), serialize_expr_stats(), text_to_array(), transformRelOptions(), tuple_data_split_internal(), and xpath().

◆ makeArrayResultAny()

Datum makeArrayResultAny ( ArrayBuildStateAny astate,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5855 of file arrayfuncs.c.

5857{
5858 Datum result;
5859
5860 if (astate->scalarstate)
5861 {
5862 /* Must use makeMdArrayResult to support "release" parameter */
5863 int ndims;
5864 int dims[1];
5865 int lbs[1];
5866
5867 /* If no elements were presented, we want to create an empty array */
5868 ndims = (astate->scalarstate->nelems > 0) ? 1 : 0;
5869 dims[0] = astate->scalarstate->nelems;
5870 lbs[0] = 1;
5871
5872 result = makeMdArrayResult(astate->scalarstate, ndims, dims, lbs,
5873 rcontext, release);
5874 }
5875 else
5876 {
5877 result = makeArrayResultArr(astate->arraystate,
5878 rcontext, release);
5879 }
5880 return result;
5881}
Datum makeArrayResultArr(ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5703

References ArrayBuildStateAny::arraystate, makeArrayResultArr(), makeMdArrayResult(), ArrayBuildState::nelems, and ArrayBuildStateAny::scalarstate.

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

◆ makeArrayResultArr()

Datum makeArrayResultArr ( ArrayBuildStateArr astate,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5703 of file arrayfuncs.c.

5706{
5707 ArrayType *result;
5708 MemoryContext oldcontext;
5709
5710 /* Build the final array result in rcontext */
5711 oldcontext = MemoryContextSwitchTo(rcontext);
5712
5713 if (astate->ndims == 0)
5714 {
5715 /* No inputs, return empty array */
5716 result = construct_empty_array(astate->element_type);
5717 }
5718 else
5719 {
5720 int dataoffset,
5721 nbytes;
5722
5723 /* Check for overflow of the array dimensions */
5724 (void) ArrayGetNItems(astate->ndims, astate->dims);
5725 ArrayCheckBounds(astate->ndims, astate->dims, astate->lbs);
5726
5727 /* Compute required space */
5728 nbytes = astate->nbytes;
5729 if (astate->nullbitmap != NULL)
5730 {
5731 dataoffset = ARR_OVERHEAD_WITHNULLS(astate->ndims, astate->nitems);
5732 nbytes += dataoffset;
5733 }
5734 else
5735 {
5736 dataoffset = 0;
5737 nbytes += ARR_OVERHEAD_NONULLS(astate->ndims);
5738 }
5739
5740 result = (ArrayType *) palloc0(nbytes);
5741 SET_VARSIZE(result, nbytes);
5742 result->ndim = astate->ndims;
5743 result->dataoffset = dataoffset;
5744 result->elemtype = astate->element_type;
5745
5746 memcpy(ARR_DIMS(result), astate->dims, astate->ndims * sizeof(int));
5747 memcpy(ARR_LBOUND(result), astate->lbs, astate->ndims * sizeof(int));
5748 memcpy(ARR_DATA_PTR(result), astate->data, astate->nbytes);
5749
5750 if (astate->nullbitmap != NULL)
5752 astate->nullbitmap, 0,
5753 astate->nitems);
5754 }
5755
5756 MemoryContextSwitchTo(oldcontext);
5757
5758 /* Clean up all the junk */
5759 if (release)
5760 {
5761 Assert(astate->private_cxt);
5763 }
5764
5765 return PointerGetDatum(result);
5766}
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454

References ARR_DATA_PTR, ARR_DIMS, ARR_LBOUND, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_bitmap_copy(), ArrayCheckBounds(), ArrayGetNItems(), Assert, construct_empty_array(), ArrayBuildStateArr::data, ArrayType::dataoffset, ArrayBuildStateArr::dims, ArrayBuildStateArr::element_type, ArrayType::elemtype, ArrayBuildStateArr::lbs, ArrayBuildStateArr::mcontext, MemoryContextDelete(), MemoryContextSwitchTo(), ArrayBuildStateArr::nbytes, ArrayType::ndim, ArrayBuildStateArr::ndims, ArrayBuildStateArr::nitems, ArrayBuildStateArr::nullbitmap, palloc0(), PointerGetDatum(), ArrayBuildStateArr::private_cxt, and SET_VARSIZE.

Referenced by array_agg_array_finalfn(), and makeArrayResultAny().

◆ makeMdArrayResult()

Datum makeMdArrayResult ( ArrayBuildState astate,
int  ndims,
int *  dims,
int *  lbs,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5452 of file arrayfuncs.c.

5458{
5459 ArrayType *result;
5460 MemoryContext oldcontext;
5461
5462 /* Build the final array result in rcontext */
5463 oldcontext = MemoryContextSwitchTo(rcontext);
5464
5465 result = construct_md_array(astate->dvalues,
5466 astate->dnulls,
5467 ndims,
5468 dims,
5469 lbs,
5470 astate->element_type,
5471 astate->typlen,
5472 astate->typbyval,
5473 astate->typalign);
5474
5475 MemoryContextSwitchTo(oldcontext);
5476
5477 /* Clean up all the junk */
5478 if (release)
5479 {
5480 Assert(astate->private_cxt);
5482 }
5483
5484 return PointerGetDatum(result);
5485}

References Assert, construct_md_array(), ArrayBuildState::dnulls, ArrayBuildState::dvalues, ArrayBuildState::element_type, ArrayBuildState::mcontext, MemoryContextDelete(), MemoryContextSwitchTo(), PointerGetDatum(), ArrayBuildState::private_cxt, ArrayBuildState::typalign, ArrayBuildState::typbyval, and ArrayBuildState::typlen.

Referenced by array_agg_finalfn(), makeArrayResult(), makeArrayResultAny(), plperl_array_to_datum(), PLySequence_ToArray(), and populate_array().

◆ mda_get_offset_values()

void mda_get_offset_values ( int  n,
int *  dist,
const int *  prod,
const int *  span 
)

Definition at line 183 of file arrayutils.c.

184{
185 int i,
186 j;
187
188 dist[n - 1] = 0;
189 for (j = n - 2; j >= 0; j--)
190 {
191 dist[j] = prod[j] - 1;
192 for (i = j + 1; i < n; i++)
193 dist[j] -= (span[i] - 1) * prod[i];
194 }
195}
int j
Definition: isn.c:73

References i, and j.

Referenced by array_extract_slice(), array_insert_slice(), and array_slice_size().

◆ mda_get_prod()

void mda_get_prod ( int  n,
const int *  range,
int *  prod 
)

Definition at line 167 of file arrayutils.c.

168{
169 int i;
170
171 prod[n - 1] = 1;
172 for (i = n - 2; i >= 0; i--)
173 prod[i] = prod[i + 1] * range[i + 1];
174}
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412

References i, and range().

Referenced by array_extract_slice(), array_insert_slice(), and array_slice_size().

◆ mda_get_range()

void mda_get_range ( int  n,
int *  span,
const int *  st,
const int *  endp 
)

Definition at line 153 of file arrayutils.c.

154{
155 int i;
156
157 for (i = 0; i < n; i++)
158 span[i] = endp[i] - st[i] + 1;
159}

References i.

Referenced by array_extract_slice(), array_get_slice(), array_insert_slice(), array_set_slice(), and array_slice_size().

◆ mda_next_tuple()

int mda_next_tuple ( int  n,
int *  curr,
const int *  span 
)

Definition at line 208 of file arrayutils.c.

209{
210 int i;
211
212 if (n <= 0)
213 return -1;
214
215 curr[n - 1] = (curr[n - 1] + 1) % span[n - 1];
216 for (i = n - 1; i && curr[i] == 0; i--)
217 curr[i - 1] = (curr[i - 1] + 1) % span[i - 1];
218
219 if (i)
220 return i;
221 if (curr[0])
222 return 0;
223
224 return -1;
225}

References i.

Referenced by array_extract_slice(), array_insert_slice(), and array_slice_size().

Variable Documentation

◆ Array_nulls

PGDLLIMPORT bool Array_nulls
extern

Definition at line 43 of file arrayfuncs.c.

Referenced by ReadArrayToken().