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

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

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:811
#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 5338 of file arrayfuncs.c.

5342 {
5343  MemoryContext oldcontext;
5344 
5345  if (astate == NULL)
5346  {
5347  /* First time through --- initialize */
5348  astate = initArrayResult(element_type, rcontext, true);
5349  }
5350  else
5351  {
5352  Assert(astate->element_type == element_type);
5353  }
5354 
5355  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5356 
5357  /* enlarge dvalues[]/dnulls[] if needed */
5358  if (astate->nelems >= astate->alen)
5359  {
5360  astate->alen *= 2;
5361  /* give an array-related error if we go past MaxAllocSize */
5362  if (!AllocSizeIsValid(astate->alen * sizeof(Datum)))
5363  ereport(ERROR,
5364  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5365  errmsg("array size exceeds the maximum allowed (%d)",
5366  (int) MaxAllocSize)));
5367  astate->dvalues = (Datum *)
5368  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5369  astate->dnulls = (bool *)
5370  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5371  }
5372 
5373  /*
5374  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5375  * it's varlena. (You might think that detoasting is not needed here
5376  * because construct_md_array can detoast the array elements later.
5377  * However, we must not let construct_md_array modify the ArrayBuildState
5378  * because that would mean array_agg_finalfn damages its input, which is
5379  * verboten. Also, this way frequently saves one copying step.)
5380  */
5381  if (!disnull && !astate->typbyval)
5382  {
5383  if (astate->typlen == -1)
5384  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5385  else
5386  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5387  }
5388 
5389  astate->dvalues[astate->nelems] = dvalue;
5390  astate->dnulls[astate->nelems] = disnull;
5391  astate->nelems++;
5392 
5393  MemoryContextSwitchTo(oldcontext);
5394 
5395  return astate;
5396 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5281
#define Assert(condition)
Definition: c.h:858
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 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
#define MaxAllocSize
Definition: memutils.h:40
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 5815 of file arrayfuncs.c.

5819 {
5820  if (astate == NULL)
5821  astate = initArrayResultAny(input_type, rcontext, true);
5822 
5823  if (astate->scalarstate)
5824  (void) accumArrayResult(astate->scalarstate,
5825  dvalue, disnull,
5826  input_type, rcontext);
5827  else
5828  (void) accumArrayResultArr(astate->arraystate,
5829  dvalue, disnull,
5830  input_type, rcontext);
5831 
5832  return astate;
5833 }
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5338
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5770
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5538
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 5538 of file arrayfuncs.c.

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

4957 {
4958  int destbitmask,
4959  destbitval,
4960  srcbitmask,
4961  srcbitval;
4962 
4963  Assert(destbitmap);
4964  if (nitems <= 0)
4965  return; /* don't risk fetch off end of memory */
4966  destbitmap += destoffset / 8;
4967  destbitmask = 1 << (destoffset % 8);
4968  destbitval = *destbitmap;
4969  if (srcbitmap)
4970  {
4971  srcbitmap += srcoffset / 8;
4972  srcbitmask = 1 << (srcoffset % 8);
4973  srcbitval = *srcbitmap;
4974  while (nitems-- > 0)
4975  {
4976  if (srcbitval & srcbitmask)
4977  destbitval |= destbitmask;
4978  else
4979  destbitval &= ~destbitmask;
4980  destbitmask <<= 1;
4981  if (destbitmask == 0x100)
4982  {
4983  *destbitmap++ = destbitval;
4984  destbitmask = 1;
4985  if (nitems > 0)
4986  destbitval = *destbitmap;
4987  }
4988  srcbitmask <<= 1;
4989  if (srcbitmask == 0x100)
4990  {
4991  srcbitmap++;
4992  srcbitmask = 1;
4993  if (nitems > 0)
4994  srcbitval = *srcbitmap;
4995  }
4996  }
4997  if (destbitmask != 1)
4998  *destbitmap = destbitval;
4999  }
5000  else
5001  {
5002  while (nitems-- > 0)
5003  {
5004  destbitval |= destbitmask;
5005  destbitmask <<= 1;
5006  if (destbitmask == 0x100)
5007  {
5008  *destbitmap++ = destbitval;
5009  destbitmask = 1;
5010  if (nitems > 0)
5011  destbitval = *destbitmap;
5012  }
5013  }
5014  if (destbitmask != 1)
5015  *destbitmap = destbitval;
5016  }
5017 }

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

