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 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)
 
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 ArrayGetOffset0 (int n, const int *tup, const int *scale)
 
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:287
#define VARATT_IS_EXPANDED_HEADER(PTR)
int a
Definition: isn.c:69

Definition at line 331 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:285

Definition at line 328 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:284

Definition at line 324 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:289

Definition at line 334 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:283

Definition at line 321 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 309 of file array.h.

◆ ARR_DATA_PTR

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

Definition at line 315 of file array.h.

◆ ARR_DIMS

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

Definition at line 287 of file array.h.

◆ ARR_ELEMTYPE

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

Definition at line 285 of file array.h.

◆ ARR_HASNULL

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

Definition at line 284 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 289 of file array.h.

◆ ARR_NDIM

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

Definition at line 283 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:449

Definition at line 293 of file array.h.

◆ ARR_OVERHEAD_NONULLS

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

Definition at line 303 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:747

Definition at line 305 of file array.h.

◆ ARR_SIZE

#define ARR_SIZE (   a)    VARSIZE(a)

Definition at line 282 of file array.h.

◆ DatumGetArrayTypeP

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

Definition at line 254 of file array.h.

◆ DatumGetArrayTypePCopy

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

Definition at line 255 of file array.h.

◆ EA_MAGIC

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

Definition at line 106 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 267 of file array.h.

◆ PG_GETARG_ARRAYTYPE_P

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

Definition at line 256 of file array.h.

◆ PG_GETARG_ARRAYTYPE_P_COPY

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

Definition at line 257 of file array.h.

◆ PG_GETARG_EXPANDED_ARRAY

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

Definition at line 261 of file array.h.

◆ PG_GETARG_EXPANDED_ARRAYX

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

Definition at line 262 of file array.h.

◆ PG_RETURN_ARRAYTYPE_P

#define PG_RETURN_ARRAYTYPE_P (   x)    PG_RETURN_POINTER(x)

Definition at line 258 of file array.h.

◆ PG_RETURN_EXPANDED_ARRAY

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

Definition at line 264 of file array.h.

Typedef Documentation

◆ AnyArrayType

typedef union AnyArrayType AnyArrayType

◆ ArrayBuildState

◆ ArrayBuildStateAny

◆ ArrayBuildStateArr

◆ ArrayIterator

Definition at line 251 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 5303 of file arrayfuncs.c.

