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 ExprState ExprState
 
typedef struct ExprContext ExprContext
 
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, ExprState *exprstate, 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:73

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:545

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:810
#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

◆ ExprContext

typedef struct ExprContext ExprContext

Definition at line 69 of file array.h.

◆ ExprState

typedef struct ExprState ExprState

Definition at line 68 of file array.h.

Function Documentation

◆ accumArrayResult()

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

Definition at line 5351 of file arrayfuncs.c.

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

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

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

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

◆ accumArrayResultArr()

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

Definition at line 5551 of file arrayfuncs.c.

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

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

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 3768 of file arrayfuncs.c.

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

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 4598 of file arrayfuncs.c.

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

◆ array_free_iterator()

void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4760 of file arrayfuncs.c.

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

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

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

◆ 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 1821 of file arrayfuncs.c.

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

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 2031 of file arrayfuncs.c.

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

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 4677 of file arrayfuncs.c.

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

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(), array_sort_internal(), and exec_stmt_foreach_a().

◆ array_map()

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

Definition at line 3202 of file arrayfuncs.c.

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

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 3147 of file arrayfuncs.c.

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

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 3164 of file arrayfuncs.c.

3167{
3169 nSubscripts, indx,
3170 dataValue, isNull,
3171 arraytyplen,
3172 elmlen, elmbyval, elmalign));
3173}
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:2202

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 2202 of file arrayfuncs.c.

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

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

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:223
#define ereturn(context, dummy_value,...)
Definition: elog.h:278

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:3768
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3698
int32 pg_strtoint32(const char *s)
Definition: numutils.c:383
static char * DatumGetCString(Datum X)
Definition: postgres.h:345

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:535
size_t Size
Definition: c.h:610

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 3362 of file arrayfuncs.c.

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

References construct_md_array().

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

◆ construct_array_builtin()

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

Definition at line 3382 of file arrayfuncs.c.

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

References construct_array(), elog, ERROR, 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 3598 of file arrayfuncs.c.

3601{
3602 ArrayType *array = construct_empty_array(element_type);
3603 Datum d;
3604
3605 d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3606 pfree(array);
3607 return (ExpandedArrayHeader *) DatumGetEOHP(d);
3608}
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 3495 of file arrayfuncs.c.

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

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(), make_SAOP_expr(), 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 962 of file arrayfuncs.c.

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

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:160
static bool VARATT_IS_EXTERNAL_EXPANDED_RW(const void *PTR)
Definition: varatt.h:382

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 3632 of file arrayfuncs.c.

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

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(), test_bms_overlap_list(), and text_format().

◆ deconstruct_array_builtin()

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

Definition at line 3698 of file arrayfuncs.c.

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

References deconstruct_array(), elog, and ERROR.

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:1229
#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 5294 of file arrayfuncs.c.

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

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 5783 of file arrayfuncs.c.

5784{
5785 ArrayBuildStateAny *astate;
5786
5787 /*
5788 * int2vector and oidvector will satisfy both get_element_type and
5789 * get_array_type. We prefer to treat them as scalars, to be consistent
5790 * with get_promoted_array_type. Hence, check get_array_type not
5791 * get_element_type.
5792 */
5793 if (!OidIsValid(get_array_type(input_type)))
5794 {
5795 /* Array case */
5796 ArrayBuildStateArr *arraystate;
5797
5798 arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5799 astate = (ArrayBuildStateAny *)
5800 MemoryContextAlloc(arraystate->mcontext,
5801 sizeof(ArrayBuildStateAny));
5802 astate->scalarstate = NULL;
5803 astate->arraystate = arraystate;
5804 }
5805 else
5806 {
5807 /* Scalar case */
5808 ArrayBuildState *scalarstate;
5809
5810 scalarstate = initArrayResult(input_type, rcontext, subcontext);
5811 astate = (ArrayBuildStateAny *)
5812 MemoryContextAlloc(scalarstate->mcontext,
5813 sizeof(ArrayBuildStateAny));
5814 astate->scalarstate = scalarstate;
5815 astate->arraystate = NULL;
5816 }
5817
5818 return astate;
5819}
#define OidIsValid(objectId)
Definition: c.h:774
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2954

References ArrayBuildStateAny::arraystate, get_array_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 5505 of file arrayfuncs.c.

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

5313{
5314 ArrayBuildState *astate;
5315 MemoryContext arr_context = rcontext;
5316
5317 /* Make a temporary context to hold all the junk */
5318 if (subcontext)
5319 arr_context = AllocSetContextCreate(rcontext,
5320 "accumArrayResult",
5322
5323 astate = (ArrayBuildState *)
5324 MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
5325 astate->mcontext = arr_context;
5326 astate->private_cxt = subcontext;
5327 astate->alen = initsize;
5328 astate->dvalues = (Datum *)
5329 MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
5330 astate->dnulls = (bool *)
5331 MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
5332 astate->nelems = 0;
5333 astate->element_type = element_type;
5334 get_typlenbyvalalign(element_type,
5335 &astate->typlen,
5336 &astate->typbyval,
5337 &astate->typalign);
5338
5339 return astate;
5340}
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 5421 of file arrayfuncs.c.

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

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 5858 of file arrayfuncs.c.

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

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

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

◆ makeArrayResultArr()

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

Definition at line 5704 of file arrayfuncs.c.

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

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 5453 of file arrayfuncs.c.

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

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:78

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 44 of file arrayfuncs.c.

Referenced by ReadArrayToken().