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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Functions

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

Variables

PGDLLIMPORT bool Array_nulls
 

Macro Definition Documentation

◆ AARR_DIMS

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

Definition at line 338 of file array.h.

◆ AARR_ELEMTYPE

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

Definition at line 335 of file array.h.

◆ AARR_HASNULL

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

Definition at line 331 of file array.h.

◆ AARR_LBOUND

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

Definition at line 341 of file array.h.

◆ AARR_NDIM

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

Definition at line 328 of file array.h.

◆ ARR_DATA_OFFSET

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

Definition at line 316 of file array.h.

◆ ARR_DATA_PTR

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

Definition at line 322 of file array.h.

◆ ARR_DIMS

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

Definition at line 294 of file array.h.

◆ ARR_ELEMTYPE

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

Definition at line 292 of file array.h.

◆ ARR_HASNULL

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

Definition at line 291 of file array.h.

◆ ARR_LBOUND

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

Definition at line 296 of file array.h.

◆ ARR_NDIM

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

Definition at line 290 of file array.h.

◆ ARR_NULLBITMAP

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

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:765
#define nitems(x)
Definition: indent.h:31

Definition at line 312 of file array.h.

◆ ARR_SIZE

#define ARR_SIZE (   a)    VARSIZE(a)

Definition at line 289 of file array.h.

◆ DatumGetArrayTypeP

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

Definition at line 261 of file array.h.

◆ DatumGetArrayTypePCopy

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

Definition at line 262 of file array.h.

◆ EA_MAGIC

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

Definition at line 113 of file array.h.

◆ MaxArraySize

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

Definition at line 82 of file array.h.

◆ MAXDIM

#define MAXDIM   6

Definition at line 75 of file array.h.

◆ PG_GETARG_ANY_ARRAY_P

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

Definition at line 274 of file array.h.

◆ PG_GETARG_ARRAYTYPE_P

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

Definition at line 263 of file array.h.

◆ PG_GETARG_ARRAYTYPE_P_COPY

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

Definition at line 264 of file array.h.

◆ PG_GETARG_EXPANDED_ARRAY

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

Definition at line 268 of file array.h.

◆ PG_GETARG_EXPANDED_ARRAYX

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

Definition at line 269 of file array.h.

◆ PG_RETURN_ARRAYTYPE_P

#define PG_RETURN_ARRAYTYPE_P (   x)    PG_RETURN_POINTER(x)

Definition at line 265 of file array.h.

◆ PG_RETURN_EXPANDED_ARRAY

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

Definition at line 271 of file array.h.

Typedef Documentation

◆ AnyArrayType

typedef union AnyArrayType AnyArrayType

◆ ArrayBuildState

◆ ArrayBuildStateAny

◆ ArrayBuildStateArr

◆ ArrayIterator

Definition at line 258 of file array.h.

◆ ArrayMapState

typedef struct ArrayMapState ArrayMapState

◆ ArrayMetaState

◆ ArrayType

typedef struct ArrayType ArrayType

◆ ExpandedArrayHeader

Function Documentation

◆ accumArrayResult()

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

Definition at line 5350 of file arrayfuncs.c.

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

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

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

◆ accumArrayResultAny()

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

Definition at line 5827 of file arrayfuncs.c.

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

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

◆ accumArrayResultArr()

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

Definition at line 5550 of file arrayfuncs.c.

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

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

Referenced by accumArrayResultAny(), and array_agg_array_transfn().

◆ array_bitmap_copy()

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

Definition at line 4966 of file arrayfuncs.c.

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

References Assert, and nitems.

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

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

Definition at line 3767 of file arrayfuncs.c.

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

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

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

◆ array_create_iterator()

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

Definition at line 4597 of file arrayfuncs.c.

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

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

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

◆ array_free_iterator()

void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4759 of file arrayfuncs.c.

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

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

Referenced by array_position_common(), and array_positions().

◆ array_get_element()

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

Definition at line 1820 of file arrayfuncs.c.

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

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

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

◆ array_get_slice()

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

Definition at line 2030 of file arrayfuncs.c.

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

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

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

◆ array_iterate()

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

Definition at line 4676 of file arrayfuncs.c.

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

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

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

◆ array_map()

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

Definition at line 3201 of file arrayfuncs.c.

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

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

Referenced by ExecEvalArrayCoerce().

◆ array_ref()

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

Definition at line 3146 of file arrayfuncs.c.

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

References array_get_element(), and PointerGetDatum().

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

◆ array_set()

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

Definition at line 3163 of file arrayfuncs.c.

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

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

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