5307 {
5308  MemoryContext oldcontext;
5309 
5310  if (astate == NULL)
5311  {
5312  /* First time through --- initialize */
5313  astate = initArrayResult(element_type, rcontext, true);
5314  }
5315  else
5316  {
5317  Assert(astate->element_type == element_type);
5318  }
5319 
5320  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5321 
5322  /* enlarge dvalues[]/dnulls[] if needed */
5323  if (astate->nelems >= astate->alen)
5324  {
5325  astate->alen *= 2;
5326  astate->dvalues = (Datum *)
5327  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5328  astate->dnulls = (bool *)
5329  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5330  }
5331 
5332  /*
5333  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5334  * it's varlena. (You might think that detoasting is not needed here
5335  * because construct_md_array can detoast the array elements later.
5336  * However, we must not let construct_md_array modify the ArrayBuildState
5337  * because that would mean array_agg_finalfn damages its input, which is
5338  * verboten. Also, this way frequently saves one copying step.)
5339  */
5340  if (!disnull && !astate->typbyval)
5341  {
5342  if (astate->typlen == -1)
5343  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5344  else
5345  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5346  }
5347 
5348  astate->dvalues[astate->nelems] = dvalue;
5349  astate->dnulls[astate->nelems] = disnull;
5350  astate->nelems++;
5351 
5352  MemoryContextSwitchTo(oldcontext);
5353 
5354  return astate;
5355 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5264
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
Assert(fmt[strlen(fmt) - 1] !='\n')
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1321
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:135
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:670
uintptr_t Datum
Definition: postgres.h:412
bool * dnulls
Definition: array.h:184
bool typbyval
Definition: array.h:189
MemoryContext mcontext
Definition: array.h:182
int16 typlen
Definition: array.h:188
Oid element_type
Definition: array.h:187
Datum * dvalues
Definition: array.h:183

References ArrayBuildState::alen, Assert(), datumCopy(), ArrayBuildState::dnulls, ArrayBuildState::dvalues, ArrayBuildState::element_type, initArrayResult(), 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(), dblink_get_connections(), multirange_agg_transfn(), optionListToArray(), parse_ident(), pg_get_statisticsobjdef_expressions(), pg_stats_ext_mcvlist_items(), 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 5774 of file arrayfuncs.c.

5778 {
5779  if (astate == NULL)
5780  astate = initArrayResultAny(input_type, rcontext, true);
5781 
5782  if (astate->scalarstate)
5783  (void) accumArrayResult(astate->scalarstate,
5784  dvalue, disnull,
5785  input_type, rcontext);
5786  else
5787  (void) accumArrayResultArr(astate->arraystate,
5788  dvalue, disnull,
5789  input_type, rcontext);
5790 
5791  return astate;
5792 }
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5303
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5729
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5497
ArrayBuildStateArr * arraystate
Definition: array.h:223
ArrayBuildState * scalarstate
Definition: array.h:222

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

5501 {
5502  ArrayType *arg;
5503  MemoryContext oldcontext;
5504  int *dims,
5505  *lbs,
5506  ndims,
5507  nitems,
5508  ndatabytes;
5509  char *data;
5510  int i;
5511 
5512  /*
5513  * We disallow accumulating null subarrays. Another plausible definition
5514  * is to ignore them, but callers that want that can just skip calling
5515  * this function.
5516  */
5517  if (disnull)
5518  ereport(ERROR,
5519  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5520  errmsg("cannot accumulate null arrays")));
5521 
5522  /* Detoast input array in caller's context */
5523  arg = DatumGetArrayTypeP(dvalue);
5524 
5525  if (astate == NULL)
5526  astate = initArrayResultArr(array_type, InvalidOid, rcontext, true);
5527  else
5528  Assert(astate->array_type == array_type);
5529 
5530  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5531 
5532  /* Collect this input's dimensions */
5533  ndims = ARR_NDIM(arg);
5534  dims = ARR_DIMS(arg);
5535  lbs = ARR_LBOUND(arg);
5536  data = ARR_DATA_PTR(arg);
5537  nitems = ArrayGetNItems(ndims, dims);
5538  ndatabytes = ARR_SIZE(arg) - ARR_DATA_OFFSET(arg);
5539 
5540  if (astate->ndims == 0)
5541  {
5542  /* First input; check/save the dimensionality info */
5543 
5544  /* Should we allow empty inputs and just produce an empty output? */
5545  if (ndims == 0)
5546  ereport(ERROR,
5547  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5548  errmsg("cannot accumulate empty arrays")));
5549  if (ndims + 1 > MAXDIM)
5550  ereport(ERROR,
5551  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5552  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5553  ndims + 1, MAXDIM)));
5554 
5555  /*
5556  * The output array will have n+1 dimensions, with the ones after the
5557  * first matching the input's dimensions.
5558  */
5559  astate->ndims = ndims + 1;
5560  astate->dims[0] = 0;
5561  memcpy(&astate->dims[1], dims, ndims * sizeof(int));
5562  astate->lbs[0] = 1;
5563  memcpy(&astate->lbs[1], lbs, ndims * sizeof(int));
5564 
5565  /* Allocate at least enough data space for this item */
5566  astate->abytes = pg_nextpower2_32(Max(1024, ndatabytes + 1));
5567  astate->data = (char *) palloc(astate->abytes);
5568  }
5569  else
5570  {
5571  /* Second or later input: must match first input's dimensionality */
5572  if (astate->ndims != ndims + 1)
5573  ereport(ERROR,
5574  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5575  errmsg("cannot accumulate arrays of different dimensionality")));
5576  for (i = 0; i < ndims; i++)
5577  {
5578  if (astate->dims[i + 1] != dims[i] || astate->lbs[i + 1] != lbs[i])
5579  ereport(ERROR,
5580  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5581  errmsg("cannot accumulate arrays of different dimensionality")));
5582  }
5583 
5584  /* Enlarge data space if needed */
5585  if (astate->nbytes + ndatabytes > astate->abytes)
5586  {
5587  astate->abytes = Max(astate->abytes * 2,
5588  astate->nbytes + ndatabytes);
5589  astate->data = (char *) repalloc(astate->data, astate->abytes);
5590  }
5591  }
5592 
5593  /*
5594  * Copy the data portion of the sub-array. Note we assume that the
5595  * advertised data length of the sub-array is properly aligned. We do not
5596  * have to worry about detoasting elements since whatever's in the
5597  * sub-array should be OK already.
5598  */
5599  memcpy(astate->data + astate->nbytes, data, ndatabytes);
5600  astate->nbytes += ndatabytes;
5601 
5602  /* Deal with null bitmap if needed */
5603  if (astate->nullbitmap || ARR_HASNULL(arg))
5604  {
5605  int newnitems = astate->nitems + nitems;
5606 
5607  if (astate->nullbitmap == NULL)
5608  {
5609  /*
5610  * First input with nulls; we must retrospectively handle any
5611  * previous inputs by marking all their items non-null.
5612  */
5613  astate->aitems = pg_nextpower2_32(Max(256, newnitems + 1));
5614  astate->nullbitmap = (bits8 *) palloc((astate->aitems + 7) / 8);
5615  array_bitmap_copy(astate->nullbitmap, 0,
5616  NULL, 0,
5617  astate->nitems);
5618  }
5619  else if (newnitems > astate->aitems)
5620  {
5621  astate->aitems = Max(astate->aitems * 2, newnitems);
5622  astate->nullbitmap = (bits8 *)
5623  repalloc(astate->nullbitmap, (astate->aitems + 7) / 8);
5624  }
5625  array_bitmap_copy(astate->nullbitmap, astate->nitems,
5626  ARR_NULLBITMAP(arg), 0,
5627  nitems);
5628  }
5629 
5630  astate->nitems += nitems;
5631  astate->dims[0] += 1;
5632 
5633  MemoryContextSwitchTo(oldcontext);
5634 
5635  /* Release detoasted copy if any */
5636  if ((Pointer) arg != DatumGetPointer(dvalue))
5637  pfree(arg);
5638 
5639  return astate;
5640 }
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define MAXDIM
Definition: array.h:75
#define ARR_NULLBITMAP(a)
Definition: array.h:293
#define DatumGetArrayTypeP(X)
Definition: array.h:254
#define ARR_SIZE(a)
Definition: array.h:282
#define ARR_DATA_OFFSET(a)
Definition: array.h:309
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5451
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4937
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
#define Max(x, y)
Definition: c.h:931
char * Pointer
Definition: c.h:419
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int i
Definition: isn.c:73
void pfree(void *pointer)
Definition: mcxt.c:1306
void * palloc(Size size)
Definition: mcxt.c:1199
void * arg
static uint32 pg_nextpower2_32(uint32 num)
Definition: pg_bitutils.h:140
const void * data
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:660
#define InvalidOid
Definition: postgres_ext.h:36
bits8 * nullbitmap
Definition: array.h:202
int lbs[MAXDIM]
Definition: array.h:209
MemoryContext mcontext
Definition: array.h:200
int dims[MAXDIM]
Definition: array.h:208

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

4940 {
4941  int destbitmask,
4942  destbitval,
4943  srcbitmask,
4944  srcbitval;
4945 
4946  Assert(destbitmap);
4947  if (nitems <= 0)
4948  return; /* don't risk fetch off end of memory */
4949  destbitmap += destoffset / 8;
4950  destbitmask = 1 << (destoffset % 8);
4951  destbitval = *destbitmap;
4952  if (srcbitmap)
4953  {
4954  srcbitmap += srcoffset / 8;
4955  srcbitmask = 1 << (srcoffset % 8);
4956  srcbitval = *srcbitmap;
4957  while (nitems-- > 0)
4958  {
4959  if (srcbitval & srcbitmask)
4960  destbitval |= destbitmask;
4961  else
4962  destbitval &= ~destbitmask;
4963  destbitmask <<= 1;
4964  if (destbitmask == 0x100)
4965  {
4966  *destbitmap++ = destbitval;
4967  destbitmask = 1;
4968  if (nitems > 0)
4969  destbitval = *destbitmap;
4970  }
4971  srcbitmask <<= 1;
4972  if (srcbitmask == 0x100)
4973  {
4974  srcbitmap++;
4975  srcbitmask = 1;
4976  if (nitems > 0)
4977  srcbitval = *srcbitmap;
4978  }
4979  }
4980  if (destbitmask != 1)
4981  *destbitmap = destbitval;
4982  }
4983  else
4984  {
4985  while (nitems-- > 0)
4986  {
4987  destbitval |= destbitmask;
4988  destbitmask <<= 1;
4989  if (destbitmask == 0x100)
4990  {
4991  *destbitmap++ = destbitval;
4992  destbitmask = 1;
4993  if (nitems > 0)
4994  destbitval = *destbitmap;
4995  }
4996  }
4997  if (destbitmask != 1)
4998  *destbitmap = destbitval;
4999  }
5000 }