3756 {
3757  int nelems;
3758  bits8 *bitmap;
3759  int bitmask;
3760 
3761  /* Easy answer if there's no null bitmap */
3762  if (!ARR_HASNULL(array))
3763  return false;
3764 
3765  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3766 
3767  bitmap = ARR_NULLBITMAP(array);
3768 
3769  /* check whole bytes of the bitmap byte-at-a-time */
3770  while (nelems >= 8)
3771  {
3772  if (*bitmap != 0xFF)
3773  return true;
3774  bitmap++;
3775  nelems -= 8;
3776  }
3777 
3778  /* check last partial byte */
3779  bitmask = 1;
3780  while (nelems > 0)
3781  {
3782  if ((*bitmap & bitmask) == 0)
3783  return true;
3784  bitmask <<= 1;
3785  nelems--;
3786  }
3787 
3788  return false;
3789 }

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(), width_bucket_array(), and worker_spi_launch().

◆ array_create_iterator()

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

Definition at line 4585 of file arrayfuncs.c.

4586 {
4587  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4588 
4589  /*
4590  * Sanity-check inputs --- caller should have got this right already
4591  */
4592  Assert(PointerIsValid(arr));
4593  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4594  elog(ERROR, "invalid arguments to array_create_iterator");
4595 
4596  /*
4597  * Remember basic info about the array and its element type
4598  */
4599  iterator->arr = arr;
4600  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4601  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4602 
4603  if (mstate != NULL)
4604  {
4605  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4606 
4607  iterator->typlen = mstate->typlen;
4608  iterator->typbyval = mstate->typbyval;
4609  iterator->typalign = mstate->typalign;
4610  }
4611  else
4613  &iterator->typlen,
4614  &iterator->typbyval,
4615  &iterator->typalign);
4616 
4617  /*
4618  * Remember the slicing parameters.
4619  */
4620  iterator->slice_ndim = slice_ndim;
4621 
4622  if (slice_ndim > 0)
4623  {
4624  /*
4625  * Get pointers into the array's dims and lbound arrays to represent
4626  * the dims/lbound arrays of a slice. These are the same as the
4627  * rightmost N dimensions of the array.
4628  */
4629  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4630  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4631 
4632  /*
4633  * Compute number of elements in a slice.
4634  */
4635  iterator->slice_len = ArrayGetNItems(slice_ndim,
4636  iterator->slice_dims);
4637 
4638  /*
4639  * Create workspace for building sub-arrays.
4640  */
4641  iterator->slice_values = (Datum *)
4642  palloc(iterator->slice_len * sizeof(Datum));
4643  iterator->slice_nulls = (bool *)
4644  palloc(iterator->slice_len * sizeof(bool));
4645  }
4646 
4647  /*
4648  * Initialize our data pointer and linear element number. These will
4649  * advance through the array during array_iterate().
4650  */
4651  iterator->data_ptr = ARR_DATA_PTR(arr);
4652  iterator->current_item = 0;
4653 
4654  return iterator;
4655 }
#define PointerIsValid(pointer)
Definition: c.h:763
#define elog(elevel,...)
Definition: elog.h:224
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 4747 of file arrayfuncs.c.

4748 {
4749  if (iterator->slice_ndim > 0)
4750  {
4751  pfree(iterator->slice_values);
4752  pfree(iterator->slice_nulls);
4753  }
4754  pfree(iterator);
4755 }

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:4769
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:4804
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4854
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:5025
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3568
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:5085
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:153
signed int int32
Definition: c.h:494
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 4664 of file arrayfuncs.c.