◆ array_set_element()

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

Definition at line 2201 of file arrayfuncs.c.

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

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

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

◆ array_set_slice()

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

Definition at line 2806 of file arrayfuncs.c.

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

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

Referenced by array_subscript_assign_slice().

◆ ArrayCheckBounds()

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

Definition at line 117 of file arrayutils.c.

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

References ArrayCheckBoundsSafe().

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

◆ ArrayCheckBoundsSafe()

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

Definition at line 127 of file arrayutils.c.

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

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

Referenced by ArrayCheckBounds().

◆ ArrayGetIntegerTypmods()

int32* ArrayGetIntegerTypmods ( ArrayType arr,
int *  n 
)

Definition at line 233 of file arrayutils.c.

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

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:482
size_t Size
Definition: c.h:559

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

References i, and scale.

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

◆ construct_array()

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

Definition at line 3361 of file arrayfuncs.c.

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

References construct_md_array().

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

◆ construct_array_builtin()

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

Definition at line 3381 of file arrayfuncs.c.

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

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

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

◆ construct_empty_array()

◆ construct_empty_expanded_array()

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

Definition at line 3597 of file arrayfuncs.c.

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

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

Referenced by fetch_array_arg_replace_nulls().

◆ construct_md_array()

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

Definition at line 3494 of file arrayfuncs.c.

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

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

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

◆ CopyArrayEls()

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

Definition at line 961 of file arrayfuncs.c.

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

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

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

◆ DatumGetAnyArrayP()

AnyArrayType* DatumGetAnyArrayP ( Datum  d)

Definition at line 401 of file array_expanded.c.

402 {
403  ExpandedArrayHeader *eah;
404 
405  /*
406  * If it's an expanded array (RW or RO), return the header pointer.
407  */
409  {
410  eah = (ExpandedArrayHeader *) DatumGetEOHP(d);
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 */
364  d = expand_array(d, CurrentMemoryContext, NULL);
365  return (ExpandedArrayHeader *) DatumGetEOHP(d);
366 }
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR)
Definition: varatt.h:296

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

Referenced by array_set_element_expanded(), and statext_expressions_load().

◆ DatumGetExpandedArrayX()

ExpandedArrayHeader* DatumGetExpandedArrayX ( Datum  d,
ArrayMetaState metacache 
)

Definition at line 372 of file array_expanded.c.

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

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

◆ deconstruct_array()

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

Definition at line 3631 of file arrayfuncs.c.

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

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

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

◆ deconstruct_array_builtin()

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

Definition at line 3697 of file arrayfuncs.c.

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

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

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

◆ deconstruct_expanded_array()

void deconstruct_expanded_array ( ExpandedArrayHeader eah)

Definition at line 424 of file array_expanded.c.

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

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

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

◆ expand_array()

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

Definition at line 50 of file array_expanded.c.

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

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

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

◆ initArrayResult()

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

Definition at line 5293 of file arrayfuncs.c.

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

References initArrayResultWithSize().

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

◆ initArrayResultAny()

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

Definition at line 5782 of file arrayfuncs.c.

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

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

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

◆ initArrayResultArr()

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

Definition at line 5504 of file arrayfuncs.c.

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

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

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

◆ initArrayResultWithSize()

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

Definition at line 5310 of file arrayfuncs.c.

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

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

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

◆ makeArrayResult()

Datum makeArrayResult ( ArrayBuildState astate,
MemoryContext  rcontext 
)

Definition at line 5420 of file arrayfuncs.c.

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

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

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

◆ makeArrayResultAny()

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

Definition at line 5855 of file arrayfuncs.c.

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

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

◆ makeArrayResultArr()

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

Definition at line 5703 of file arrayfuncs.c.

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

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

Referenced by array_agg_array_finalfn(), and makeArrayResultAny().

◆ makeMdArrayResult()

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

Definition at line 5452 of file arrayfuncs.c.

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

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

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

◆ mda_get_offset_values()

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

Definition at line 183 of file arrayutils.c.

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

References i, and j.

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

◆ mda_get_prod()

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

Definition at line 167 of file arrayutils.c.

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

References i, and range().

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

◆ mda_get_range()

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

Definition at line 153 of file arrayutils.c.

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

References i.

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

◆ mda_next_tuple()

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

Definition at line 208 of file arrayutils.c.

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

References i.

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

Variable Documentation

◆ Array_nulls

PGDLLIMPORT bool Array_nulls
extern

Definition at line 43 of file arrayfuncs.c.

Referenced by ReadArrayToken().