References Assert().

Referenced by accumArrayResultArr(), 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 3738 of file arrayfuncs.c.

3739 {
3740  int nelems;
3741  bits8 *bitmap;
3742  int bitmask;
3743 
3744  /* Easy answer if there's no null bitmap */
3745  if (!ARR_HASNULL(array))
3746  return false;
3747 
3748  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3749 
3750  bitmap = ARR_NULLBITMAP(array);
3751 
3752  /* check whole bytes of the bitmap byte-at-a-time */
3753  while (nelems >= 8)
3754  {
3755  if (*bitmap != 0xFF)
3756  return true;
3757  bitmap++;
3758  nelems -= 8;
3759  }
3760 
3761  /* check last partial byte */
3762  bitmask = 1;
3763  while (nelems > 0)
3764  {
3765  if ((*bitmap & bitmask) == 0)
3766  return true;
3767  bitmask <<= 1;
3768  nelems--;
3769  }
3770 
3771  return false;
3772 }

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

◆ array_create_iterator()

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

Definition at line 4568 of file arrayfuncs.c.

4569 {
4570  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4571 
4572  /*
4573  * Sanity-check inputs --- caller should have got this right already
4574  */
4575  Assert(PointerIsValid(arr));
4576  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4577  elog(ERROR, "invalid arguments to array_create_iterator");
4578 
4579  /*
4580  * Remember basic info about the array and its element type
4581  */
4582  iterator->arr = arr;
4583  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4584  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4585 
4586  if (mstate != NULL)
4587  {
4588  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4589 
4590  iterator->typlen = mstate->typlen;
4591  iterator->typbyval = mstate->typbyval;
4592  iterator->typalign = mstate->typalign;
4593  }
4594  else
4596  &iterator->typlen,
4597  &iterator->typbyval,
4598  &iterator->typalign);
4599 
4600  /*
4601  * Remember the slicing parameters.
4602  */
4603  iterator->slice_ndim = slice_ndim;
4604 
4605  if (slice_ndim > 0)
4606  {
4607  /*
4608  * Get pointers into the array's dims and lbound arrays to represent
4609  * the dims/lbound arrays of a slice. These are the same as the
4610  * rightmost N dimensions of the array.
4611  */
4612  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4613  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4614 
4615  /*
4616  * Compute number of elements in a slice.
4617  */
4618  iterator->slice_len = ArrayGetNItems(slice_ndim,
4619  iterator->slice_dims);
4620 
4621  /*
4622  * Create workspace for building sub-arrays.
4623  */
4624  iterator->slice_values = (Datum *)
4625  palloc(iterator->slice_len * sizeof(Datum));
4626  iterator->slice_nulls = (bool *)
4627  palloc(iterator->slice_len * sizeof(bool));
4628  }
4629 
4630  /*
4631  * Initialize our data pointer and linear element number. These will
4632  * advance through the array during array_iterate().
4633  */
4634  iterator->data_ptr = ARR_DATA_PTR(arr);
4635  iterator->current_item = 0;
4636 
4637  return iterator;
4638 }
#define PointerIsValid(pointer)
Definition: c.h:699
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2229
void * palloc0(Size size)
Definition: mcxt.c:1230
ArrayType * arr
Definition: arrayfuncs.c:72
bool * slice_nulls
Definition: arrayfuncs.c:85
Datum * slice_values
Definition: arrayfuncs.c:84
bits8 * nullbitmap
Definition: arrayfuncs.c:73
char typalign
Definition: array.h:234
int16 typlen
Definition: array.h:232
Oid element_type
Definition: array.h:231
bool typbyval
Definition: array.h:233

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

4731 {
4732  if (iterator->slice_ndim > 0)
4733  {
4734  pfree(iterator->slice_values);
4735  pfree(iterator->slice_nulls);
4736  }
4737  pfree(iterator);
4738 }

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

1863 {
1864  int i,
1865  ndim,
1866  *dim,
1867  *lb,
1868  offset,
1869  fixedDim[1],
1870  fixedLb[1];
1871  char *arraydataptr,
1872  *retptr;
1873  bits8 *arraynullsptr;
1874 
1875  if (arraytyplen > 0)
1876  {
1877  /*
1878  * fixed-length arrays -- these are assumed to be 1-d, 0-based
1879  */
1880  ndim = 1;
1881  fixedDim[0] = arraytyplen / elmlen;
1882  fixedLb[0] = 0;
1883  dim = fixedDim;
1884  lb = fixedLb;
1885  arraydataptr = (char *) DatumGetPointer(arraydatum);
1886  arraynullsptr = NULL;
1887  }
1888  else if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(arraydatum)))
1889  {
1890  /* expanded array: let's do this in a separate function */
1891  return array_get_element_expanded(arraydatum,
1892  nSubscripts,
1893  indx,
1894  arraytyplen,
1895  elmlen,
1896  elmbyval,
1897  elmalign,
1898  isNull);
1899  }
1900  else
1901  {
1902  /* detoast array if necessary, producing normal varlena input */
1903  ArrayType *array = DatumGetArrayTypeP(arraydatum);
1904 
1905  ndim = ARR_NDIM(array);
1906  dim = ARR_DIMS(array);
1907  lb = ARR_LBOUND(array);
1908  arraydataptr = ARR_DATA_PTR(array);
1909  arraynullsptr = ARR_NULLBITMAP(array);
1910  }
1911 
1912  /*
1913  * Return NULL for invalid subscript
1914  */
1915  if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
1916  {
1917  *isNull = true;
1918  return (Datum) 0;
1919  }
1920  for (i = 0; i < ndim; i++)
1921  {
1922  if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
1923  {
1924  *isNull = true;
1925  return (Datum) 0;
1926  }
1927  }
1928 
1929  /*
1930  * Calculate the element number
1931  */
1932  offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
1933 
1934  /*
1935  * Check for NULL array element
1936  */
1937  if (array_get_isnull(arraynullsptr, offset))
1938  {
1939  *isNull = true;
1940  return (Datum) 0;
1941  }
1942 
1943  /*
1944  * OK, get the element
1945  */
1946  *isNull = false;
1947  retptr = array_seek(arraydataptr, 0, arraynullsptr, offset,
1948  elmlen, elmbyval, elmalign);
1949  return ArrayCast(retptr, elmbyval, elmlen);
1950 }
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4752
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:1956
static Datum ArrayCast(char *value, bool byval, int len)
Definition: arrayfuncs.c:4787
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4837
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:32
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:336

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