4665 {
4666  /* Done if we have reached the end of the array */
4667  if (iterator->current_item >= iterator->nitems)
4668  return false;
4669 
4670  if (iterator->slice_ndim == 0)
4671  {
4672  /*
4673  * Scalar case: return one element.
4674  */
4675  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4676  {
4677  *isnull = true;
4678  *value = (Datum) 0;
4679  }
4680  else
4681  {
4682  /* non-NULL, so fetch the individual Datum to return */
4683  char *p = iterator->data_ptr;
4684 
4685  *isnull = false;
4686  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4687 
4688  /* Move our data pointer forward to the next element */
4689  p = att_addlength_pointer(p, iterator->typlen, p);
4690  p = (char *) att_align_nominal(p, iterator->typalign);
4691  iterator->data_ptr = p;
4692  }
4693  }
4694  else
4695  {
4696  /*
4697  * Slice case: build and return an array of the requested size.
4698  */
4699  ArrayType *result;
4700  Datum *values = iterator->slice_values;
4701  bool *nulls = iterator->slice_nulls;
4702  char *p = iterator->data_ptr;
4703  int i;
4704 
4705  for (i = 0; i < iterator->slice_len; i++)
4706  {
4707  if (array_get_isnull(iterator->nullbitmap,
4708  iterator->current_item++))
4709  {
4710  nulls[i] = true;
4711  values[i] = (Datum) 0;
4712  }
4713  else
4714  {
4715  nulls[i] = false;
4716  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4717 
4718  /* Move our data pointer forward to the next element */
4719  p = att_addlength_pointer(p, iterator->typlen, p);
4720  p = (char *) att_align_nominal(p, iterator->typalign);
4721  }
4722  }
4723 
4724  iterator->data_ptr = p;
4725 
4726  result = construct_md_array(values,
4727  nulls,
4728  iterator->slice_ndim,
4729  iterator->slice_dims,
4730  iterator->slice_lbound,
4731  ARR_ELEMTYPE(iterator->arr),
4732  iterator->typlen,
4733  iterator->typbyval,
4734  iterator->typalign);
4735 
4736  *isnull = false;
4737  *value = PointerGetDatum(result);
4738  }
4739 
4740  return true;
4741 }
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:3482
static Datum values[MAXATTR]
Definition: bootstrap.c:150
static struct @155 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:333
#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:4786
static int ArrayCastAndSet(Datum src, int typlen, bool typbyval, char typalign, char *dest)
Definition: arrayfuncs.c:4815
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:122
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:104

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:3619
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:5158
static int array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4902
#define Min(x, y)
Definition: c.h:1004
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:182
#define ereturn(context, dummy_value,...)
Definition: elog.h:276

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:3755
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3685
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 }
size_t Size
Definition: c.h:605

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(), float4_accum(), float8_accum(), float8_combine(), float8_regr_accum(), float8_regr_combine(), 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 INT2OID:
3408  elmlen = sizeof(int16);
3409  elmbyval = true;
3410  elmalign = TYPALIGN_SHORT;
3411  break;
3412 
3413  case INT4OID:
3414  elmlen = sizeof(int32);
3415  elmbyval = true;
3416  elmalign = TYPALIGN_INT;
3417  break;
3418 
3419  case INT8OID:
3420  elmlen = sizeof(int64);
3421  elmbyval = FLOAT8PASSBYVAL;
3422  elmalign = TYPALIGN_DOUBLE;
3423  break;
3424 
3425  case NAMEOID:
3426  elmlen = NAMEDATALEN;
3427  elmbyval = false;
3428  elmalign = TYPALIGN_CHAR;
3429  break;
3430 
3431  case OIDOID:
3432  case REGTYPEOID:
3433  elmlen = sizeof(Oid);
3434  elmbyval = true;
3435  elmalign = TYPALIGN_INT;
3436  break;
3437 
3438  case TEXTOID:
3439  elmlen = -1;
3440  elmbyval = false;
3441  elmalign = TYPALIGN_INT;
3442  break;
3443 
3444  case TIDOID:
3445  elmlen = sizeof(ItemPointerData);
3446  elmbyval = false;
3447  elmalign = TYPALIGN_SHORT;
3448  break;
3449 
3450  default:
3451  elog(ERROR, "type %u not supported by construct_array_builtin()", elmtype);
3452  /* keep compiler quiet */
3453  elmlen = 0;
3454  elmbyval = false;
3455  elmalign = 0;
3456  }
3457 
3458  return construct_array(elems, nelems, elmtype, elmlen, elmbyval, elmalign);
3459 }
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3361
signed short int16
Definition: c.h:493
#define FLOAT8PASSBYVAL
Definition: c.h:635
float float4
Definition: c.h:629
struct ItemPointerData ItemPointerData
#define NAMEDATALEN

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

