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)
 
ArrayBuildStateinitArrayResultWithSize (Oid element_type, MemoryContext rcontext, bool subcontext, int initsize)
 
ArrayBuildStateaccumArrayResult (ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
 
Datum makeArrayResult (ArrayBuildState *astate, MemoryContext rcontext)
 
Datum makeMdArrayResult (ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
 
ArrayBuildStateArrinitArrayResultArr (Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateArraccumArrayResultArr (ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
 
Datum makeArrayResultArr (ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
 
ArrayBuildStateAnyinitArrayResultAny (Oid input_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateAnyaccumArrayResultAny (ArrayBuildStateAny *astate, Datum dvalue, bool disnull, Oid input_type, MemoryContext rcontext)
 
Datum makeArrayResultAny (ArrayBuildStateAny *astate, MemoryContext rcontext, bool release)
 
ArrayIterator array_create_iterator (ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
 
bool array_iterate (ArrayIterator iterator, Datum *value, bool *isnull)
 
void array_free_iterator (ArrayIterator iterator)
 
int ArrayGetOffset (int n, const int *dim, const int *lb, const int *indx)
 
int 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:497

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

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

5322 {
5323  MemoryContext oldcontext;
5324 
5325  if (astate == NULL)
5326  {
5327  /* First time through --- initialize */
5328  astate = initArrayResult(element_type, rcontext, true);
5329  }
5330  else
5331  {
5332  Assert(astate->element_type == element_type);
5333  }
5334 
5335  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5336 
5337  /* enlarge dvalues[]/dnulls[] if needed */
5338  if (astate->nelems >= astate->alen)
5339  {
5340  astate->alen *= 2;
5341  astate->dvalues = (Datum *)
5342  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5343  astate->dnulls = (bool *)
5344  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5345  }
5346 
5347  /*
5348  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5349  * it's varlena. (You might think that detoasting is not needed here
5350  * because construct_md_array can detoast the array elements later.
5351  * However, we must not let construct_md_array modify the ArrayBuildState
5352  * because that would mean array_agg_finalfn damages its input, which is
5353  * verboten. Also, this way frequently saves one copying step.)
5354  */
5355  if (!disnull && !astate->typbyval)
5356  {
5357  if (astate->typlen == -1)
5358  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5359  else
5360  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5361  }
5362 
5363  astate->dvalues[astate->nelems] = dvalue;
5364  astate->dnulls[astate->nelems] = disnull;
5365  astate->nelems++;
5366 
5367  MemoryContextSwitchTo(oldcontext);
5368 
5369  return astate;
5370 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5261
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:1476
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
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(), daitch_mokotoff_coding(), dblink_get_connections(), find_or_create_child_node(), multirange_agg_transfn(), optionListToArray(), parse_ident(), pg_get_statisticsobjdef_expressions(), pg_stats_ext_mcvlist_items(), PLySequence_ToArray_recurse(), populate_array_element(), range_agg_transfn(), regexp_split_to_array(), serialize_expr_stats(), split_text_accum_result(), transformRelOptions(), and tuple_data_split_internal().

◆ accumArrayResultAny()

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

Definition at line 5789 of file arrayfuncs.c.

5793 {
5794  if (astate == NULL)
5795  astate = initArrayResultAny(input_type, rcontext, true);
5796 
5797  if (astate->scalarstate)
5798  (void) accumArrayResult(astate->scalarstate,
5799  dvalue, disnull,
5800  input_type, rcontext);
5801  else
5802  (void) accumArrayResultArr(astate->arraystate,
5803  dvalue, disnull,
5804  input_type, rcontext);
5805 
5806  return astate;
5807 }
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5318
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5744
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5512
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 5512 of file arrayfuncs.c.

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

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

References Assert(), and nitems.

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

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

Definition at line 3735 of file arrayfuncs.c.

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

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

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

4728 {
4729  if (iterator->slice_ndim > 0)
4730  {
4731  pfree(iterator->slice_values);
4732  pfree(iterator->slice_nulls);
4733  }
4734  pfree(iterator);
4735 }

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:4749
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:4784
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4834
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:32
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: varatt.h:298

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

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

◆ array_get_slice()

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

Definition at line 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:5005
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3548
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:5065
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:174
signed int int32
Definition: c.h:478
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
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

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

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

◆ array_iterate()

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

Definition at line 4644 of file arrayfuncs.c.

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

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

Referenced by ExecEvalArrayCoerce().

◆ array_ref()

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

Definition at line 3126 of file arrayfuncs.c.

3129 {
3130  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3131  arraytyplen, elmlen, elmbyval, elmalign,
3132  isNull);
3133 }
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 3143 of file arrayfuncs.c.

3146 {
3148  nSubscripts, indx,
3149  dataValue, isNull,
3150  arraytyplen,
3151  elmlen, elmbyval, elmalign));
3152 }
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  /* palloc0 above already marked any inserted positions as nulls */
2487  /* Fix the inserted value */
2488  if (addedafter)
2489  array_set_isnull(newnullbitmap, newnitems - 1, isNull);
2490  else
2491  array_set_isnull(newnullbitmap, offset, isNull);
2492  /* Fix the copied range(s) */
2493  if (addedbefore)
2494  array_bitmap_copy(newnullbitmap, addedbefore,
2495  oldnullbitmap, 0,
2496  oldnitems);
2497  else
2498  {
2499  array_bitmap_copy(newnullbitmap, 0,
2500  oldnullbitmap, 0,
2501  offset);
2502  if (addedafter == 0)
2503  array_bitmap_copy(newnullbitmap, offset + 1,
2504  oldnullbitmap, offset + 1,
2505  oldnitems - offset - 1);
2506  }
2507  }
2508 
2509  return PointerGetDatum(newarray);
2510 }
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:2520
static void array_set_isnull(bits8 *nullbitmap, int offset, bool isNull)
Definition: arrayfuncs.c:4766
static int ArrayCastAndSet(Datum src, int typlen, bool typbyval, char typalign, char *dest)
Definition: arrayfuncs.c:4795
void ArrayCheckBounds(int ndim, const int *dims, const int *lb)
Definition: arrayutils.c:138

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

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

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

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

◆ ArrayGetNItems()

◆ ArrayGetNItemsSafe()

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

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

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

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

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

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

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

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

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

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

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

◆ CopyArrayEls()

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

Definition at line 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, nitems, pfree(), typalign, and values.

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

◆ DatumGetAnyArrayP()

AnyArrayType* DatumGetAnyArrayP ( Datum  d)

Definition at line 401 of file array_expanded.c.

402 {
403  ExpandedArrayHeader *eah;
404 
405  /*
406  * If it's an expanded array (RW or RO), return the header pointer.
407  */
409  {
410  eah = (ExpandedArrayHeader *) DatumGetEOHP(d);
411  Assert(eah->ea_magic == EA_MAGIC);
412  return (AnyArrayType *) eah;
413  }
414 
415  /* Else do regular detoasting as needed */
416  return (AnyArrayType *) PG_DETOAST_DATUM(d);
417 }
#define EA_MAGIC
Definition: array.h: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:135
#define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR)
Definition: varatt.h:296

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

Referenced by array_set_element_expanded(), and statext_expressions_load().

◆ DatumGetExpandedArrayX()

ExpandedArrayHeader* DatumGetExpandedArrayX ( Datum  d,
ArrayMetaState metacache 
)

Definition at line 372 of file array_expanded.c.

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

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

◆ deconstruct_array()

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

Definition at line 3599 of file arrayfuncs.c.

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

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

Referenced by _bt_preprocess_array_keys(), array_contain_compare(), array_set_slice(), array_shuffle_n(), array_to_json_internal(), array_to_jsonb_internal(), arrayconst_startup_fn(), compute_array_stats(), deconstruct_array_builtin(), deconstruct_expanded_array(), ExecIndexEvalArrayKeys(), extract_variadic_args(), get_attstatsslot(), ginarrayextract(), gincost_scalararrayopexpr(), ginqueryarrayextract(), 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(), pg_get_publication_tables(), plperl_ref_from_pg_array(), satisfies_hash_partition(), scalararraysel(), and text_format().

◆ deconstruct_array_builtin()

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

Definition at line 3665 of file arrayfuncs.c.

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

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:1021
#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 5261 of file arrayfuncs.c.

5262 {
5263  /*
5264  * When using a subcontext, we can afford to start with a somewhat larger
5265  * initial array size. Without subcontexts, we'd better hope that most of
5266  * the states stay small ...
5267  */
5268  return initArrayResultWithSize(element_type, rcontext, subcontext,
5269  subcontext ? 64 : 8);
5270 }
ArrayBuildState * initArrayResultWithSize(Oid element_type, MemoryContext rcontext, bool subcontext, int initsize)
Definition: arrayfuncs.c:5278

References initArrayResultWithSize().

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

◆ initArrayResultAny()

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

Definition at line 5744 of file arrayfuncs.c.

5745 {
5746  ArrayBuildStateAny *astate;
5747  Oid element_type = get_element_type(input_type);
5748 
5749  if (OidIsValid(element_type))
5750  {
5751  /* Array case */
5752  ArrayBuildStateArr *arraystate;
5753 
5754  arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5755  astate = (ArrayBuildStateAny *)
5756  MemoryContextAlloc(arraystate->mcontext,
5757  sizeof(ArrayBuildStateAny));
5758  astate->scalarstate = NULL;
5759  astate->arraystate = arraystate;
5760  }
5761  else
5762  {
5763  /* Scalar case */
5764  ArrayBuildState *scalarstate;
5765 
5766  /* Let's just check that we have a type that can be put into arrays */
5767  Assert(OidIsValid(get_array_type(input_type)));
5768 
5769  scalarstate = initArrayResult(input_type, rcontext, subcontext);
5770  astate = (ArrayBuildStateAny *)
5771  MemoryContextAlloc(scalarstate->mcontext,
5772  sizeof(ArrayBuildStateAny));
5773  astate->scalarstate = scalarstate;
5774  astate->arraystate = NULL;
5775  }
5776 
5777  return astate;
5778 }
#define OidIsValid(objectId)
Definition: c.h:759
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 5466 of file arrayfuncs.c.

5468 {
5469  ArrayBuildStateArr *astate;
5470  MemoryContext arr_context = rcontext; /* by default use the parent ctx */
5471 
5472  /* Lookup element type, unless element_type already provided */
5473  if (!OidIsValid(element_type))
5474  {
5475  element_type = get_element_type(array_type);
5476 
5477  if (!OidIsValid(element_type))
5478  ereport(ERROR,
5479  (errcode(ERRCODE_DATATYPE_MISMATCH),
5480  errmsg("data type %s is not an array type",
5481  format_type_be(array_type))));
5482  }
5483 
5484  /* Make a temporary context to hold all the junk */
5485  if (subcontext)
5486  arr_context = AllocSetContextCreate(rcontext,
5487  "accumArrayResultArr",
5489 
5490  /* Note we initialize all fields to zero */
5491  astate = (ArrayBuildStateArr *)
5492  MemoryContextAllocZero(arr_context, sizeof(ArrayBuildStateArr));
5493  astate->mcontext = arr_context;
5494  astate->private_cxt = subcontext;
5495 
5496  /* Save relevant datatype information */
5497  astate->array_type = array_type;
5498  astate->element_type = element_type;
5499 
5500  return astate;
5501 }
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1064
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
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_combine(), array_agg_array_deserialize(), array_agg_array_transfn(), and initArrayResultAny().

◆ initArrayResultWithSize()

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

Definition at line 5278 of file arrayfuncs.c.

5280 {
5281  ArrayBuildState *astate;
5282  MemoryContext arr_context = rcontext;
5283 
5284  /* Make a temporary context to hold all the junk */
5285  if (subcontext)
5286  arr_context = AllocSetContextCreate(rcontext,
5287  "accumArrayResult",
5289 
5290  astate = (ArrayBuildState *)
5291  MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
5292  astate->mcontext = arr_context;
5293  astate->private_cxt = subcontext;
5294  astate->alen = initsize;
5295  astate->dvalues = (Datum *)
5296  MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
5297  astate->dnulls = (bool *)
5298  MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
5299  astate->nelems = 0;
5300  astate->element_type = element_type;
5301  get_typlenbyvalalign(element_type,
5302  &astate->typlen,
5303  &astate->typbyval,
5304  &astate->typalign);
5305 
5306  return astate;
5307 }
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 array_agg_combine(), array_agg_deserialize(), and initArrayResult().

◆ makeArrayResult()

Datum makeArrayResult ( ArrayBuildState astate,
MemoryContext  rcontext 
)

Definition at line 5382 of file arrayfuncs.c.

5384 {
5385  int ndims;
5386  int dims[1];
5387  int lbs[1];
5388 
5389  /* If no elements were presented, we want to create an empty array */
5390  ndims = (astate->nelems > 0) ? 1 : 0;
5391  dims[0] = astate->nelems;
5392  lbs[0] = 1;
5393 
5394  return makeMdArrayResult(astate, ndims, dims, lbs, rcontext,
5395  astate->private_cxt);
5396 }
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5414

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

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

◆ makeArrayResultAny()

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

Definition at line 5817 of file arrayfuncs.c.

5819 {
5820  Datum result;
5821 
5822  if (astate->scalarstate)
5823  {
5824  /* Must use makeMdArrayResult to support "release" parameter */
5825  int ndims;
5826  int dims[1];
5827  int lbs[1];
5828 
5829  /* If no elements were presented, we want to create an empty array */
5830  ndims = (astate->scalarstate->nelems > 0) ? 1 : 0;
5831  dims[0] = astate->scalarstate->nelems;
5832  lbs[0] = 1;
5833 
5834  result = makeMdArrayResult(astate->scalarstate, ndims, dims, lbs,
5835  rcontext, release);
5836  }
5837  else
5838  {
5839  result = makeArrayResultArr(astate->arraystate,
5840  rcontext, release);
5841  }
5842  return result;
5843 }
Datum makeArrayResultArr(ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5665

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

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

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

5420 {
5421  ArrayType *result;
5422  MemoryContext oldcontext;
5423 
5424  /* Build the final array result in rcontext */
5425  oldcontext = MemoryContextSwitchTo(rcontext);
5426 
5427  result = construct_md_array(astate->dvalues,
5428  astate->dnulls,
5429  ndims,
5430  dims,
5431  lbs,
5432  astate->element_type,
5433  astate->typlen,
5434  astate->typbyval,
5435  astate->typalign);
5436 
5437  MemoryContextSwitchTo(oldcontext);
5438 
5439  /* Clean up all the junk */
5440  if (release)
5441  {
5442  Assert(astate->private_cxt);
5443  MemoryContextDelete(astate->mcontext);
5444  }
5445 
5446  return PointerGetDatum(result);
5447 }

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

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

◆ mda_get_offset_values()

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

Definition at line 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().