2075 {
2076  ArrayType *array;
2077  ArrayType *newarray;
2078  int i,
2079  ndim,
2080  *dim,
2081  *lb,
2082  *newlb;
2083  int fixedDim[1],
2084  fixedLb[1];
2085  Oid elemtype;
2086  char *arraydataptr;
2087  bits8 *arraynullsptr;
2088  int32 dataoffset;
2089  int bytes,
2090  span[MAXDIM];
2091 
2092  if (arraytyplen > 0)
2093  {
2094  /*
2095  * fixed-length arrays -- currently, cannot slice these because parser
2096  * labels output as being of the fixed-length array type! Code below
2097  * shows how we could support it if the parser were changed to label
2098  * output as a suitable varlena array type.
2099  */
2100  ereport(ERROR,
2101  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2102  errmsg("slices of fixed-length arrays not implemented")));
2103 
2104  /*
2105  * fixed-length arrays -- these are assumed to be 1-d, 0-based
2106  *
2107  * XXX where would we get the correct ELEMTYPE from?
2108  */
2109  ndim = 1;
2110  fixedDim[0] = arraytyplen / elmlen;
2111  fixedLb[0] = 0;
2112  dim = fixedDim;
2113  lb = fixedLb;
2114  elemtype = InvalidOid; /* XXX */
2115  arraydataptr = (char *) DatumGetPointer(arraydatum);
2116  arraynullsptr = NULL;
2117  }
2118  else
2119  {
2120  /* detoast input array if necessary */
2121  array = DatumGetArrayTypeP(arraydatum);
2122 
2123  ndim = ARR_NDIM(array);
2124  dim = ARR_DIMS(array);
2125  lb = ARR_LBOUND(array);
2126  elemtype = ARR_ELEMTYPE(array);
2127  arraydataptr = ARR_DATA_PTR(array);
2128  arraynullsptr = ARR_NULLBITMAP(array);
2129  }
2130 
2131  /*
2132  * Check provided subscripts. A slice exceeding the current array limits
2133  * is silently truncated to the array limits. If we end up with an empty
2134  * slice, return an empty array.
2135  */
2136  if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
2137  return PointerGetDatum(construct_empty_array(elemtype));
2138 
2139  for (i = 0; i < nSubscripts; i++)
2140  {
2141  if (!lowerProvided[i] || lowerIndx[i] < lb[i])
2142  lowerIndx[i] = lb[i];
2143  if (!upperProvided[i] || upperIndx[i] >= (dim[i] + lb[i]))
2144  upperIndx[i] = dim[i] + lb[i] - 1;
2145  if (lowerIndx[i] > upperIndx[i])
2146  return PointerGetDatum(construct_empty_array(elemtype));
2147  }
2148  /* fill any missing subscript positions with full array range */
2149  for (; i < ndim; i++)
2150  {
2151  lowerIndx[i] = lb[i];
2152  upperIndx[i] = dim[i] + lb[i] - 1;
2153  if (lowerIndx[i] > upperIndx[i])
2154  return PointerGetDatum(construct_empty_array(elemtype));
2155  }
2156 
2157  mda_get_range(ndim, span, lowerIndx, upperIndx);
2158 
2159  bytes = array_slice_size(arraydataptr, arraynullsptr,
2160  ndim, dim, lb,
2161  lowerIndx, upperIndx,
2162  elmlen, elmbyval, elmalign);
2163 
2164  /*
2165  * Currently, we put a null bitmap in the result if the source has one;
2166  * could be smarter ...
2167  */
2168  if (arraynullsptr)
2169  {
2170  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, ArrayGetNItems(ndim, span));
2171  bytes += dataoffset;
2172  }
2173  else
2174  {
2175  dataoffset = 0; /* marker for no null bitmap */
2176  bytes += ARR_OVERHEAD_NONULLS(ndim);
2177  }
2178 
2179  newarray = (ArrayType *) palloc0(bytes);
2180  SET_VARSIZE(newarray, bytes);
2181  newarray->ndim = ndim;
2182  newarray->dataoffset = dataoffset;
2183  newarray->elemtype = elemtype;
2184  memcpy(ARR_DIMS(newarray), span, ndim * sizeof(int));
2185 
2186  /*
2187  * Lower bounds of the new array are set to 1. Formerly (before 7.3) we
2188  * copied the given lowerIndx values ... but that seems confusing.
2189  */
2190  newlb = ARR_LBOUND(newarray);
2191  for (i = 0; i < ndim; i++)
2192  newlb[i] = 1;
2193 
2194  array_extract_slice(newarray,
2195  ndim, dim, lb,
2196  arraydataptr, arraynullsptr,
2197  lowerIndx, upperIndx,
2198  elmlen, elmbyval, elmalign);
2199 
2200  return PointerGetDatum(newarray);
2201 }
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
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:5008
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3551
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:5068
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:174
signed int int32
Definition: c.h:430
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:343
unsigned int Oid
Definition: postgres_ext.h:31
Oid elemtype
Definition: array.h:90
int ndim
Definition: array.h:88
int32 dataoffset
Definition: array.h:89

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