Referenced by AlterPolicy(), 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(), 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_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 3585 of file arrayfuncs.c.

3588 {
3589  ArrayType *array = construct_empty_array(element_type);
3590  Datum d;
3591 
3592  d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3593  pfree(array);
3594  return (ExpandedArrayHeader *) DatumGetEOHP(d);
3595 }
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 3482 of file arrayfuncs.c.

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

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

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

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_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(), pg_get_publication_tables(), 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 3685 of file arrayfuncs.c.

3688 {
3689  int elmlen;
3690  bool elmbyval;
3691  char elmalign;
3692 
3693  switch (elmtype)
3694  {
3695  case CHAROID:
3696  elmlen = 1;
3697  elmbyval = true;
3698  elmalign = TYPALIGN_CHAR;
3699  break;
3700 
3701  case CSTRINGOID:
3702  elmlen = -2;
3703  elmbyval = false;
3704  elmalign = TYPALIGN_CHAR;
3705  break;
3706 
3707  case FLOAT8OID:
3708  elmlen = sizeof(float8);
3709  elmbyval = FLOAT8PASSBYVAL;
3710  elmalign = TYPALIGN_DOUBLE;
3711  break;
3712 
3713  case INT2OID:
3714  elmlen = sizeof(int16);
3715  elmbyval = true;
3716  elmalign = TYPALIGN_SHORT;
3717  break;
3718 
3719  case OIDOID:
3720  elmlen = sizeof(Oid);
3721  elmbyval = true;
3722  elmalign = TYPALIGN_INT;
3723  break;
3724 
3725  case TEXTOID:
3726  elmlen = -1;
3727  elmbyval = false;
3728  elmalign = TYPALIGN_INT;
3729  break;
3730 
3731  case TIDOID:
3732  elmlen = sizeof(ItemPointerData);
3733  elmbyval = false;
3734  elmalign = TYPALIGN_SHORT;
3735  break;
3736 
3737  default:
3738  elog(ERROR, "type %u not supported by deconstruct_array_builtin()", elmtype);
3739  /* keep compiler quiet */
3740  elmlen = 0;
3741  elmbyval = false;
3742  elmalign = 0;
3743  }
3744 
3745  deconstruct_array(array, elmtype, elmlen, elmbyval, elmalign, elemsp, nullsp, nelemsp);
3746 }
double float8
Definition: c.h:630

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

5282 {
5283  /*
5284  * When using a subcontext, we can afford to start with a somewhat larger
5285  * initial array size. Without subcontexts, we'd better hope that most of
5286  * the states stay small ...
5287  */
5288  return initArrayResultWithSize(element_type, rcontext, subcontext,
5289  subcontext ? 64 : 8);
5290 }
ArrayBuildState * initArrayResultWithSize(Oid element_type, MemoryContext rcontext, bool subcontext, int initsize)
Definition: arrayfuncs.c:5298

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