4648 {
4649  /* Done if we have reached the end of the array */
4650  if (iterator->current_item >= iterator->nitems)
4651  return false;
4652 
4653  if (iterator->slice_ndim == 0)
4654  {
4655  /*
4656  * Scalar case: return one element.
4657  */
4658  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4659  {
4660  *isnull = true;
4661  *value = (Datum) 0;
4662  }
4663  else
4664  {
4665  /* non-NULL, so fetch the individual Datum to return */
4666  char *p = iterator->data_ptr;
4667 
4668  *isnull = false;
4669  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4670 
4671  /* Move our data pointer forward to the next element */
4672  p = att_addlength_pointer(p, iterator->typlen, p);
4673  p = (char *) att_align_nominal(p, iterator->typalign);
4674  iterator->data_ptr = p;
4675  }
4676  }
4677  else
4678  {
4679  /*
4680  * Slice case: build and return an array of the requested size.
4681  */
4682  ArrayType *result;
4683  Datum *values = iterator->slice_values;
4684  bool *nulls = iterator->slice_nulls;
4685  char *p = iterator->data_ptr;
4686  int i;
4687 
4688  for (i = 0; i < iterator->slice_len; i++)
4689  {
4690  if (array_get_isnull(iterator->nullbitmap,
4691  iterator->current_item++))
4692  {
4693  nulls[i] = true;
4694  values[i] = (Datum) 0;
4695  }
4696  else
4697  {
4698  nulls[i] = false;
4699  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4700 
4701  /* Move our data pointer forward to the next element */
4702  p = att_addlength_pointer(p, iterator->typlen, p);
4703  p = (char *) att_align_nominal(p, iterator->typalign);
4704  }
4705  }
4706 
4707  iterator->data_ptr = p;
4708 
4709  result = construct_md_array(values,
4710  nulls,
4711  iterator->slice_ndim,
4712  iterator->slice_dims,
4713  iterator->slice_lbound,
4714  ARR_ELEMTYPE(iterator->arr),
4715  iterator->typlen,
4716  iterator->typbyval,
4717  iterator->typalign);
4718 
4719  *isnull = false;
4720  *value = PointerGetDatum(result);
4721  }
4722 
4723  return true;
4724 }
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:3465
static Datum values[MAXATTR]
Definition: bootstrap.c:156
static struct @143 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 3183 of file arrayfuncs.c.

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

3131 {
3132  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3133  arraytyplen, elmlen, elmbyval, elmalign,
3134  isNull);
3135 }
Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1855

References array_get_element(), and PointerGetDatum().

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

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

3148 {
3150  nSubscripts, indx,
3151  dataValue, isNull,
3152  arraytyplen,
3153  elmlen, elmbyval, elmalign));
3154 }
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:2236

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

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

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, MAXDIM, MemSet, ArrayType::ndim, palloc(), palloc0(), PG_DETOAST_DATUM, 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 2810 of file arrayfuncs.c.

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

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, MAXDIM, mda_get_range(), MemSet, Min, ArrayType::ndim, palloc0(), PointerGetDatum(), and SET_VARSIZE.

Referenced by array_subscript_assign_slice().

◆ ArrayCheckBounds()

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

Definition at line 138 of file arrayutils.c.

139 {
140  (void) ArrayCheckBoundsSafe(ndim, dims, lb, NULL);
141 }
bool ArrayCheckBoundsSafe(int ndim, const int *dims, const int *lb, struct Node *escontext)
Definition: arrayutils.c:148

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 148 of file arrayutils.c.

150 {
151  int i;
152 
153  for (i = 0; i < ndim; i++)
154  {
155  /* PG_USED_FOR_ASSERTS_ONLY prevents variable-isn't-read warnings */
157 
158  if (pg_add_s32_overflow(dims[i], lb[i], &sum))
159  ereturn(escontext, false,
160  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
161  errmsg("array lower bound is too large: %d",
162  lb[i])));
163  }
164 
165  return true;
166 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:166
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:104

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

Referenced by array_in(), and ArrayCheckBounds().

◆ ArrayGetIntegerTypmods()

int32* ArrayGetIntegerTypmods ( ArrayType arr,
int *  n 
)

Definition at line 254 of file arrayutils.c.

255 {
256  int32 *result;
257  Datum *elem_values;
258  int i;
259 
260  if (ARR_ELEMTYPE(arr) != CSTRINGOID)
261  ereport(ERROR,
262  (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
263  errmsg("typmod array must be type cstring[]")));
264 
265  if (ARR_NDIM(arr) != 1)
266  ereport(ERROR,
267  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
268  errmsg("typmod array must be one-dimensional")));
269 
270  if (array_contains_nulls(arr))
271  ereport(ERROR,
272  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
273  errmsg("typmod array must not contain nulls")));
274 
275  deconstruct_array_builtin(arr, CSTRINGOID, &elem_values, NULL, n);
276 
277  result = (int32 *) palloc(*n * sizeof(int32));
278 
279  for (i = 0; i < *n; i++)
280  result[i] = pg_strtoint32(DatumGetCString(elem_values[i]));
281 
282  pfree(elem_values);
283 
284  return result;
285 }
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3738
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3668
int32 pg_strtoint32(const char *s)
Definition: numutils.c:187
static char * DatumGetCString(Datum X)
Definition: postgres.h:683

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 86 of file arrayutils.c.

87 {
88  int32 ret;
89  int i;
90 
91 #define MaxArraySize ((Size) (MaxAllocSize / sizeof(Datum)))
92 
93  if (ndim <= 0)
94  return 0;
95  ret = 1;
96  for (i = 0; i < ndim; i++)
97  {
98  int64 prod;
99 
100  /* A negative dimension implies that UB-LB overflowed ... */
101  if (dims[i] < 0)
102  ereturn(escontext, -1,
103  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
104  errmsg("array size exceeds the maximum allowed (%d)",
105  (int) MaxArraySize)));
106 
107  prod = (int64) ret * (int64) dims[i];
108 
109  ret = (int32) prod;
110  if ((int64) ret != prod)
111  ereturn(escontext, -1,
112  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
113  errmsg("array size exceeds the maximum allowed (%d)",
114  (int) MaxArraySize)));
115  }
116  Assert(ret >= 0);
117  if ((Size) ret > MaxArraySize)
118  ereturn(escontext, -1,
119  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
120  errmsg("array size exceeds the maximum allowed (%d)",
121  (int) MaxArraySize)));
122  return (int) ret;
123 }
#define MaxArraySize
size_t Size
Definition: c.h:541

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

Referenced by array_in(), and 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 }
int scale
Definition: pgbench.c:190

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

◆ ArrayGetOffset0()

int ArrayGetOffset0 ( int  n,
const int *  tup,
const int *  scale 
)

Definition at line 51 of file arrayutils.c.

52 {
53  int i,
54  lin = 0;
55 
56  for (i = 0; i < n; i++)
57  lin += tup[i] * scale[i];
58  return lin;
59 }

References i, and scale.

Referenced by ReadArrayStr().

◆ construct_array()

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

Definition at line 3343 of file arrayfuncs.c.

3346 {
3347  int dims[1];
3348  int lbs[1];
3349 
3350  dims[0] = nelems;
3351  lbs[0] = 1;
3352 
3353  return construct_md_array(elems, NULL, 1, dims, lbs,
3354  elmtype, elmlen, elmbyval, elmalign);
3355 }

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(), interval_accum(), interval_accum_inv(), interval_combine(), serialize_expr_stats(), StoreAttrDefault(), and update_attstats().

◆ construct_array_builtin()

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

Definition at line 3363 of file arrayfuncs.c.

3364 {
3365  int elmlen;
3366  bool elmbyval;
3367  char elmalign;
3368 
3369  switch (elmtype)
3370  {
3371  case CHAROID:
3372  case BOOLOID:
3373  elmlen = 1;
3374  elmbyval = true;
3375  elmalign = TYPALIGN_CHAR;
3376  break;
3377 
3378  case CSTRINGOID:
3379  elmlen = -2;
3380  elmbyval = false;
3381  elmalign = TYPALIGN_CHAR;
3382  break;
3383 
3384  case FLOAT4OID:
3385  elmlen = sizeof(float4);
3386  elmbyval = true;
3387  elmalign = TYPALIGN_INT;
3388  break;
3389 
3390  case INT2OID:
3391  elmlen = sizeof(int16);
3392  elmbyval = true;
3393  elmalign = TYPALIGN_SHORT;
3394  break;
3395 
3396  case INT4OID:
3397  elmlen = sizeof(int32);
3398  elmbyval = true;
3399  elmalign = TYPALIGN_INT;
3400  break;
3401 
3402  case INT8OID:
3403  elmlen = sizeof(int64);
3404  elmbyval = FLOAT8PASSBYVAL;
3405  elmalign = TYPALIGN_DOUBLE;
3406  break;
3407 
3408  case NAMEOID:
3409  elmlen = NAMEDATALEN;
3410  elmbyval = false;
3411  elmalign = TYPALIGN_CHAR;
3412  break;
3413 
3414  case OIDOID:
3415  case REGTYPEOID:
3416  elmlen = sizeof(Oid);
3417  elmbyval = true;
3418  elmalign = TYPALIGN_INT;
3419  break;
3420 
3421  case TEXTOID:
3422  elmlen = -1;
3423  elmbyval = false;
3424  elmalign = TYPALIGN_INT;
3425  break;
3426 
3427  case TIDOID:
3428  elmlen = sizeof(ItemPointerData);
3429  elmbyval = false;
3430  elmalign = TYPALIGN_SHORT;
3431  break;
3432 
3433  default:
3434  elog(ERROR, "type %u not supported by construct_array_builtin()", elmtype);
3435  /* keep compiler quiet */
3436  elmlen = 0;
3437  elmbyval = false;
3438  elmalign = 0;
3439  }
3440 
3441  return construct_array(elems, nelems, elmtype, elmlen, elmbyval, elmalign);
3442 }
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3343
signed short int16
Definition: c.h:429
#define FLOAT8PASSBYVAL
Definition: c.h:571
float float4
Definition: c.h:565
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(), extension_config_remove(), filter_list_to_array(), get_hba_options(), gin_leafpage_items(), gin_page_opaque_info(), gist_page_opaque_info(), GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), hash_metapage_info(), heap_tuple_infomask_flags(), hstore_akeys(), 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 3568 of file arrayfuncs.c.

3571 {
3572  ArrayType *array = construct_empty_array(element_type);
3573  Datum d;
3574 
3575  d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3576  pfree(array);
3577  return (ExpandedArrayHeader *) DatumGetEOHP(d);
3578 }
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 3465 of file arrayfuncs.c.

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

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

993 {
994  char *p = ARR_DATA_PTR(array);
995  bits8 *bitmap = ARR_NULLBITMAP(array);
996  int bitval = 0;
997  int bitmask = 1;
998  int i;
999 
1000  if (typbyval)
1001  freedata = false;
1002 
1003  for (i = 0; i < nitems; i++)
1004  {
1005  if (nulls && nulls[i])
1006  {
1007  if (!bitmap) /* shouldn't happen */
1008  elog(ERROR, "null array element where not supported");
1009  /* bitmap bit stays 0 */
1010  }
1011  else
1012  {
1013  bitval |= bitmask;
1014  p += ArrayCastAndSet(values[i], typlen, typbyval, typalign, p);
1015  if (freedata)
1017  }
1018  if (bitmap)
1019  {
1020  bitmask <<= 1;
1021  if (bitmask == 0x100)
1022  {
1023  *bitmap++ = bitval;
1024  bitval = 0;
1025  bitmask = 1;
1026  }
1027  }
1028  }
1029 
1030  if (bitmap && bitmask != 1)
1031  *bitmap = bitval;
1032 }

References ARR_DATA_PTR, ARR_NULLBITMAP, ArrayCastAndSet(), DatumGetPointer(), elog(), ERROR, i, 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:106

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:124
#define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR)
Definition: postgres.h:334

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

3606 {
3607  Datum *elems;
3608  bool *nulls;
3609  int nelems;
3610  char *p;
3611  bits8 *bitmap;
3612  int bitmask;
3613  int i;
3614 
3615  Assert(ARR_ELEMTYPE(array) == elmtype);
3616 
3617  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3618  *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
3619  if (nullsp)
3620  *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
3621  else
3622  nulls = NULL;
3623  *nelemsp = nelems;
3624 
3625  p = ARR_DATA_PTR(array);
3626  bitmap = ARR_NULLBITMAP(array);
3627  bitmask = 1;
3628 
3629  for (i = 0; i < nelems; i++)
3630  {
3631  /* Get source element, checking for NULL */
3632  if (bitmap && (*bitmap & bitmask) == 0)
3633  {
3634  elems[i] = (Datum) 0;
3635  if (nulls)
3636  nulls[i] = true;
3637  else
3638  ereport(ERROR,
3639  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3640  errmsg("null array element not allowed in this context")));
3641  }
3642  else
3643  {
3644  elems[i] = fetch_att(p, elmbyval, elmlen);
3645  p = att_addlength_pointer(p, elmlen, p);
3646  p = (char *) att_align_nominal(p, elmalign);
3647  }
3648 
3649  /* advance bitmap pointer if any */
3650  if (bitmap)
3651  {
3652  bitmask <<= 1;
3653  if (bitmask == 0x100)
3654  {
3655  bitmap++;
3656  bitmask = 1;
3657  }
3658  }
3659  }
3660 }

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_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(), interval_accum(), interval_accum_inv(), interval_avg(), interval_combine(), map_sql_value_to_xml_value(), match_clause_to_partition_key(), mcelem_array_selec(), mcv_get_match_bitmap(), multirange_constructor2(), plperl_ref_from_pg_array(), satisfies_hash_partition(), scalararraysel(), and text_format().