5771 {
5772  ArrayBuildStateAny *astate;
5773  Oid element_type = get_element_type(input_type);
5774 
5775  if (OidIsValid(element_type))
5776  {
5777  /* Array case */
5778  ArrayBuildStateArr *arraystate;
5779 
5780  arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5781  astate = (ArrayBuildStateAny *)
5782  MemoryContextAlloc(arraystate->mcontext,
5783  sizeof(ArrayBuildStateAny));
5784  astate->scalarstate = NULL;
5785  astate->arraystate = arraystate;
5786  }
5787  else
5788  {
5789  /* Scalar case */
5790  ArrayBuildState *scalarstate;
5791 
5792  /* Let's just check that we have a type that can be put into arrays */
5793  Assert(OidIsValid(get_array_type(input_type)));
5794 
5795  scalarstate = initArrayResult(input_type, rcontext, subcontext);
5796  astate = (ArrayBuildStateAny *)
5797  MemoryContextAlloc(scalarstate->mcontext,
5798  sizeof(ArrayBuildStateAny));
5799  astate->scalarstate = scalarstate;
5800  astate->arraystate = NULL;
5801  }
5802 
5803  return astate;
5804 }
#define OidIsValid(objectId)
Definition: c.h:775
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 5492 of file arrayfuncs.c.