◆ deconstruct_array_builtin()

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

Definition at line 3668 of file arrayfuncs.c.

3671 {
3672  int elmlen;
3673  bool elmbyval;
3674  char elmalign;
3675 
3676  switch (elmtype)
3677  {
3678  case CHAROID:
3679  elmlen = 1;
3680  elmbyval = true;
3681  elmalign = TYPALIGN_CHAR;
3682  break;
3683 
3684  case CSTRINGOID:
3685  elmlen = -2;
3686  elmbyval = false;
3687  elmalign = TYPALIGN_CHAR;
3688  break;
3689 
3690  case FLOAT8OID:
3691  elmlen = sizeof(float8);
3692  elmbyval = FLOAT8PASSBYVAL;
3693  elmalign = TYPALIGN_DOUBLE;
3694  break;
3695 
3696  case INT2OID:
3697  elmlen = sizeof(int16);
3698  elmbyval = true;
3699  elmalign = TYPALIGN_SHORT;
3700  break;
3701 
3702  case OIDOID:
3703  elmlen = sizeof(Oid);
3704  elmbyval = true;
3705  elmalign = TYPALIGN_INT;
3706  break;
3707 
3708  case TEXTOID:
3709  elmlen = -1;
3710  elmbyval = false;
3711  elmalign = TYPALIGN_INT;
3712  break;
3713 
3714  case TIDOID:
3715  elmlen = sizeof(ItemPointerData);
3716  elmbyval = false;
3717  elmalign = TYPALIGN_SHORT;
3718  break;
3719 
3720  default:
3721  elog(ERROR, "type %u not supported by deconstruct_array_builtin()", elmtype);
3722  /* keep compiler quiet */
3723  elmlen = 0;
3724  elmbyval = false;
3725  elmalign = 0;
3726  }
3727 
3728  deconstruct_array(array, elmtype, elmlen, elmbyval, elmalign, elemsp, nullsp, nelemsp);
3729 }
double float8
Definition: c.h:566

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

◆ 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:111
Datum * dvalues
Definition: array.h:139
ArrayType * fvalue
Definition: array.h:158
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:255
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:994
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:170
char * fstartptr
Definition: array.h:159
char * fendptr
Definition: array.h:160

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

5265 {
5266  ArrayBuildState *astate;
5267  MemoryContext arr_context = rcontext;
5268 
5269  /* Make a temporary context to hold all the junk */
5270  if (subcontext)
5271  arr_context = AllocSetContextCreate(rcontext,
5272  "accumArrayResult",
5274 
5275  astate = (ArrayBuildState *)
5276  MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
5277  astate->mcontext = arr_context;
5278  astate->private_cxt = subcontext;
5279  astate->alen = (subcontext ? 64 : 8); /* arbitrary starting array size */
5280  astate->dvalues = (Datum *)
5281  MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
5282  astate->dnulls = (bool *)
5283  MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
5284  astate->nelems = 0;
5285  astate->element_type = element_type;
5286  get_typlenbyvalalign(element_type,
5287  &astate->typlen,
5288  &astate->typbyval,
5289  &astate->typalign);
5290 
5291  return astate;
5292 }
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
bool private_cxt
Definition: array.h:191
char typalign
Definition: array.h:190

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 accumArrayResult(), array_agg_transfn(), array_positions(), initArrayResultAny(), multirange_agg_transfn(), plperl_array_to_datum(), populate_array(), range_agg_transfn(), tuple_data_split_internal(), and xpath().

◆ initArrayResultAny()

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

Definition at line 5729 of file arrayfuncs.c.

5730 {
5731  ArrayBuildStateAny *astate;
5732  Oid element_type = get_element_type(input_type);
5733 
5734  if (OidIsValid(element_type))
5735  {
5736  /* Array case */
5737  ArrayBuildStateArr *arraystate;
5738 
5739  arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5740  astate = (ArrayBuildStateAny *)
5741  MemoryContextAlloc(arraystate->mcontext,
5742  sizeof(ArrayBuildStateAny));
5743  astate->scalarstate = NULL;
5744  astate->arraystate = arraystate;
5745  }
5746  else
5747  {
5748  /* Scalar case */
5749  ArrayBuildState *scalarstate;
5750 
5751  /* Let's just check that we have a type that can be put into arrays */
5752  Assert(OidIsValid(get_array_type(input_type)));
5753 
5754  scalarstate = initArrayResult(input_type, rcontext, subcontext);
5755  astate = (ArrayBuildStateAny *)
5756  MemoryContextAlloc(scalarstate->mcontext,
5757  sizeof(ArrayBuildStateAny));
5758  astate->scalarstate = scalarstate;
5759  astate->arraystate = NULL;
5760  }
5761 
5762  return astate;
5763 }
#define OidIsValid(objectId)
Definition: c.h:711
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2717
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2745

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

5453 {
5454  ArrayBuildStateArr *astate;
5455  MemoryContext arr_context = rcontext; /* by default use the parent ctx */
5456 
5457  /* Lookup element type, unless element_type already provided */
5458  if (!OidIsValid(element_type))
5459  {
5460  element_type = get_element_type(array_type);
5461 
5462  if (!OidIsValid(element_type))
5463  ereport(ERROR,
5464  (errcode(ERRCODE_DATATYPE_MISMATCH),
5465  errmsg("data type %s is not an array type",
5466  format_type_be(array_type))));
5467  }
5468 
5469  /* Make a temporary context to hold all the junk */
5470  if (subcontext)
5471  arr_context = AllocSetContextCreate(rcontext,
5472  "accumArrayResultArr",
5474 
5475  /* Note we initialize all fields to zero */
5476  astate = (ArrayBuildStateArr *)
5477  MemoryContextAllocZero(arr_context, sizeof(ArrayBuildStateArr));
5478  astate->mcontext = arr_context;
5479  astate->private_cxt = subcontext;
5480 
5481  /* Save relevant datatype information */
5482  astate->array_type = array_type;
5483  astate->element_type = element_type;
5484 
5485  return astate;
5486 }
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1037
bool private_cxt
Definition: array.h:212

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_transfn(), and initArrayResultAny().

◆ makeArrayResult()

Datum makeArrayResult ( ArrayBuildState astate,
MemoryContext  rcontext 
)

Definition at line 5367 of file arrayfuncs.c.

5369 {
5370  int ndims;
5371  int dims[1];
5372  int lbs[1];
5373 
5374  /* If no elements were presented, we want to create an empty array */
5375  ndims = (astate->nelems > 0) ? 1 : 0;
5376  dims[0] = astate->nelems;
5377  lbs[0] = 1;
5378 
5379  return makeMdArrayResult(astate, ndims, dims, lbs, rcontext,
5380  astate->private_cxt);
5381 }
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5399

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

Referenced by array_positions(), brin_minmax_multi_summary_out(), 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 5802 of file arrayfuncs.c.

5804 {
5805  Datum result;
5806 
5807  if (astate->scalarstate)
5808  {
5809  /* Must use makeMdArrayResult to support "release" parameter */
5810  int ndims;
5811  int dims[1];
5812  int lbs[1];
5813 
5814  /* If no elements were presented, we want to create an empty array */
5815  ndims = (astate->scalarstate->nelems > 0) ? 1 : 0;
5816  dims[0] = astate->scalarstate->nelems;
5817  lbs[0] = 1;
5818 
5819  result = makeMdArrayResult(astate->scalarstate, ndims, dims, lbs,
5820  rcontext, release);
5821  }
5822  else
5823  {
5824  result = makeArrayResultArr(astate->arraystate,
5825  rcontext, release);
5826  }
5827  return result;
5828 }
Datum makeArrayResultArr(ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5650

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

5653 {
5654  ArrayType *result;
5655  MemoryContext oldcontext;
5656 
5657  /* Build the final array result in rcontext */
5658  oldcontext = MemoryContextSwitchTo(rcontext);
5659 
5660  if (astate->ndims == 0)
5661  {
5662  /* No inputs, return empty array */
5663  result = construct_empty_array(astate->element_type);
5664  }
5665  else
5666  {
5667  int dataoffset,
5668  nbytes;
5669 
5670  /* Check for overflow of the array dimensions */
5671  (void) ArrayGetNItems(astate->ndims, astate->dims);
5672  ArrayCheckBounds(astate->ndims, astate->dims, astate->lbs);
5673 
5674  /* Compute required space */
5675  nbytes = astate->nbytes;
5676  if (astate->nullbitmap != NULL)
5677  {
5678  dataoffset = ARR_OVERHEAD_WITHNULLS(astate->ndims, astate->nitems);
5679  nbytes += dataoffset;
5680  }
5681  else
5682  {
5683  dataoffset = 0;
5684  nbytes += ARR_OVERHEAD_NONULLS(astate->ndims);
5685  }
5686 
5687  result = (ArrayType *) palloc0(nbytes);
5688  SET_VARSIZE(result, nbytes);
5689  result->ndim = astate->ndims;
5690  result->dataoffset = dataoffset;
5691  result->elemtype = astate->element_type;
5692 
5693  memcpy(ARR_DIMS(result), astate->dims, astate->ndims * sizeof(int));
5694  memcpy(ARR_LBOUND(result), astate->lbs, astate->ndims * sizeof(int));
5695  memcpy(ARR_DATA_PTR(result), astate->data, astate->nbytes);
5696 
5697  if (astate->nullbitmap != NULL)
5698  array_bitmap_copy(ARR_NULLBITMAP(result), 0,
5699  astate->nullbitmap, 0,
5700  astate->nitems);
5701  }
5702 
5703  MemoryContextSwitchTo(oldcontext);
5704 
5705  /* Clean up all the junk */
5706  if (release)
5707  {
5708  Assert(astate->private_cxt);
5709  MemoryContextDelete(astate->mcontext);
5710  }
5711 
5712  return PointerGetDatum(result);
5713 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:376

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

5405 {
5406  ArrayType *result;
5407  MemoryContext oldcontext;
5408 
5409  /* Build the final array result in rcontext */
5410  oldcontext = MemoryContextSwitchTo(rcontext);
5411 
5412  result = construct_md_array(astate->dvalues,
5413  astate->dnulls,
5414  ndims,
5415  dims,
5416  lbs,
5417  astate->element_type,
5418  astate->typlen,
5419  astate->typbyval,
5420  astate->typalign);
5421 
5422  MemoryContextSwitchTo(oldcontext);
5423 
5424  /* Clean up all the junk */
5425  if (release)
5426  {
5427  Assert(astate->private_cxt);
5428  MemoryContextDelete(astate->mcontext);
5429  }
5430 
5431  return PointerGetDatum(result);
5432 }

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(), 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 204 of file arrayutils.c.

205 {
206  int i,
207  j;
208 
209  dist[n - 1] = 0;
210  for (j = n - 2; j >= 0; j--)
211  {
212  dist[j] = prod[j] - 1;
213  for (i = j + 1; i < n; i++)
214  dist[j] -= (span[i] - 1) * prod[i];
215  }
216 }
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 188 of file arrayutils.c.

189 {
190  int i;
191 
192  prod[n - 1] = 1;
193  for (i = n - 2; i >= 0; i--)
194  prod[i] = prod[i + 1] * range[i + 1];
195 }
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(), array_slice_size(), and ReadArrayStr().

◆ mda_get_range()

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

Definition at line 174 of file arrayutils.c.

175 {
176  int i;
177 
178  for (i = 0; i < n; i++)
179  span[i] = endp[i] - st[i] + 1;
180 }

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 229 of file arrayutils.c.

230 {
231  int i;
232 
233  if (n <= 0)
234  return -1;
235 
236  curr[n - 1] = (curr[n - 1] + 1) % span[n - 1];
237  for (i = n - 1; i && curr[i] == 0; i--)
238  curr[i - 1] = (curr[i - 1] + 1) % span[i - 1];
239 
240  if (i)
241  return i;
242  if (curr[0])
243  return 0;
244 
245  return -1;
246 }

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

Referenced by ReadArrayStr().