5494 {
5495  ArrayBuildStateArr *astate;
5496  MemoryContext arr_context = rcontext; /* by default use the parent ctx */
5497 
5498  /* Lookup element type, unless element_type already provided */
5499  if (!OidIsValid(element_type))
5500  {
5501  element_type = get_element_type(array_type);
5502 
5503  if (!OidIsValid(element_type))
5504  ereport(ERROR,
5505  (errcode(ERRCODE_DATATYPE_MISMATCH),
5506  errmsg("data type %s is not an array type",
5507  format_type_be(array_type))));
5508  }
5509 
5510  /* Make a temporary context to hold all the junk */
5511  if (subcontext)
5512  arr_context = AllocSetContextCreate(rcontext,
5513  "accumArrayResultArr",
5515 
5516  /* Note we initialize all fields to zero */
5517  astate = (ArrayBuildStateArr *)
5518  MemoryContextAllocZero(arr_context, sizeof(ArrayBuildStateArr));
5519  astate->mcontext = arr_context;
5520  astate->private_cxt = subcontext;
5521 
5522  /* Save relevant datatype information */
5523  astate->array_type = array_type;
5524  astate->element_type = element_type;
5525 
5526  return astate;
5527 }
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 5298 of file arrayfuncs.c.

5300 {
5301  ArrayBuildState *astate;
5302  MemoryContext arr_context = rcontext;
5303 
5304  /* Make a temporary context to hold all the junk */
5305  if (subcontext)
5306  arr_context = AllocSetContextCreate(rcontext,
5307  "accumArrayResult",
5309 
5310  astate = (ArrayBuildState *)
5311  MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
5312  astate->mcontext = arr_context;
5313  astate->private_cxt = subcontext;
5314  astate->alen = initsize;
5315  astate->dvalues = (Datum *)
5316  MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
5317  astate->dnulls = (bool *)
5318  MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
5319  astate->nelems = 0;
5320  astate->element_type = element_type;
5321  get_typlenbyvalalign(element_type,
5322  &astate->typlen,
5323  &astate->typbyval,
5324  &astate->typalign);
5325 
5326  return astate;
5327 }
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 5408 of file arrayfuncs.c.

5410 {
5411  int ndims;
5412  int dims[1];
5413  int lbs[1];
5414 
5415  /* If no elements were presented, we want to create an empty array */
5416  ndims = (astate->nelems > 0) ? 1 : 0;
5417  dims[0] = astate->nelems;
5418  lbs[0] = 1;
5419 
5420  return makeMdArrayResult(astate, ndims, dims, lbs, rcontext,
5421  astate->private_cxt);
5422 }
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5440

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

5845 {
5846  Datum result;
5847 
5848  if (astate->scalarstate)
5849  {
5850  /* Must use makeMdArrayResult to support "release" parameter */
5851  int ndims;
5852  int dims[1];
5853  int lbs[1];
5854 
5855  /* If no elements were presented, we want to create an empty array */
5856  ndims = (astate->scalarstate->nelems > 0) ? 1 : 0;
5857  dims[0] = astate->scalarstate->nelems;
5858  lbs[0] = 1;
5859 
5860  result = makeMdArrayResult(astate->scalarstate, ndims, dims, lbs,
5861  rcontext, release);
5862  }
5863  else
5864  {
5865  result = makeArrayResultArr(astate->arraystate,
5866  rcontext, release);
5867  }
5868  return result;
5869 }
Datum makeArrayResultArr(ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5691

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

5694 {
5695  ArrayType *result;
5696  MemoryContext oldcontext;
5697 
5698  /* Build the final array result in rcontext */
5699  oldcontext = MemoryContextSwitchTo(rcontext);
5700 
5701  if (astate->ndims == 0)
5702  {
5703  /* No inputs, return empty array */
5704  result = construct_empty_array(astate->element_type);
5705  }
5706  else
5707  {
5708  int dataoffset,
5709  nbytes;
5710 
5711  /* Check for overflow of the array dimensions */
5712  (void) ArrayGetNItems(astate->ndims, astate->dims);
5713  ArrayCheckBounds(astate->ndims, astate->dims, astate->lbs);
5714 
5715  /* Compute required space */
5716  nbytes = astate->nbytes;
5717  if (astate->nullbitmap != NULL)
5718  {
5719  dataoffset = ARR_OVERHEAD_WITHNULLS(astate->ndims, astate->nitems);
5720  nbytes += dataoffset;
5721  }
5722  else
5723  {
5724  dataoffset = 0;
5725  nbytes += ARR_OVERHEAD_NONULLS(astate->ndims);
5726  }
5727 
5728  result = (ArrayType *) palloc0(nbytes);
5729  SET_VARSIZE(result, nbytes);
5730  result->ndim = astate->ndims;
5731  result->dataoffset = dataoffset;
5732  result->elemtype = astate->element_type;
5733 
5734  memcpy(ARR_DIMS(result), astate->dims, astate->ndims * sizeof(int));
5735  memcpy(ARR_LBOUND(result), astate->lbs, astate->ndims * sizeof(int));
5736  memcpy(ARR_DATA_PTR(result), astate->data, astate->nbytes);
5737 
5738  if (astate->nullbitmap != NULL)
5739  array_bitmap_copy(ARR_NULLBITMAP(result), 0,
5740  astate->nullbitmap, 0,
5741  astate->nitems);
5742  }
5743 
5744  MemoryContextSwitchTo(oldcontext);
5745 
5746  /* Clean up all the junk */
5747  if (release)
5748  {
5749  Assert(astate->private_cxt);
5750  MemoryContextDelete(astate->mcontext);
5751  }
5752 
5753  return PointerGetDatum(result);
5754 }
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 5440 of file arrayfuncs.c.

5446 {
5447  ArrayType *result;
5448  MemoryContext oldcontext;
5449 
5450  /* Build the final array result in rcontext */
5451  oldcontext = MemoryContextSwitchTo(rcontext);
5452 
5453  result = construct_md_array(astate->dvalues,
5454  astate->dnulls,
5455  ndims,
5456  dims,
5457  lbs,
5458  astate->element_type,
5459  astate->typlen,
5460  astate->typbyval,
5461  astate->typalign);
5462 
5463  MemoryContextSwitchTo(oldcontext);
5464 
5465  /* Clean up all the junk */
5466  if (release)
5467  {
5468  Assert(astate->private_cxt);
5469  MemoryContextDelete(astate->mcontext);
5470  }
5471 
5472  return PointerGetDatum(result);
5473 }

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

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().