PostgreSQL Source Code  git master
arrayfuncs.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <math.h>
#include "access/hash.h"
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "utils/array.h"
#include "utils/arrayaccess.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/typcache.h"
Include dependency graph for arrayfuncs.c:

Go to the source code of this file.

Data Structures

struct  ArrayIteratorData
 
struct  generate_subscripts_fctx
 

Macros

#define ASSGN   "="
 
#define AARR_FREE_IF_COPY(array, n)
 
#define APPENDSTR(str)   (strcpy(p, (str)), p += strlen(p))
 
#define APPENDCHAR(ch)   (*p++ = (ch), *p = '\0')
 

Typedefs

typedef struct ArrayIteratorData ArrayIteratorData
 
typedef struct generate_subscripts_fctx generate_subscripts_fctx
 

Enumerations

enum  ArrayParseState {
  ARRAY_NO_LEVEL, ARRAY_LEVEL_STARTED, ARRAY_ELEM_STARTED, ARRAY_ELEM_COMPLETED,
  ARRAY_QUOTED_ELEM_STARTED, ARRAY_QUOTED_ELEM_COMPLETED, ARRAY_ELEM_DELIMITED, ARRAY_LEVEL_COMPLETED,
  ARRAY_LEVEL_DELIMITED
}
 

Functions

static bool array_isspace (char ch)
 
static int ArrayCount (const char *str, int *dim, char typdelim)
 
static void ReadArrayStr (char *arrayStr, const char *origStr, int nitems, int ndim, int *dim, FmgrInfo *inputproc, Oid typioparam, int32 typmod, char typdelim, int typlen, bool typbyval, char typalign, Datum *values, bool *nulls, bool *hasnulls, int32 *nbytes)
 
static void ReadArrayBinary (StringInfo buf, int nitems, FmgrInfo *receiveproc, Oid typioparam, int32 typmod, int typlen, bool typbyval, char typalign, Datum *values, bool *nulls, bool *hasnulls, int32 *nbytes)
 
static Datum array_get_element_expanded (Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
static Datum array_set_element_expanded (Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
static bool array_get_isnull (const bits8 *nullbitmap, int offset)
 
static void array_set_isnull (bits8 *nullbitmap, int offset, bool isNull)
 
static Datum ArrayCast (char *value, bool byval, int len)
 
static int ArrayCastAndSet (Datum src, int typlen, bool typbyval, char typalign, char *dest)
 
static char * array_seek (char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
 
static int array_nelems_size (char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
 
static int array_copy (char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
 
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)
 
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)
 
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)
 
static int array_cmp (FunctionCallInfo fcinfo)
 
static ArrayTypecreate_array_envelope (int ndims, int *dimv, int *lbv, int nbytes, Oid elmtype, int dataoffset)
 
static ArrayTypearray_fill_internal (ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
 
static ArrayTypearray_replace_internal (ArrayType *array, Datum search, bool search_isnull, Datum replace, bool replace_isnull, bool remove, Oid collation, FunctionCallInfo fcinfo)
 
static int width_bucket_array_float8 (Datum operand, ArrayType *thresholds)
 
static int width_bucket_array_fixed (Datum operand, ArrayType *thresholds, Oid collation, TypeCacheEntry *typentry)
 
static int width_bucket_array_variable (Datum operand, ArrayType *thresholds, Oid collation, TypeCacheEntry *typentry)
 
Datum array_in (PG_FUNCTION_ARGS)
 
void CopyArrayEls (ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
 
Datum array_out (PG_FUNCTION_ARGS)
 
Datum array_recv (PG_FUNCTION_ARGS)
 
Datum array_send (PG_FUNCTION_ARGS)
 
Datum array_ndims (PG_FUNCTION_ARGS)
 
Datum array_dims (PG_FUNCTION_ARGS)
 
Datum array_lower (PG_FUNCTION_ARGS)
 
Datum array_upper (PG_FUNCTION_ARGS)
 
Datum array_length (PG_FUNCTION_ARGS)
 
Datum array_cardinality (PG_FUNCTION_ARGS)
 
Datum array_get_element (Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
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_element (Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_set_slice (Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, Datum srcArrayDatum, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_ref (ArrayType *array, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
ArrayTypearray_set (ArrayType *array, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_map (Datum arrayd, ExprState *exprstate, ExprContext *econtext, Oid retType, ArrayMapState *amstate)
 
ArrayTypeconstruct_array (Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
 
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)
 
bool array_contains_nulls (ArrayType *array)
 
Datum array_eq (PG_FUNCTION_ARGS)
 
Datum array_ne (PG_FUNCTION_ARGS)
 
Datum array_lt (PG_FUNCTION_ARGS)
 
Datum array_gt (PG_FUNCTION_ARGS)
 
Datum array_le (PG_FUNCTION_ARGS)
 
Datum array_ge (PG_FUNCTION_ARGS)
 
Datum btarraycmp (PG_FUNCTION_ARGS)
 
Datum hash_array (PG_FUNCTION_ARGS)
 
Datum hash_array_extended (PG_FUNCTION_ARGS)
 
static bool array_contain_compare (AnyArrayType *array1, AnyArrayType *array2, Oid collation, bool matchall, void **fn_extra)
 
Datum arrayoverlap (PG_FUNCTION_ARGS)
 
Datum arraycontains (PG_FUNCTION_ARGS)
 
Datum arraycontained (PG_FUNCTION_ARGS)
 
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)
 
void array_bitmap_copy (bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
 
ArrayBuildStateinitArrayResult (Oid element_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateaccumArrayResult (ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
 
Datum makeArrayResult (ArrayBuildState *astate, MemoryContext rcontext)
 
Datum makeMdArrayResult (ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
 
ArrayBuildStateArrinitArrayResultArr (Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateArraccumArrayResultArr (ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
 
Datum makeArrayResultArr (ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
 
ArrayBuildStateAnyinitArrayResultAny (Oid input_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateAnyaccumArrayResultAny (ArrayBuildStateAny *astate, Datum dvalue, bool disnull, Oid input_type, MemoryContext rcontext)
 
Datum makeArrayResultAny (ArrayBuildStateAny *astate, MemoryContext rcontext, bool release)
 
Datum array_larger (PG_FUNCTION_ARGS)
 
Datum array_smaller (PG_FUNCTION_ARGS)
 
Datum generate_subscripts (PG_FUNCTION_ARGS)
 
Datum generate_subscripts_nodir (PG_FUNCTION_ARGS)
 
Datum array_fill_with_lower_bounds (PG_FUNCTION_ARGS)
 
Datum array_fill (PG_FUNCTION_ARGS)
 
Datum array_unnest (PG_FUNCTION_ARGS)
 
Datum array_remove (PG_FUNCTION_ARGS)
 
Datum array_replace (PG_FUNCTION_ARGS)
 
Datum width_bucket_array (PG_FUNCTION_ARGS)
 

Variables

bool Array_nulls = true
 

Macro Definition Documentation

◆ AARR_FREE_IF_COPY

#define AARR_FREE_IF_COPY (   array,
 
)
Value:
do { \
PG_FREE_IF_COPY(array, n); \
} while (0)
#define VARATT_IS_EXPANDED_HEADER(PTR)

Definition at line 47 of file arrayfuncs.c.

Referenced by array_cmp(), array_eq(), arraycontained(), arraycontains(), arrayoverlap(), hash_array(), and hash_array_extended().

◆ APPENDCHAR

#define APPENDCHAR (   ch)    (*p++ = (ch), *p = '\0')

Referenced by array_out().

◆ APPENDSTR

#define APPENDSTR (   str)    (strcpy(p, (str)), p += strlen(p))

Referenced by array_out().

◆ ASSGN

#define ASSGN   "="

Definition at line 45 of file arrayfuncs.c.

Referenced by array_in(), and array_out().

Typedef Documentation

◆ ArrayIteratorData

◆ generate_subscripts_fctx

Enumeration Type Documentation

◆ ArrayParseState

Enumerator
ARRAY_NO_LEVEL 
ARRAY_LEVEL_STARTED 
ARRAY_ELEM_STARTED 
ARRAY_ELEM_COMPLETED 
ARRAY_QUOTED_ELEM_STARTED 
ARRAY_QUOTED_ELEM_COMPLETED 
ARRAY_ELEM_DELIMITED 
ARRAY_LEVEL_COMPLETED 
ARRAY_LEVEL_DELIMITED 

Definition at line 53 of file arrayfuncs.c.

Function Documentation

◆ accumArrayResult()

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

Definition at line 5042 of file arrayfuncs.c.

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(), dblink_get_connections(), get_altertable_subcmdtypes(), optionListToArray(), parse_ident(), populate_array_element(), regexp_split_to_array(), SPI_sql_row_to_xmlelement(), text_to_array_internal(), transformRelOptions(), and tuple_data_split_internal().

5046 {
5047  MemoryContext oldcontext;
5048 
5049  if (astate == NULL)
5050  {
5051  /* First time through --- initialize */
5052  astate = initArrayResult(element_type, rcontext, true);
5053  }
5054  else
5055  {
5056  Assert(astate->element_type == element_type);
5057  }
5058 
5059  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5060 
5061  /* enlarge dvalues[]/dnulls[] if needed */
5062  if (astate->nelems >= astate->alen)
5063  {
5064  astate->alen *= 2;
5065  astate->dvalues = (Datum *)
5066  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5067  astate->dnulls = (bool *)
5068  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5069  }
5070 
5071  /*
5072  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5073  * it's varlena. (You might think that detoasting is not needed here
5074  * because construct_md_array can detoast the array elements later.
5075  * However, we must not let construct_md_array modify the ArrayBuildState
5076  * because that would mean array_agg_finalfn damages its input, which is
5077  * verboten. Also, this way frequently saves one copying step.)
5078  */
5079  if (!disnull && !astate->typbyval)
5080  {
5081  if (astate->typlen == -1)
5082  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5083  else
5084  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5085  }
5086 
5087  astate->dvalues[astate->nelems] = dvalue;
5088  astate->dnulls[astate->nelems] = disnull;
5089  astate->nelems++;
5090 
5091  MemoryContextSwitchTo(oldcontext);
5092 
5093  return astate;
5094 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:207
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5003
#define PointerGetDatum(X)
Definition: postgres.h:562
Datum * dvalues
Definition: array.h:175
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:181
Oid element_type
Definition: array.h:179
bool * dnulls
Definition: array.h:176
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:670
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
MemoryContext mcontext
Definition: array.h:174
int16 typlen
Definition: array.h:180

◆ accumArrayResultAny()

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

Definition at line 5513 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5517 {
5518  if (astate == NULL)
5519  astate = initArrayResultAny(input_type, rcontext, true);
5520 
5521  if (astate->scalarstate)
5522  (void) accumArrayResult(astate->scalarstate,
5523  dvalue, disnull,
5524  input_type, rcontext);
5525  else
5526  (void) accumArrayResultArr(astate->arraystate,
5527  dvalue, disnull,
5528  input_type, rcontext);
5529 
5530  return astate;
5531 }
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5468
ArrayBuildState * scalarstate
Definition: array.h:214
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5236
ArrayBuildStateArr * arraystate
Definition: array.h:215
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5042

◆ accumArrayResultArr()

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

Definition at line 5236 of file arrayfuncs.c.

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, DatumGetArrayTypeP, DatumGetPointer, ArrayBuildStateArr::dims, ereport, errcode(), errmsg(), ERROR, i, initArrayResultArr(), InvalidOid, ArrayBuildStateArr::lbs, Max, MAXDIM, ArrayBuildStateArr::mcontext, MemoryContextSwitchTo(), ArrayBuildStateArr::nbytes, ArrayBuildStateArr::ndims, ArrayIteratorData::nitems, ArrayBuildStateArr::nitems, ArrayBuildStateArr::nullbitmap, palloc(), pfree(), and repalloc().

Referenced by accumArrayResultAny(), and array_agg_array_transfn().

5240 {
5241  ArrayType *arg;
5242  MemoryContext oldcontext;
5243  int *dims,
5244  *lbs,
5245  ndims,
5246  nitems,
5247  ndatabytes;
5248  char *data;
5249  int i;
5250 
5251  /*
5252  * We disallow accumulating null subarrays. Another plausible definition
5253  * is to ignore them, but callers that want that can just skip calling
5254  * this function.
5255  */
5256  if (disnull)
5257  ereport(ERROR,
5258  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5259  errmsg("cannot accumulate null arrays")));
5260 
5261  /* Detoast input array in caller's context */
5262  arg = DatumGetArrayTypeP(dvalue);
5263 
5264  if (astate == NULL)
5265  astate = initArrayResultArr(array_type, InvalidOid, rcontext, true);
5266  else
5267  Assert(astate->array_type == array_type);
5268 
5269  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5270 
5271  /* Collect this input's dimensions */
5272  ndims = ARR_NDIM(arg);
5273  dims = ARR_DIMS(arg);
5274  lbs = ARR_LBOUND(arg);
5275  data = ARR_DATA_PTR(arg);
5276  nitems = ArrayGetNItems(ndims, dims);
5277  ndatabytes = ARR_SIZE(arg) - ARR_DATA_OFFSET(arg);
5278 
5279  if (astate->ndims == 0)
5280  {
5281  /* First input; check/save the dimensionality info */
5282 
5283  /* Should we allow empty inputs and just produce an empty output? */
5284  if (ndims == 0)
5285  ereport(ERROR,
5286  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5287  errmsg("cannot accumulate empty arrays")));
5288  if (ndims + 1 > MAXDIM)
5289  ereport(ERROR,
5290  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5291  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5292  ndims + 1, MAXDIM)));
5293 
5294  /*
5295  * The output array will have n+1 dimensions, with the ones after the
5296  * first matching the input's dimensions.
5297  */
5298  astate->ndims = ndims + 1;
5299  astate->dims[0] = 0;
5300  memcpy(&astate->dims[1], dims, ndims * sizeof(int));
5301  astate->lbs[0] = 1;
5302  memcpy(&astate->lbs[1], lbs, ndims * sizeof(int));
5303 
5304  /* Allocate at least enough data space for this item */
5305  astate->abytes = 1024;
5306  while (astate->abytes <= ndatabytes)
5307  astate->abytes *= 2;
5308  astate->data = (char *) palloc(astate->abytes);
5309  }
5310  else
5311  {
5312  /* Second or later input: must match first input's dimensionality */
5313  if (astate->ndims != ndims + 1)
5314  ereport(ERROR,
5315  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5316  errmsg("cannot accumulate arrays of different dimensionality")));
5317  for (i = 0; i < ndims; i++)
5318  {
5319  if (astate->dims[i + 1] != dims[i] || astate->lbs[i + 1] != lbs[i])
5320  ereport(ERROR,
5321  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5322  errmsg("cannot accumulate arrays of different dimensionality")));
5323  }
5324 
5325  /* Enlarge data space if needed */
5326  if (astate->nbytes + ndatabytes > astate->abytes)
5327  {
5328  astate->abytes = Max(astate->abytes * 2,
5329  astate->nbytes + ndatabytes);
5330  astate->data = (char *) repalloc(astate->data, astate->abytes);
5331  }
5332  }
5333 
5334  /*
5335  * Copy the data portion of the sub-array. Note we assume that the
5336  * advertised data length of the sub-array is properly aligned. We do not
5337  * have to worry about detoasting elements since whatever's in the
5338  * sub-array should be OK already.
5339  */
5340  memcpy(astate->data + astate->nbytes, data, ndatabytes);
5341  astate->nbytes += ndatabytes;
5342 
5343  /* Deal with null bitmap if needed */
5344  if (astate->nullbitmap || ARR_HASNULL(arg))
5345  {
5346  int newnitems = astate->nitems + nitems;
5347 
5348  if (astate->nullbitmap == NULL)
5349  {
5350  /*
5351  * First input with nulls; we must retrospectively handle any
5352  * previous inputs by marking all their items non-null.
5353  */
5354  astate->aitems = 256;
5355  while (astate->aitems <= newnitems)
5356  astate->aitems *= 2;
5357  astate->nullbitmap = (bits8 *) palloc((astate->aitems + 7) / 8);
5358  array_bitmap_copy(astate->nullbitmap, 0,
5359  NULL, 0,
5360  astate->nitems);
5361  }
5362  else if (newnitems > astate->aitems)
5363  {
5364  astate->aitems = Max(astate->aitems * 2, newnitems);
5365  astate->nullbitmap = (bits8 *)
5366  repalloc(astate->nullbitmap, (astate->aitems + 7) / 8);
5367  }
5368  array_bitmap_copy(astate->nullbitmap, astate->nitems,
5369  ARR_NULLBITMAP(arg), 0,
5370  nitems);
5371  }
5372 
5373  astate->nitems += nitems;
5374  astate->dims[0] += 1;
5375 
5376  MemoryContextSwitchTo(oldcontext);
5377 
5378  /* Release detoasted copy if any */
5379  if ((Pointer) arg != DatumGetPointer(dvalue))
5380  pfree(arg);
5381 
5382  return astate;
5383 }
#define ARR_SIZE(a)
Definition: array.h:274
#define MAXDIM
Definition: c.h:467
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4676
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5190
#define ARR_DATA_OFFSET(a)
Definition: array.h:301
#define ARR_LBOUND(a)
Definition: array.h:281
bits8 * nullbitmap
Definition: array.h:194
void pfree(void *pointer)
Definition: mcxt.c:949
char * Pointer
Definition: c.h:273
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define ereport(elevel, rest)
Definition: elog.h:122
uint8 bits8
Definition: c.h:303
#define InvalidOid
Definition: postgres_ext.h:36
int lbs[MAXDIM]
Definition: array.h:201
#define Max(x, y)
Definition: c.h:796
#define Assert(condition)
Definition: c.h:670
#define ARR_NDIM(a)
Definition: array.h:275
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
#define DatumGetPointer(X)
Definition: postgres.h:555
int dims[MAXDIM]
Definition: array.h:200
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void * arg
#define ARR_NULLBITMAP(a)
Definition: array.h:285
MemoryContext mcontext
Definition: array.h:192
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ array_bitmap_copy()

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

Definition at line 4676 of file arrayfuncs.c.

References Assert.

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

4679 {
4680  int destbitmask,
4681  destbitval,
4682  srcbitmask,
4683  srcbitval;
4684 
4685  Assert(destbitmap);
4686  if (nitems <= 0)
4687  return; /* don't risk fetch off end of memory */
4688  destbitmap += destoffset / 8;
4689  destbitmask = 1 << (destoffset % 8);
4690  destbitval = *destbitmap;
4691  if (srcbitmap)
4692  {
4693  srcbitmap += srcoffset / 8;
4694  srcbitmask = 1 << (srcoffset % 8);
4695  srcbitval = *srcbitmap;
4696  while (nitems-- > 0)
4697  {
4698  if (srcbitval & srcbitmask)
4699  destbitval |= destbitmask;
4700  else
4701  destbitval &= ~destbitmask;
4702  destbitmask <<= 1;
4703  if (destbitmask == 0x100)
4704  {
4705  *destbitmap++ = destbitval;
4706  destbitmask = 1;
4707  if (nitems > 0)
4708  destbitval = *destbitmap;
4709  }
4710  srcbitmask <<= 1;
4711  if (srcbitmask == 0x100)
4712  {
4713  srcbitmap++;
4714  srcbitmask = 1;
4715  if (nitems > 0)
4716  srcbitval = *srcbitmap;
4717  }
4718  }
4719  if (destbitmask != 1)
4720  *destbitmap = destbitval;
4721  }
4722  else
4723  {
4724  while (nitems-- > 0)
4725  {
4726  destbitval |= destbitmask;
4727  destbitmask <<= 1;
4728  if (destbitmask == 0x100)
4729  {
4730  *destbitmap++ = destbitval;
4731  destbitmask = 1;
4732  if (nitems > 0)
4733  destbitval = *destbitmap;
4734  }
4735  }
4736  if (destbitmask != 1)
4737  *destbitmap = destbitval;
4738  }
4739 }
#define Assert(condition)
Definition: c.h:670

◆ array_cardinality()

Datum array_cardinality ( PG_FUNCTION_ARGS  )

Definition at line 1777 of file arrayfuncs.c.

References AARR_DIMS, AARR_NDIM, ArrayGetNItems(), PG_GETARG_ANY_ARRAY_P, and PG_RETURN_INT32.

1778 {
1780 
1782 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:259
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
#define AARR_DIMS(a)
Definition: array.h:321
#define AARR_NDIM(a)
Definition: array.h:313

◆ array_cmp()

static int array_cmp ( FunctionCallInfo  fcinfo)
static

Definition at line 3734 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_FREE_IF_COPY, AARR_LBOUND, AARR_NDIM, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, array_iter_next(), array_iter_setup(), ArrayGetNItems(), TypeCacheEntry::cmp_proc_finfo, DatumGetInt32, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_oid, format_type_be(), FunctionCallInvoke, i, InitFunctionCallInfoData, FunctionCallInfoData::isnull, lookup_type_cache(), Min, OidIsValid, PG_GET_COLLATION, PG_GETARG_ANY_ARRAY_P, TypeCacheEntry::typalign, ArrayIteratorData::typalign, TypeCacheEntry::typbyval, ArrayIteratorData::typbyval, TypeCacheEntry::type_id, TYPECACHE_CMP_PROC_FINFO, TypeCacheEntry::typlen, and ArrayIteratorData::typlen.

Referenced by array_ge(), array_gt(), array_larger(), array_le(), array_lt(), array_smaller(), and btarraycmp().

3735 {
3736  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY_P(0);
3737  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY_P(1);
3738  Oid collation = PG_GET_COLLATION();
3739  int ndims1 = AARR_NDIM(array1);
3740  int ndims2 = AARR_NDIM(array2);
3741  int *dims1 = AARR_DIMS(array1);
3742  int *dims2 = AARR_DIMS(array2);
3743  int nitems1 = ArrayGetNItems(ndims1, dims1);
3744  int nitems2 = ArrayGetNItems(ndims2, dims2);
3745  Oid element_type = AARR_ELEMTYPE(array1);
3746  int result = 0;
3747  TypeCacheEntry *typentry;
3748  int typlen;
3749  bool typbyval;
3750  char typalign;
3751  int min_nitems;
3752  array_iter it1;
3753  array_iter it2;
3754  int i;
3755  FunctionCallInfoData locfcinfo;
3756 
3757  if (element_type != AARR_ELEMTYPE(array2))
3758  ereport(ERROR,
3759  (errcode(ERRCODE_DATATYPE_MISMATCH),
3760  errmsg("cannot compare arrays of different element types")));
3761 
3762  /*
3763  * We arrange to look up the comparison function only once per series of
3764  * calls, assuming the element type doesn't change underneath us. The
3765  * typcache is used so that we have no memory leakage when being used as
3766  * an index support function.
3767  */
3768  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3769  if (typentry == NULL ||
3770  typentry->type_id != element_type)
3771  {
3772  typentry = lookup_type_cache(element_type,
3774  if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
3775  ereport(ERROR,
3776  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3777  errmsg("could not identify a comparison function for type %s",
3778  format_type_be(element_type))));
3779  fcinfo->flinfo->fn_extra = (void *) typentry;
3780  }
3781  typlen = typentry->typlen;
3782  typbyval = typentry->typbyval;
3783  typalign = typentry->typalign;
3784 
3785  /*
3786  * apply the operator to each pair of array elements.
3787  */
3788  InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
3789  collation, NULL, NULL);
3790 
3791  /* Loop over source data */
3792  min_nitems = Min(nitems1, nitems2);
3793  array_iter_setup(&it1, array1);
3794  array_iter_setup(&it2, array2);
3795 
3796  for (i = 0; i < min_nitems; i++)
3797  {
3798  Datum elt1;
3799  Datum elt2;
3800  bool isnull1;
3801  bool isnull2;
3802  int32 cmpresult;
3803 
3804  /* Get elements, checking for NULL */
3805  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
3806  elt2 = array_iter_next(&it2, &isnull2, i, typlen, typbyval, typalign);
3807 
3808  /*
3809  * We consider two NULLs equal; NULL > not-NULL.
3810  */
3811  if (isnull1 && isnull2)
3812  continue;
3813  if (isnull1)
3814  {
3815  /* arg1 is greater than arg2 */
3816  result = 1;
3817  break;
3818  }
3819  if (isnull2)
3820  {
3821  /* arg1 is less than arg2 */
3822  result = -1;
3823  break;
3824  }
3825 
3826  /* Compare the pair of elements */
3827  locfcinfo.arg[0] = elt1;
3828  locfcinfo.arg[1] = elt2;
3829  locfcinfo.argnull[0] = false;
3830  locfcinfo.argnull[1] = false;
3831  locfcinfo.isnull = false;
3832  cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
3833 
3834  if (cmpresult == 0)
3835  continue; /* equal */
3836 
3837  if (cmpresult < 0)
3838  {
3839  /* arg1 is less than arg2 */
3840  result = -1;
3841  break;
3842  }
3843  else
3844  {
3845  /* arg1 is greater than arg2 */
3846  result = 1;
3847  break;
3848  }
3849  }
3850 
3851  /*
3852  * If arrays contain same data (up to end of shorter one), apply
3853  * additional rules to sort by dimensionality. The relative significance
3854  * of the different bits of information is historical; mainly we just care
3855  * that we don't say "equal" for arrays of different dimensionality.
3856  */
3857  if (result == 0)
3858  {
3859  if (nitems1 != nitems2)
3860  result = (nitems1 < nitems2) ? -1 : 1;
3861  else if (ndims1 != ndims2)
3862  result = (ndims1 < ndims2) ? -1 : 1;
3863  else
3864  {
3865  for (i = 0; i < ndims1; i++)
3866  {
3867  if (dims1[i] != dims2[i])
3868  {
3869  result = (dims1[i] < dims2[i]) ? -1 : 1;
3870  break;
3871  }
3872  }
3873  if (result == 0)
3874  {
3875  int *lbound1 = AARR_LBOUND(array1);
3876  int *lbound2 = AARR_LBOUND(array2);
3877 
3878  for (i = 0; i < ndims1; i++)
3879  {
3880  if (lbound1[i] != lbound2[i])
3881  {
3882  result = (lbound1[i] < lbound2[i]) ? -1 : 1;
3883  break;
3884  }
3885  }
3886  }
3887  }
3888  }
3889 
3890  /* Avoid leaking memory when handed toasted input. */
3891  AARR_FREE_IF_COPY(array1, 0);
3892  AARR_FREE_IF_COPY(array2, 1);
3893 
3894  return result;
3895 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:259
#define DatumGetInt32(X)
Definition: postgres.h:478
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
#define Min(x, y)
Definition: c.h:802
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
bool typbyval
Definition: typcache.h:38
#define OidIsValid(objectId)
Definition: c.h:576
#define PG_GET_COLLATION()
Definition: fmgr.h:163
signed int int32
Definition: c.h:284
FmgrInfo cmp_proc_finfo
Definition: typcache.h:72
FmgrInfo * flinfo
Definition: fmgr.h:79
#define ERROR
Definition: elog.h:43
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:137
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:86
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define AARR_DIMS(a)
Definition: array.h:321
#define AARR_ELEMTYPE(a)
Definition: array.h:319
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:311
Oid fn_oid
Definition: fmgr.h:59
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:85
#define AARR_LBOUND(a)
Definition: array.h:323
#define AARR_NDIM(a)
Definition: array.h:313
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:120
#define AARR_FREE_IF_COPY(array, n)
Definition: arrayfuncs.c:47
void * fn_extra
Definition: fmgr.h:64
char typalign
Definition: typcache.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:130

◆ array_contain_compare()

static bool array_contain_compare ( AnyArrayType array1,
AnyArrayType array2,
Oid  collation,
bool  matchall,
void **  fn_extra 
)
static

Definition at line 4091 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_NDIM, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, array_iter_next(), array_iter_setup(), ArrayGetNItems(), DatumGetBool, deconstruct_array(), deconstruct_expanded_array(), ExpandedArrayHeader::dnulls, ExpandedArrayHeader::dvalues, TypeCacheEntry::eq_opr_finfo, ereport, errcode(), errmsg(), ERROR, AnyArrayType::flt, FmgrInfo::fn_oid, format_type_be(), FunctionCallInvoke, i, InitFunctionCallInfoData, FunctionCallInfoData::isnull, lookup_type_cache(), ExpandedArrayHeader::nelems, OidIsValid, TypeCacheEntry::typalign, ArrayIteratorData::typalign, TypeCacheEntry::typbyval, ArrayIteratorData::typbyval, TypeCacheEntry::type_id, TYPECACHE_EQ_OPR_FINFO, TypeCacheEntry::typlen, ArrayIteratorData::typlen, VARATT_IS_EXPANDED_HEADER, and AnyArrayType::xpn.

Referenced by arraycontained(), arraycontains(), and arrayoverlap().

4093 {
4094  bool result = matchall;
4095  Oid element_type = AARR_ELEMTYPE(array1);
4096  TypeCacheEntry *typentry;
4097  int nelems1;
4098  Datum *values2;
4099  bool *nulls2;
4100  int nelems2;
4101  int typlen;
4102  bool typbyval;
4103  char typalign;
4104  int i;
4105  int j;
4106  array_iter it1;
4107  FunctionCallInfoData locfcinfo;
4108 
4109  if (element_type != AARR_ELEMTYPE(array2))
4110  ereport(ERROR,
4111  (errcode(ERRCODE_DATATYPE_MISMATCH),
4112  errmsg("cannot compare arrays of different element types")));
4113 
4114  /*
4115  * We arrange to look up the equality function only once per series of
4116  * calls, assuming the element type doesn't change underneath us. The
4117  * typcache is used so that we have no memory leakage when being used as
4118  * an index support function.
4119  */
4120  typentry = (TypeCacheEntry *) *fn_extra;
4121  if (typentry == NULL ||
4122  typentry->type_id != element_type)
4123  {
4124  typentry = lookup_type_cache(element_type,
4126  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
4127  ereport(ERROR,
4128  (errcode(ERRCODE_UNDEFINED_FUNCTION),
4129  errmsg("could not identify an equality operator for type %s",
4130  format_type_be(element_type))));
4131  *fn_extra = (void *) typentry;
4132  }
4133  typlen = typentry->typlen;
4134  typbyval = typentry->typbyval;
4135  typalign = typentry->typalign;
4136 
4137  /*
4138  * Since we probably will need to scan array2 multiple times, it's
4139  * worthwhile to use deconstruct_array on it. We scan array1 the hard way
4140  * however, since we very likely won't need to look at all of it.
4141  */
4142  if (VARATT_IS_EXPANDED_HEADER(array2))
4143  {
4144  /* This should be safe even if input is read-only */
4145  deconstruct_expanded_array(&(array2->xpn));
4146  values2 = array2->xpn.dvalues;
4147  nulls2 = array2->xpn.dnulls;
4148  nelems2 = array2->xpn.nelems;
4149  }
4150  else
4151  deconstruct_array(&(array2->flt),
4152  element_type, typlen, typbyval, typalign,
4153  &values2, &nulls2, &nelems2);
4154 
4155  /*
4156  * Apply the comparison operator to each pair of array elements.
4157  */
4158  InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
4159  collation, NULL, NULL);
4160 
4161  /* Loop over source data */
4162  nelems1 = ArrayGetNItems(AARR_NDIM(array1), AARR_DIMS(array1));
4163  array_iter_setup(&it1, array1);
4164 
4165  for (i = 0; i < nelems1; i++)
4166  {
4167  Datum elt1;
4168  bool isnull1;
4169 
4170  /* Get element, checking for NULL */
4171  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
4172 
4173  /*
4174  * We assume that the comparison operator is strict, so a NULL can't
4175  * match anything. XXX this diverges from the "NULL=NULL" behavior of
4176  * array_eq, should we act like that?
4177  */
4178  if (isnull1)
4179  {
4180  if (matchall)
4181  {
4182  result = false;
4183  break;
4184  }
4185  continue;
4186  }
4187 
4188  for (j = 0; j < nelems2; j++)
4189  {
4190  Datum elt2 = values2[j];
4191  bool isnull2 = nulls2 ? nulls2[j] : false;
4192  bool oprresult;
4193 
4194  if (isnull2)
4195  continue; /* can't match */
4196 
4197  /*
4198  * Apply the operator to the element pair
4199  */
4200  locfcinfo.arg[0] = elt1;
4201  locfcinfo.arg[1] = elt2;
4202  locfcinfo.argnull[0] = false;
4203  locfcinfo.argnull[1] = false;
4204  locfcinfo.isnull = false;
4205  oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
4206  if (oprresult)
4207  break;
4208  }
4209 
4210  if (j < nelems2)
4211  {
4212  /* found a match for elt1 */
4213  if (!matchall)
4214  {
4215  result = true;
4216  break;
4217  }
4218  }
4219  else
4220  {
4221  /* no match for elt1 */
4222  if (matchall)
4223  {
4224  result = false;
4225  break;
4226  }
4227  }
4228  }
4229 
4230  return result;
4231 }
void deconstruct_expanded_array(ExpandedArrayHeader *eah)
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:129
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
ExpandedArrayHeader xpn
Definition: array.h:165
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
Datum * dvalues
Definition: array.h:134
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
bool typbyval
Definition: typcache.h:38
#define OidIsValid(objectId)
Definition: c.h:576
#define ERROR
Definition: elog.h:43
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:137
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
#define DatumGetBool(X)
Definition: postgres.h:399
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:86
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define AARR_DIMS(a)
Definition: array.h:321
#define AARR_ELEMTYPE(a)
Definition: array.h:319
FmgrInfo eq_opr_finfo
Definition: typcache.h:71
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:311
Oid fn_oid
Definition: fmgr.h:59
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:85
#define AARR_NDIM(a)
Definition: array.h:313
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:120
#define VARATT_IS_EXPANDED_HEADER(PTR)
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
char typalign
Definition: typcache.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:797
ArrayType flt
Definition: array.h:164
int i

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

Definition at line 3516 of file arrayfuncs.c.

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

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

3517 {
3518  int nelems;
3519  bits8 *bitmap;
3520  int bitmask;
3521 
3522  /* Easy answer if there's no null bitmap */
3523  if (!ARR_HASNULL(array))
3524  return false;
3525 
3526  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3527 
3528  bitmap = ARR_NULLBITMAP(array);
3529 
3530  /* check whole bytes of the bitmap byte-at-a-time */
3531  while (nelems >= 8)
3532  {
3533  if (*bitmap != 0xFF)
3534  return true;
3535  bitmap++;
3536  nelems -= 8;
3537  }
3538 
3539  /* check last partial byte */
3540  bitmask = 1;
3541  while (nelems > 0)
3542  {
3543  if ((*bitmap & bitmask) == 0)
3544  return true;
3545  bitmask <<= 1;
3546  nelems--;
3547  }
3548 
3549  return false;
3550 }
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_HASNULL(a)
Definition: array.h:276
uint8 bits8
Definition: c.h:303
#define ARR_NDIM(a)
Definition: array.h:275
#define ARR_NULLBITMAP(a)
Definition: array.h:285

◆ array_copy()

static int array_copy ( char *  destptr,
int  nitems,
char *  srcptr,
int  offset,
bits8 nullbitmap,
int  typlen,
bool  typbyval,
char  typalign 
)
static

Definition at line 4646 of file arrayfuncs.c.

References array_nelems_size().

Referenced by array_extract_slice(), and array_insert_slice().

4649 {
4650  int numbytes;
4651 
4652  numbytes = array_nelems_size(srcptr, offset, nullbitmap, nitems,
4653  typlen, typbyval, typalign);
4654  memcpy(destptr, srcptr, numbytes);
4655  return numbytes;
4656 }
static int array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4624

◆ array_create_iterator()

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

Definition at line 4307 of file arrayfuncs.c.

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

4308 {
4309  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4310 
4311  /*
4312  * Sanity-check inputs --- caller should have got this right already
4313  */
4314  Assert(PointerIsValid(arr));
4315  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4316  elog(ERROR, "invalid arguments to array_create_iterator");
4317 
4318  /*
4319  * Remember basic info about the array and its element type
4320  */
4321  iterator->arr = arr;
4322  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4323  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4324 
4325  if (mstate != NULL)
4326  {
4327  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4328 
4329  iterator->typlen = mstate->typlen;
4330  iterator->typbyval = mstate->typbyval;
4331  iterator->typalign = mstate->typalign;
4332  }
4333  else
4335  &iterator->typlen,
4336  &iterator->typbyval,
4337  &iterator->typalign);
4338 
4339  /*
4340  * Remember the slicing parameters.
4341  */
4342  iterator->slice_ndim = slice_ndim;
4343 
4344  if (slice_ndim > 0)
4345  {
4346  /*
4347  * Get pointers into the array's dims and lbound arrays to represent
4348  * the dims/lbound arrays of a slice. These are the same as the
4349  * rightmost N dimensions of the array.
4350  */
4351  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4352  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4353 
4354  /*
4355  * Compute number of elements in a slice.
4356  */
4357  iterator->slice_len = ArrayGetNItems(slice_ndim,
4358  iterator->slice_dims);
4359 
4360  /*
4361  * Create workspace for building sub-arrays.
4362  */
4363  iterator->slice_values = (Datum *)
4364  palloc(iterator->slice_len * sizeof(Datum));
4365  iterator->slice_nulls = (bool *)
4366  palloc(iterator->slice_len * sizeof(bool));
4367  }
4368 
4369  /*
4370  * Initialize our data pointer and linear element number. These will
4371  * advance through the array during array_iterate().
4372  */
4373  iterator->data_ptr = ARR_DATA_PTR(arr);
4374  iterator->current_item = 0;
4375 
4376  return iterator;
4377 }
bits8 * nullbitmap
Definition: arrayfuncs.c:71
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2040
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_LBOUND(a)
Definition: array.h:281
bool typbyval
Definition: array.h:225
bool * slice_nulls
Definition: arrayfuncs.c:83
#define ERROR
Definition: elog.h:43
Datum * slice_values
Definition: arrayfuncs.c:82
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
int16 typlen
Definition: array.h:224
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:670
#define ARR_NDIM(a)
Definition: array.h:275
char typalign
Definition: array.h:226
void * palloc(Size size)
Definition: mcxt.c:848
Oid element_type
Definition: array.h:223
#define elog
Definition: elog.h:219
#define PointerIsValid(pointer)
Definition: c.h:564
#define ARR_ELEMTYPE(a)
Definition: array.h:277
#define ARR_NULLBITMAP(a)
Definition: array.h:285
ArrayType * arr
Definition: arrayfuncs.c:70

◆ array_dims()

Datum array_dims ( PG_FUNCTION_ARGS  )

Definition at line 1655 of file arrayfuncs.c.

References AARR_DIMS, AARR_LBOUND, AARR_NDIM, buf, cstring_to_text(), i, MAXDIM, PG_GETARG_ANY_ARRAY_P, PG_RETURN_NULL, and PG_RETURN_TEXT_P.

1656 {
1658  char *p;
1659  int i;
1660  int *dimv,
1661  *lb;
1662 
1663  /*
1664  * 33 since we assume 15 digits per number + ':' +'[]'
1665  *
1666  * +1 for trailing null
1667  */
1668  char buf[MAXDIM * 33 + 1];
1669 
1670  /* Sanity check: does it look like an array at all? */
1671  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1672  PG_RETURN_NULL();
1673 
1674  dimv = AARR_DIMS(v);
1675  lb = AARR_LBOUND(v);
1676 
1677  p = buf;
1678  for (i = 0; i < AARR_NDIM(v); i++)
1679  {
1680  sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1);
1681  p += strlen(p);
1682  }
1683 
1685 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:259
#define MAXDIM
Definition: c.h:467
static char * buf
Definition: pg_test_fsync.c:67
#define AARR_DIMS(a)
Definition: array.h:321
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
text * cstring_to_text(const char *s)
Definition: varlena.c:149
#define AARR_LBOUND(a)
Definition: array.h:323
#define AARR_NDIM(a)
Definition: array.h:313
int i
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ array_eq()

Datum array_eq ( PG_FUNCTION_ARGS  )

Definition at line 3563 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_FREE_IF_COPY, AARR_LBOUND, AARR_NDIM, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, array_iter_next(), array_iter_setup(), ArrayGetNItems(), DatumGetBool, TypeCacheEntry::eq_opr_finfo, ereport, errcode(), errmsg(), ERROR, FmgrInfo::fn_oid, format_type_be(), FunctionCallInvoke, i, InitFunctionCallInfoData, FunctionCallInfoData::isnull, lookup_type_cache(), ArrayIteratorData::nitems, OidIsValid, PG_GET_COLLATION, PG_GETARG_ANY_ARRAY_P, PG_RETURN_BOOL, TypeCacheEntry::typalign, ArrayIteratorData::typalign, TypeCacheEntry::typbyval, ArrayIteratorData::typbyval, TypeCacheEntry::type_id, TYPECACHE_EQ_OPR_FINFO, TypeCacheEntry::typlen, and ArrayIteratorData::typlen.

Referenced by array_ne().

3564 {
3565  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY_P(0);
3566  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY_P(1);
3567  Oid collation = PG_GET_COLLATION();
3568  int ndims1 = AARR_NDIM(array1);
3569  int ndims2 = AARR_NDIM(array2);
3570  int *dims1 = AARR_DIMS(array1);
3571  int *dims2 = AARR_DIMS(array2);
3572  int *lbs1 = AARR_LBOUND(array1);
3573  int *lbs2 = AARR_LBOUND(array2);
3574  Oid element_type = AARR_ELEMTYPE(array1);
3575  bool result = true;
3576  int nitems;
3577  TypeCacheEntry *typentry;
3578  int typlen;
3579  bool typbyval;
3580  char typalign;
3581  array_iter it1;
3582  array_iter it2;
3583  int i;
3584  FunctionCallInfoData locfcinfo;
3585 
3586  if (element_type != AARR_ELEMTYPE(array2))
3587  ereport(ERROR,
3588  (errcode(ERRCODE_DATATYPE_MISMATCH),
3589  errmsg("cannot compare arrays of different element types")));
3590 
3591  /* fast path if the arrays do not have the same dimensionality */
3592  if (ndims1 != ndims2 ||
3593  memcmp(dims1, dims2, ndims1 * sizeof(int)) != 0 ||
3594  memcmp(lbs1, lbs2, ndims1 * sizeof(int)) != 0)
3595  result = false;
3596  else
3597  {
3598  /*
3599  * We arrange to look up the equality function only once per series of
3600  * calls, assuming the element type doesn't change underneath us. The
3601  * typcache is used so that we have no memory leakage when being used
3602  * as an index support function.
3603  */
3604  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3605  if (typentry == NULL ||
3606  typentry->type_id != element_type)
3607  {
3608  typentry = lookup_type_cache(element_type,
3610  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
3611  ereport(ERROR,
3612  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3613  errmsg("could not identify an equality operator for type %s",
3614  format_type_be(element_type))));
3615  fcinfo->flinfo->fn_extra = (void *) typentry;
3616  }
3617  typlen = typentry->typlen;
3618  typbyval = typentry->typbyval;
3619  typalign = typentry->typalign;
3620 
3621  /*
3622  * apply the operator to each pair of array elements.
3623  */
3624  InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
3625  collation, NULL, NULL);
3626 
3627  /* Loop over source data */
3628  nitems = ArrayGetNItems(ndims1, dims1);
3629  array_iter_setup(&it1, array1);
3630  array_iter_setup(&it2, array2);
3631 
3632  for (i = 0; i < nitems; i++)
3633  {
3634  Datum elt1;
3635  Datum elt2;
3636  bool isnull1;
3637  bool isnull2;
3638  bool oprresult;
3639 
3640  /* Get elements, checking for NULL */
3641  elt1 = array_iter_next(&it1, &isnull1, i,
3642  typlen, typbyval, typalign);
3643  elt2 = array_iter_next(&it2, &isnull2, i,
3644  typlen, typbyval, typalign);
3645 
3646  /*
3647  * We consider two NULLs equal; NULL and not-NULL are unequal.
3648  */
3649  if (isnull1 && isnull2)
3650  continue;
3651  if (isnull1 || isnull2)
3652  {
3653  result = false;
3654  break;
3655  }
3656 
3657  /*
3658  * Apply the operator to the element pair
3659  */
3660  locfcinfo.arg[0] = elt1;
3661  locfcinfo.arg[1] = elt2;
3662  locfcinfo.argnull[0] = false;
3663  locfcinfo.argnull[1] = false;
3664  locfcinfo.isnull = false;
3665  oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
3666  if (!oprresult)
3667  {
3668  result = false;
3669  break;
3670  }
3671  }
3672  }
3673 
3674  /* Avoid leaking memory when handed toasted input. */
3675  AARR_FREE_IF_COPY(array1, 0);
3676  AARR_FREE_IF_COPY(array2, 1);
3677 
3678  PG_RETURN_BOOL(result);
3679 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:259
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:129
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
bool typbyval
Definition: typcache.h:38
#define OidIsValid(objectId)
Definition: c.h:576
#define PG_GET_COLLATION()
Definition: fmgr.h:163
#define ERROR
Definition: elog.h:43
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:137
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
#define DatumGetBool(X)
Definition: postgres.h:399
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:86
#define ereport(elevel, rest)
Definition: elog.h:122
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
uintptr_t Datum
Definition: postgres.h:372
#define AARR_DIMS(a)
Definition: array.h:321
#define AARR_ELEMTYPE(a)
Definition: array.h:319
FmgrInfo eq_opr_finfo
Definition: typcache.h:71
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:311
Oid fn_oid
Definition: fmgr.h:59
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:85
#define AARR_LBOUND(a)
Definition: array.h:323
#define AARR_NDIM(a)
Definition: array.h:313
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:120
#define AARR_FREE_IF_COPY(array, n)
Definition: arrayfuncs.c:47
char typalign
Definition: typcache.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i

◆ array_extract_slice()

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 
)
static

Definition at line 4807 of file arrayfuncs.c.

References ARR_DATA_PTR, ARR_NULLBITMAP, array_bitmap_copy(), array_copy(), array_seek(), ArrayGetOffset(), i, MAXDIM, mda_get_offset_values(), mda_get_prod(), mda_get_range(), and mda_next_tuple().

Referenced by array_get_slice().

4818 {
4819  char *destdataptr = ARR_DATA_PTR(newarray);
4820  bits8 *destnullsptr = ARR_NULLBITMAP(newarray);
4821  char *srcdataptr;
4822  int src_offset,
4823  dest_offset,
4824  prod[MAXDIM],
4825  span[MAXDIM],
4826  dist[MAXDIM],
4827  indx[MAXDIM];
4828  int i,
4829  j,
4830  inc;
4831 
4832  src_offset = ArrayGetOffset(ndim, dim, lb, st);
4833  srcdataptr = array_seek(arraydataptr, 0, arraynullsptr, src_offset,
4834  typlen, typbyval, typalign);
4835  mda_get_prod(ndim, dim, prod);
4836  mda_get_range(ndim, span, st, endp);
4837  mda_get_offset_values(ndim, dist, prod, span);
4838  for (i = 0; i < ndim; i++)
4839  indx[i] = 0;
4840  dest_offset = 0;
4841  j = ndim - 1;
4842  do
4843  {
4844  if (dist[j])
4845  {
4846  /* skip unwanted elements */
4847  srcdataptr = array_seek(srcdataptr, src_offset, arraynullsptr,
4848  dist[j],
4849  typlen, typbyval, typalign);
4850  src_offset += dist[j];
4851  }
4852  inc = array_copy(destdataptr, 1,
4853  srcdataptr, src_offset, arraynullsptr,
4854  typlen, typbyval, typalign);
4855  if (destnullsptr)
4856  array_bitmap_copy(destnullsptr, dest_offset,
4857  arraynullsptr, src_offset,
4858  1);
4859  destdataptr += inc;
4860  srcdataptr += inc;
4861  src_offset++;
4862  dest_offset++;
4863  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4864 }
#define MAXDIM
Definition: c.h:467
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
void mda_get_prod(int n, const int *range, int *prod)
Definition: arrayutils.c:134
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4676
static int array_copy(char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4646
#define ARR_DATA_PTR(a)
Definition: array.h:307
void mda_get_offset_values(int n, int *dist, const int *prod, const int *span)
Definition: arrayutils.c:150
uint8 bits8
Definition: c.h:303
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:120
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4576
int mda_next_tuple(int n, int *curr, const int *span)
Definition: arrayutils.c:175
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:285

◆ array_fill()

Datum array_fill ( PG_FUNCTION_ARGS  )

Definition at line 5717 of file arrayfuncs.c.

References array_fill_internal(), elog, ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), OidIsValid, PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_ARRAYTYPE_P, and value.

5718 {
5719  ArrayType *dims;
5720  ArrayType *result;
5721  Oid elmtype;
5722  Datum value;
5723  bool isnull;
5724 
5725  if (PG_ARGISNULL(1))
5726  ereport(ERROR,
5727  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5728  errmsg("dimension array or low bound array cannot be null")));
5729 
5730  dims = PG_GETARG_ARRAYTYPE_P(1);
5731 
5732  if (!PG_ARGISNULL(0))
5733  {
5734  value = PG_GETARG_DATUM(0);
5735  isnull = false;
5736  }
5737  else
5738  {
5739  value = 0;
5740  isnull = true;
5741  }
5742 
5743  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5744  if (!OidIsValid(elmtype))
5745  elog(ERROR, "could not determine data type of input");
5746 
5747  result = array_fill_internal(dims, NULL, value, isnull, elmtype, fcinfo);
5748  PG_RETURN_ARRAYTYPE_P(result);
5749 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5769
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1904
static struct @121 value
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219

◆ array_fill_internal()

static ArrayType * array_fill_internal ( ArrayType dims,
ArrayType lbs,
Datum  value,
bool  isnull,
Oid  elmtype,
FunctionCallInfo  fcinfo 
)
static

Definition at line 5769 of file arrayfuncs.c.

References AllocSizeIsValid, ARR_DATA_PTR, ARR_DIMS, ARR_NDIM, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_contains_nulls(), ArrayCastAndSet(), ArrayGetNItems(), Assert, att_addlength_datum, att_align_nominal, construct_empty_array(), create_array_envelope(), ArrayMetaState::element_type, ereport, errcode(), errdetail(), errmsg(), ERROR, FunctionCallInfoData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, get_typlenbyvalalign(), i, InvalidOid, MaxAllocSize, MAXDIM, MemoryContextAlloc(), ArrayIteratorData::nitems, PG_DETOAST_DATUM, PointerGetDatum, ArrayMetaState::typalign, ArrayMetaState::typbyval, and ArrayMetaState::typlen.

Referenced by array_fill(), and array_fill_with_lower_bounds().

5772 {
5773  ArrayType *result;
5774  int *dimv;
5775  int *lbsv;
5776  int ndims;
5777  int nitems;
5778  int deflbs[MAXDIM];
5779  int16 elmlen;
5780  bool elmbyval;
5781  char elmalign;
5782  ArrayMetaState *my_extra;
5783 
5784  /*
5785  * Params checks
5786  */
5787  if (ARR_NDIM(dims) > 1)
5788  ereport(ERROR,
5789  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5790  errmsg("wrong number of array subscripts"),
5791  errdetail("Dimension array must be one dimensional.")));
5792 
5793  if (array_contains_nulls(dims))
5794  ereport(ERROR,
5795  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5796  errmsg("dimension values cannot be null")));
5797 
5798  dimv = (int *) ARR_DATA_PTR(dims);
5799  ndims = (ARR_NDIM(dims) > 0) ? ARR_DIMS(dims)[0] : 0;
5800 
5801  if (ndims < 0) /* we do allow zero-dimension arrays */
5802  ereport(ERROR,
5803  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5804  errmsg("invalid number of dimensions: %d", ndims)));
5805  if (ndims > MAXDIM)
5806  ereport(ERROR,
5807  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5808  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5809  ndims, MAXDIM)));
5810 
5811  if (lbs != NULL)
5812  {
5813  if (ARR_NDIM(lbs) > 1)
5814  ereport(ERROR,
5815  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5816  errmsg("wrong number of array subscripts"),
5817  errdetail("Dimension array must be one dimensional.")));
5818 
5819  if (array_contains_nulls(lbs))
5820  ereport(ERROR,
5821  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5822  errmsg("dimension values cannot be null")));
5823 
5824  if (ndims != ((ARR_NDIM(lbs) > 0) ? ARR_DIMS(lbs)[0] : 0))
5825  ereport(ERROR,
5826  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5827  errmsg("wrong number of array subscripts"),
5828  errdetail("Low bound array has different size than dimensions array.")));
5829 
5830  lbsv = (int *) ARR_DATA_PTR(lbs);
5831  }
5832  else
5833  {
5834  int i;
5835 
5836  for (i = 0; i < MAXDIM; i++)
5837  deflbs[i] = 1;
5838 
5839  lbsv = deflbs;
5840  }
5841 
5842  nitems = ArrayGetNItems(ndims, dimv);
5843 
5844  /* fast track for empty array */
5845  if (nitems <= 0)
5846  return construct_empty_array(elmtype);
5847 
5848  /*
5849  * We arrange to look up info about element type only once per series of
5850  * calls, assuming the element type doesn't change underneath us.
5851  */
5852  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
5853  if (my_extra == NULL)
5854  {
5855  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
5856  sizeof(ArrayMetaState));
5857  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
5858  my_extra->element_type = InvalidOid;
5859  }
5860 
5861  if (my_extra->element_type != elmtype)
5862  {
5863  /* Get info about element type */
5864  get_typlenbyvalalign(elmtype,
5865  &my_extra->typlen,
5866  &my_extra->typbyval,
5867  &my_extra->typalign);
5868  my_extra->element_type = elmtype;
5869  }
5870 
5871  elmlen = my_extra->typlen;
5872  elmbyval = my_extra->typbyval;
5873  elmalign = my_extra->typalign;
5874 
5875  /* compute required space */
5876  if (!isnull)
5877  {
5878  int i;
5879  char *p;
5880  int nbytes;
5881  int totbytes;
5882 
5883  /* make sure data is not toasted */
5884  if (elmlen == -1)
5886 
5887  nbytes = att_addlength_datum(0, elmlen, value);
5888  nbytes = att_align_nominal(nbytes, elmalign);
5889  Assert(nbytes > 0);
5890 
5891  totbytes = nbytes * nitems;
5892 
5893  /* check for overflow of multiplication or total request */
5894  if (totbytes / nbytes != nitems ||
5895  !AllocSizeIsValid(totbytes))
5896  ereport(ERROR,
5897  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5898  errmsg("array size exceeds the maximum allowed (%d)",
5899  (int) MaxAllocSize)));
5900 
5901  /*
5902  * This addition can't overflow, but it might cause us to go past
5903  * MaxAllocSize. We leave it to palloc to complain in that case.
5904  */
5905  totbytes += ARR_OVERHEAD_NONULLS(ndims);
5906 
5907  result = create_array_envelope(ndims, dimv, lbsv, totbytes,
5908  elmtype, 0);
5909 
5910  p = ARR_DATA_PTR(result);
5911  for (i = 0; i < nitems; i++)
5912  p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, p);
5913  }
5914  else
5915  {
5916  int nbytes;
5917  int dataoffset;
5918 
5919  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
5920  nbytes = dataoffset;
5921 
5922  result = create_array_envelope(ndims, dimv, lbsv, nbytes,
5923  elmtype, dataoffset);
5924 
5925  /* create_array_envelope already zeroed the bitmap, so we're done */
5926  }
5927 
5928  return result;
5929 }
signed short int16
Definition: c.h:283
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define MAXDIM
Definition: c.h:467
static ArrayType * create_array_envelope(int ndims, int *dimv, int *lbv, int nbytes, Oid elmtype, int dataoffset)
Definition: arrayfuncs.c:5752
static int ArrayCastAndSet(Datum src, int typlen, bool typbyval, char typalign, char *dest)
Definition: arrayfuncs.c:4537
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2040
#define PointerGetDatum(X)
Definition: postgres.h:562
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3398
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:297
bool typbyval
Definition: array.h:225
FmgrInfo * flinfo
Definition: fmgr.h:79
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:279
static struct @121 value
#define ARR_DATA_PTR(a)
Definition: array.h:307
int16 typlen
Definition: array.h:224
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:670
void * fn_extra
Definition: fmgr.h:64
#define ARR_NDIM(a)
Definition: array.h:275
char typalign
Definition: array.h:226
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
int i
Oid element_type
Definition: array.h:223
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:205
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3516

◆ array_fill_with_lower_bounds()

Datum array_fill_with_lower_bounds ( PG_FUNCTION_ARGS  )

Definition at line 5676 of file arrayfuncs.c.

References array_fill_internal(), elog, ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), OidIsValid, PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_ARRAYTYPE_P, and value.

5677 {
5678  ArrayType *dims;
5679  ArrayType *lbs;
5680  ArrayType *result;
5681  Oid elmtype;
5682  Datum value;
5683  bool isnull;
5684 
5685  if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
5686  ereport(ERROR,
5687  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5688  errmsg("dimension array or low bound array cannot be null")));
5689 
5690  dims = PG_GETARG_ARRAYTYPE_P(1);
5691  lbs = PG_GETARG_ARRAYTYPE_P(2);
5692 
5693  if (!PG_ARGISNULL(0))
5694  {
5695  value = PG_GETARG_DATUM(0);
5696  isnull = false;
5697  }
5698  else
5699  {
5700  value = 0;
5701  isnull = true;
5702  }
5703 
5704  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5705  if (!OidIsValid(elmtype))
5706  elog(ERROR, "could not determine data type of input");
5707 
5708  result = array_fill_internal(dims, lbs, value, isnull, elmtype, fcinfo);
5709  PG_RETURN_ARRAYTYPE_P(result);
5710 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5769
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1904
static struct @121 value
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219

◆ array_free_iterator()

void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4469 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4470 {
4471  if (iterator->slice_ndim > 0)
4472  {
4473  pfree(iterator->slice_values);
4474  pfree(iterator->slice_nulls);
4475  }
4476  pfree(iterator);
4477 }
bool * slice_nulls
Definition: arrayfuncs.c:83
void pfree(void *pointer)
Definition: mcxt.c:949
Datum * slice_values
Definition: arrayfuncs.c:82

◆ array_ge()

Datum array_ge ( PG_FUNCTION_ARGS  )

Definition at line 3716 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3717 {
3718  PG_RETURN_BOOL(array_cmp(fcinfo) >= 0);
3719 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3734
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319

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

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

1815 {
1816  int i,
1817  ndim,
1818  *dim,
1819  *lb,
1820  offset,
1821  fixedDim[1],
1822  fixedLb[1];
1823  char *arraydataptr,
1824  *retptr;
1825  bits8 *arraynullsptr;
1826 
1827  if (arraytyplen > 0)
1828  {
1829  /*
1830  * fixed-length arrays -- these are assumed to be 1-d, 0-based
1831  */
1832  ndim = 1;
1833  fixedDim[0] = arraytyplen / elmlen;
1834  fixedLb[0] = 0;
1835  dim = fixedDim;
1836  lb = fixedLb;
1837  arraydataptr = (char *) DatumGetPointer(arraydatum);
1838  arraynullsptr = NULL;
1839  }
1840  else if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(arraydatum)))
1841  {
1842  /* expanded array: let's do this in a separate function */
1843  return array_get_element_expanded(arraydatum,
1844  nSubscripts,
1845  indx,
1846  arraytyplen,
1847  elmlen,
1848  elmbyval,
1849  elmalign,
1850  isNull);
1851  }
1852  else
1853  {
1854  /* detoast array if necessary, producing normal varlena input */
1855  ArrayType *array = DatumGetArrayTypeP(arraydatum);
1856 
1857  ndim = ARR_NDIM(array);
1858  dim = ARR_DIMS(array);
1859  lb = ARR_LBOUND(array);
1860  arraydataptr = ARR_DATA_PTR(array);
1861  arraynullsptr = ARR_NULLBITMAP(array);
1862  }
1863 
1864  /*
1865  * Return NULL for invalid subscript
1866  */
1867  if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
1868  {
1869  *isNull = true;
1870  return (Datum) 0;
1871  }
1872  for (i = 0; i < ndim; i++)
1873  {
1874  if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
1875  {
1876  *isNull = true;
1877  return (Datum) 0;
1878  }
1879  }
1880 
1881  /*
1882  * Calculate the element number
1883  */
1884  offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
1885 
1886  /*
1887  * Check for NULL array element
1888  */
1889  if (array_get_isnull(arraynullsptr, offset))
1890  {
1891  *isNull = true;
1892  return (Datum) 0;
1893  }
1894 
1895  /*
1896  * OK, get the element
1897  */
1898  *isNull = false;
1899  retptr = array_seek(arraydataptr, 0, arraynullsptr, offset,
1900  elmlen, elmbyval, elmalign);
1901  return ArrayCast(retptr, elmbyval, elmlen);
1902 }
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:323
#define MAXDIM
Definition: c.h:467
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
#define ARR_LBOUND(a)
Definition: array.h:281
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
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:1908
uint8 bits8
Definition: c.h:303
uintptr_t Datum
Definition: postgres.h:372
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4576
static Datum ArrayCast(char *value, bool byval, int len)
Definition: arrayfuncs.c:4526
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4491
#define ARR_NDIM(a)
Definition: array.h:275
#define DatumGetPointer(X)
Definition: postgres.h:555
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:285
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ array_get_element_expanded()

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

Definition at line 1908 of file arrayfuncs.c.

References ArrayGetOffset(), Assert, DatumGetEOHP(), deconstruct_expanded_array(), ExpandedArrayHeader::dims, ExpandedArrayHeader::dnulls, ExpandedArrayHeader::dvalues, EA_MAGIC, ExpandedArrayHeader::ea_magic, i, ExpandedArrayHeader::lbound, MAXDIM, ExpandedArrayHeader::ndims, ExpandedArrayHeader::typalign, ExpandedArrayHeader::typbyval, and ExpandedArrayHeader::typlen.

Referenced by array_get_element().

1913 {
1914  ExpandedArrayHeader *eah;
1915  int i,
1916  ndim,
1917  *dim,
1918  *lb,
1919  offset;
1920  Datum *dvalues;
1921  bool *dnulls;
1922 
1923  eah = (ExpandedArrayHeader *) DatumGetEOHP(arraydatum);
1924  Assert(eah->ea_magic == EA_MAGIC);
1925 
1926  /* sanity-check caller's info against object */
1927  Assert(arraytyplen == -1);
1928  Assert(elmlen == eah->typlen);
1929  Assert(elmbyval == eah->typbyval);
1930  Assert(elmalign == eah->typalign);
1931 
1932  ndim = eah->ndims;
1933  dim = eah->dims;
1934  lb = eah->lbound;
1935 
1936  /*
1937  * Return NULL for invalid subscript
1938  */
1939  if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
1940  {
1941  *isNull = true;
1942  return (Datum) 0;
1943  }
1944  for (i = 0; i < ndim; i++)
1945  {
1946  if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
1947  {
1948  *isNull = true;
1949  return (Datum) 0;
1950  }
1951  }
1952 
1953  /*
1954  * Calculate the element number
1955  */
1956  offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
1957 
1958  /*
1959  * Deconstruct array if we didn't already. Note that we apply this even
1960  * if the input is nominally read-only: it should be safe enough.
1961  */
1963 
1964  dvalues = eah->dvalues;
1965  dnulls = eah->dnulls;
1966 
1967  /*
1968  * Check for NULL array element
1969  */
1970  if (dnulls && dnulls[offset])
1971  {
1972  *isNull = true;
1973  return (Datum) 0;
1974  }
1975 
1976  /*
1977  * OK, get the element. It's OK to return a pass-by-ref value as a
1978  * pointer into the expanded array, for the same reason that regular
1979  * array_get_element can return a pointer into flat arrays: the value is
1980  * assumed not to change for as long as the Datum reference can exist.
1981  */
1982  *isNull = false;
1983  return dvalues[offset];
1984 }
void deconstruct_expanded_array(ExpandedArrayHeader *eah)
#define MAXDIM
Definition: c.h:467
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
Datum * dvalues
Definition: array.h:134
#define EA_MAGIC
Definition: array.h:101
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:670
int i

◆ array_get_isnull()

static bool array_get_isnull ( const bits8 nullbitmap,
int  offset 
)
static

Definition at line 4491 of file arrayfuncs.c.

Referenced by array_get_element(), array_iterate(), array_set_element(), and array_slice_size().

4492 {
4493  if (nullbitmap == NULL)
4494  return false; /* assume not null */
4495  if (nullbitmap[offset / 8] & (1 << (offset % 8)))
4496  return false; /* not null */
4497  return true;
4498 }

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

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

2026 {
2027  ArrayType *array;
2028  ArrayType *newarray;
2029  int i,
2030  ndim,
2031  *dim,
2032  *lb,
2033  *newlb;
2034  int fixedDim[1],
2035  fixedLb[1];
2036  Oid elemtype;
2037  char *arraydataptr;
2038  bits8 *arraynullsptr;
2039  int32 dataoffset;
2040  int bytes,
2041  span[MAXDIM];
2042 
2043  if (arraytyplen > 0)
2044  {
2045  /*
2046  * fixed-length arrays -- currently, cannot slice these because parser
2047  * labels output as being of the fixed-length array type! Code below
2048  * shows how we could support it if the parser were changed to label
2049  * output as a suitable varlena array type.
2050  */
2051  ereport(ERROR,
2052  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2053  errmsg("slices of fixed-length arrays not implemented")));
2054 
2055  /*
2056  * fixed-length arrays -- these are assumed to be 1-d, 0-based
2057  *
2058  * XXX where would we get the correct ELEMTYPE from?
2059  */
2060  ndim = 1;
2061  fixedDim[0] = arraytyplen / elmlen;
2062  fixedLb[0] = 0;
2063  dim = fixedDim;
2064  lb = fixedLb;
2065  elemtype = InvalidOid; /* XXX */
2066  arraydataptr = (char *) DatumGetPointer(arraydatum);
2067  arraynullsptr = NULL;
2068  }
2069  else
2070  {
2071  /* detoast input array if necessary */
2072  array = DatumGetArrayTypeP(arraydatum);
2073 
2074  ndim = ARR_NDIM(array);
2075  dim = ARR_DIMS(array);
2076  lb = ARR_LBOUND(array);
2077  elemtype = ARR_ELEMTYPE(array);
2078  arraydataptr = ARR_DATA_PTR(array);
2079  arraynullsptr = ARR_NULLBITMAP(array);
2080  }
2081 
2082  /*
2083  * Check provided subscripts. A slice exceeding the current array limits
2084  * is silently truncated to the array limits. If we end up with an empty
2085  * slice, return an empty array.
2086  */
2087  if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
2088  return PointerGetDatum(construct_empty_array(elemtype));
2089 
2090  for (i = 0; i < nSubscripts; i++)
2091  {
2092  if (!lowerProvided[i] || lowerIndx[i] < lb[i])
2093  lowerIndx[i] = lb[i];
2094  if (!upperProvided[i] || upperIndx[i] >= (dim[i] + lb[i]))
2095  upperIndx[i] = dim[i] + lb[i] - 1;
2096  if (lowerIndx[i] > upperIndx[i])
2097  return PointerGetDatum(construct_empty_array(elemtype));
2098  }
2099  /* fill any missing subscript positions with full array range */
2100  for (; i < ndim; i++)
2101  {
2102  lowerIndx[i] = lb[i];
2103  upperIndx[i] = dim[i] + lb[i] - 1;
2104  if (lowerIndx[i] > upperIndx[i])
2105  return PointerGetDatum(construct_empty_array(elemtype));
2106  }
2107 
2108  mda_get_range(ndim, span, lowerIndx, upperIndx);
2109 
2110  bytes = array_slice_size(arraydataptr, arraynullsptr,
2111  ndim, dim, lb,
2112  lowerIndx, upperIndx,
2113  elmlen, elmbyval, elmalign);
2114 
2115  /*
2116  * Currently, we put a null bitmap in the result if the source has one;
2117  * could be smarter ...
2118  */
2119  if (arraynullsptr)
2120  {
2121  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, ArrayGetNItems(ndim, span));
2122  bytes += dataoffset;
2123  }
2124  else
2125  {
2126  dataoffset = 0; /* marker for no null bitmap */
2127  bytes += ARR_OVERHEAD_NONULLS(ndim);
2128  }
2129 
2130  newarray = (ArrayType *) palloc0(bytes);
2131  SET_VARSIZE(newarray, bytes);
2132  newarray->ndim = ndim;
2133  newarray->dataoffset = dataoffset;
2134  newarray->elemtype = elemtype;
2135  memcpy(ARR_DIMS(newarray), span, ndim * sizeof(int));
2136 
2137  /*
2138  * Lower bounds of the new array are set to 1. Formerly (before 7.3) we
2139  * copied the given lowerIndx values ... but that seems confusing.
2140  */
2141  newlb = ARR_LBOUND(newarray);
2142  for (i = 0; i < ndim; i++)
2143  newlb[i] = 1;
2144 
2145  array_extract_slice(newarray,
2146  ndim, dim, lb,
2147  arraydataptr, arraynullsptr,
2148  lowerIndx, upperIndx,
2149  elmlen, elmbyval, elmalign);
2150 
2151  return PointerGetDatum(newarray);
2152 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define MAXDIM
Definition: c.h:467
#define PointerGetDatum(X)
Definition: postgres.h:562
int32 dataoffset
Definition: array.h:84
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:4747
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
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:4807
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3398
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:297
signed int int32
Definition: c.h:284
#define ARR_LBOUND(a)
Definition: array.h:281
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ereport(elevel, rest)
Definition: elog.h:122
uint8 bits8
Definition: c.h:303
void * palloc0(Size size)
Definition: mcxt.c:877
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:120
#define InvalidOid
Definition: postgres_ext.h:36
#define ARR_NDIM(a)
Definition: array.h:275
#define DatumGetPointer(X)
Definition: postgres.h:555
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
#define ARR_ELEMTYPE(a)
Definition: array.h:277
#define ARR_NULLBITMAP(a)
Definition: array.h:285
int ndim
Definition: array.h:83
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ array_gt()

Datum array_gt ( PG_FUNCTION_ARGS  )

Definition at line 3704 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3705 {
3706  PG_RETURN_BOOL(array_cmp(fcinfo) > 0);
3707 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3734
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319

◆ array_in()

Datum array_in ( PG_FUNCTION_ARGS  )

Definition at line 172 of file arrayfuncs.c.

References ARR_DIMS, ARR_LBOUND, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_isspace(), ArrayCount(), ArrayGetNItems(), ASSGN, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, ArrayMetaState::element_type, ArrayType::elemtype, ereport, errcode(), errdetail(), errmsg(), ERROR, fmgr_info_cxt(), FmgrInfo::fn_mcxt, get_type_io_data(), i, IOFunc_input, MAXDIM, MemoryContextAlloc(), ArrayType::ndim, ArrayIteratorData::nitems, palloc(), palloc0(), pfree(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_ARRAYTYPE_P, ArrayMetaState::proc, pstrdup(), ReadArrayStr(), SET_VARSIZE, ArrayIteratorData::typalign, ArrayMetaState::typalign, ArrayIteratorData::typbyval, ArrayMetaState::typbyval, ArrayMetaState::typdelim, ArrayMetaState::typiofunc, ArrayMetaState::typioparam, ArrayIteratorData::typlen, and ArrayMetaState::typlen.

Referenced by extract_variadic_args().

173 {
174  char *string = PG_GETARG_CSTRING(0); /* external form */
175  Oid element_type = PG_GETARG_OID(1); /* type of an array
176  * element */
177  int32 typmod = PG_GETARG_INT32(2); /* typmod for array elements */
178  int typlen;
179  bool typbyval;
180  char typalign;
181  char typdelim;
182  Oid typioparam;
183  char *string_save,
184  *p;
185  int i,
186  nitems;
187  Datum *dataPtr;
188  bool *nullsPtr;
189  bool hasnulls;
190  int32 nbytes;
191  int32 dataoffset;
192  ArrayType *retval;
193  int ndim,
194  dim[MAXDIM],
195  lBound[MAXDIM];
196  ArrayMetaState *my_extra;
197 
198  /*
199  * We arrange to look up info about element type, including its input
200  * conversion proc, only once per series of calls, assuming the element
201  * type doesn't change underneath us.
202  */
203  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
204  if (my_extra == NULL)
205  {
206  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
207  sizeof(ArrayMetaState));
208  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
209  my_extra->element_type = ~element_type;
210  }
211 
212  if (my_extra->element_type != element_type)
213  {
214  /*
215  * Get info about element type, including its input conversion proc
216  */
217  get_type_io_data(element_type, IOFunc_input,
218  &my_extra->typlen, &my_extra->typbyval,
219  &my_extra->typalign, &my_extra->typdelim,
220  &my_extra->typioparam, &my_extra->typiofunc);
221  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
222  fcinfo->flinfo->fn_mcxt);
223  my_extra->element_type = element_type;
224  }
225  typlen = my_extra->typlen;
226  typbyval = my_extra->typbyval;
227  typalign = my_extra->typalign;
228  typdelim = my_extra->typdelim;
229  typioparam = my_extra->typioparam;
230 
231  /* Make a modifiable copy of the input */
232  string_save = pstrdup(string);
233 
234  /*
235  * If the input string starts with dimension info, read and use that.
236  * Otherwise, we require the input to be in curly-brace style, and we
237  * prescan the input to determine dimensions.
238  *
239  * Dimension info takes the form of one or more [n] or [m:n] items. The
240  * outer loop iterates once per dimension item.
241  */
242  p = string_save;
243  ndim = 0;
244  for (;;)
245  {
246  char *q;
247  int ub;
248 
249  /*
250  * Note: we currently allow whitespace between, but not within,
251  * dimension items.
252  */
253  while (array_isspace(*p))
254  p++;
255  if (*p != '[')
256  break; /* no more dimension items */
257  p++;
258  if (ndim >= MAXDIM)
259  ereport(ERROR,
260  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
261  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
262  ndim + 1, MAXDIM)));
263 
264  for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++)
265  /* skip */ ;
266  if (q == p) /* no digits? */
267  ereport(ERROR,
268  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
269  errmsg("malformed array literal: \"%s\"", string),
270  errdetail("\"[\" must introduce explicitly-specified array dimensions.")));
271 
272  if (*q == ':')
273  {
274  /* [m:n] format */
275  *q = '\0';
276  lBound[ndim] = atoi(p);
277  p = q + 1;
278  for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++)
279  /* skip */ ;
280  if (q == p) /* no digits? */
281  ereport(ERROR,
282  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
283  errmsg("malformed array literal: \"%s\"", string),
284  errdetail("Missing array dimension value.")));
285  }
286  else
287  {
288  /* [n] format */
289  lBound[ndim] = 1;
290  }
291  if (*q != ']')
292  ereport(ERROR,
293  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
294  errmsg("malformed array literal: \"%s\"", string),
295  errdetail("Missing \"%s\" after array dimensions.",
296  "]")));
297 
298  *q = '\0';
299  ub = atoi(p);
300  p = q + 1;
301  if (ub < lBound[ndim])
302  ereport(ERROR,
303  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
304  errmsg("upper bound cannot be less than lower bound")));
305 
306  dim[ndim] = ub - lBound[ndim] + 1;
307  ndim++;
308  }
309 
310  if (ndim == 0)
311  {
312  /* No array dimensions, so intuit dimensions from brace structure */
313  if (*p != '{')
314  ereport(ERROR,
315  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
316  errmsg("malformed array literal: \"%s\"", string),
317  errdetail("Array value must start with \"{\" or dimension information.")));
318  ndim = ArrayCount(p, dim, typdelim);
319  for (i = 0; i < ndim; i++)
320  lBound[i] = 1;
321  }
322  else
323  {
324  int ndim_braces,
325  dim_braces[MAXDIM];
326 
327  /* If array dimensions are given, expect '=' operator */
328  if (strncmp(p, ASSGN, strlen(ASSGN)) != 0)
329  ereport(ERROR,
330  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
331  errmsg("malformed array literal: \"%s\"", string),
332  errdetail("Missing \"%s\" after array dimensions.",
333  ASSGN)));
334  p += strlen(ASSGN);
335  while (array_isspace(*p))
336  p++;
337 
338  /*
339  * intuit dimensions from brace structure -- it better match what we
340  * were given
341  */
342  if (*p != '{')
343  ereport(ERROR,
344  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
345  errmsg("malformed array literal: \"%s\"", string),
346  errdetail("Array contents must start with \"{\".")));
347  ndim_braces = ArrayCount(p, dim_braces, typdelim);
348  if (ndim_braces != ndim)
349  ereport(ERROR,
350  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
351  errmsg("malformed array literal: \"%s\"", string),
352  errdetail("Specified array dimensions do not match array contents.")));
353  for (i = 0; i < ndim; ++i)
354  {
355  if (dim[i] != dim_braces[i])
356  ereport(ERROR,
357  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
358  errmsg("malformed array literal: \"%s\"", string),
359  errdetail("Specified array dimensions do not match array contents.")));
360  }
361  }
362 
363 #ifdef ARRAYDEBUG
364  printf("array_in- ndim %d (", ndim);
365  for (i = 0; i < ndim; i++)
366  {
367  printf(" %d", dim[i]);
368  };
369  printf(") for %s\n", string);
370 #endif
371 
372  /* This checks for overflow of the array dimensions */
373  nitems = ArrayGetNItems(ndim, dim);
374  /* Empty array? */
375  if (nitems == 0)
377 
378  dataPtr = (Datum *) palloc(nitems * sizeof(Datum));
379  nullsPtr = (bool *) palloc(nitems * sizeof(bool));
380  ReadArrayStr(p, string,
381  nitems, ndim, dim,
382  &my_extra->proc, typioparam, typmod,
383  typdelim,
384  typlen, typbyval, typalign,
385  dataPtr, nullsPtr,
386  &hasnulls, &nbytes);
387  if (hasnulls)
388  {
389  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
390  nbytes += dataoffset;
391  }
392  else
393  {
394  dataoffset = 0; /* marker for no null bitmap */
395  nbytes += ARR_OVERHEAD_NONULLS(ndim);
396  }
397  retval = (ArrayType *) palloc0(nbytes);
398  SET_VARSIZE(retval, nbytes);
399  retval->ndim = ndim;
400  retval->dataoffset = dataoffset;
401 
402  /*
403  * This comes from the array's pg_type.typelem (which points to the base
404  * data type's pg_type.oid) and stores system oids in user tables. This
405  * oid must be preserved by binary upgrades.
406  */
407  retval->elemtype = element_type;
408  memcpy(ARR_DIMS(retval), dim, ndim * sizeof(int));
409  memcpy(ARR_LBOUND(retval), lBound, ndim * sizeof(int));
410 
411  CopyArrayEls(retval,
412  dataPtr, nullsPtr, nitems,
413  typlen, typbyval, typalign,
414  true);
415 
416  pfree(dataPtr);
417  pfree(nullsPtr);
418  pfree(string_save);
419 
420  PG_RETURN_ARRAYTYPE_P(retval);
421 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
static bool array_isspace(char ch)
Definition: arrayfuncs.c:432
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define MAXDIM
Definition: c.h:467
char * pstrdup(const char *in)
Definition: mcxt.c:1076
int32 dataoffset
Definition: array.h:84
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3398
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:297
signed int int32
Definition: c.h:284
static void ReadArrayStr(char *arrayStr, const char *origStr, int nitems, int ndim, int *dim, FmgrInfo *inputproc, Oid typioparam, int32 typmod, char typdelim, int typlen, bool typbyval, char typalign, Datum *values, bool *nulls, bool *hasnulls, int32 *nbytes)
Definition: arrayfuncs.c:717
#define ARR_LBOUND(a)
Definition: array.h:281
bool typbyval
Definition: array.h:225
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:279
int16 typlen
Definition: array.h:224
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
char typdelim
Definition: array.h:227
int errdetail(const char *fmt,...)
Definition: elog.c:873
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define ereport(elevel, rest)
Definition: elog.h:122
#define ASSGN
Definition: arrayfuncs.c:45
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
Oid typioparam
Definition: array.h:228
static int ArrayCount(const char *str, int *dim, char typdelim)
Definition: arrayfuncs.c:452
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:957
Oid typiofunc
Definition: array.h:229
char typalign
Definition: array.h:226
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
FmgrInfo proc
Definition: array.h:230
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
int i
Oid element_type
Definition: array.h:223
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:242
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
int ndim
Definition: array.h:83
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition: lsyscache.c:2094

◆ array_insert_slice()

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 
)
static

Definition at line 4880 of file arrayfuncs.c.

References ARR_DATA_PTR, ARR_DIMS, ARR_NDIM, ARR_NULLBITMAP, array_bitmap_copy(), array_copy(), array_seek(), ArrayGetNItems(), ArrayGetOffset(), i, MAXDIM, mda_get_offset_values(), mda_get_prod(), mda_get_range(), and mda_next_tuple().

Referenced by array_set_slice().

4891 {
4892  char *destPtr = ARR_DATA_PTR(destArray);
4893  char *origPtr = ARR_DATA_PTR(origArray);
4894  char *srcPtr = ARR_DATA_PTR(srcArray);
4895  bits8 *destBitmap = ARR_NULLBITMAP(destArray);
4896  bits8 *origBitmap = ARR_NULLBITMAP(origArray);
4897  bits8 *srcBitmap = ARR_NULLBITMAP(srcArray);
4898  int orignitems = ArrayGetNItems(ARR_NDIM(origArray),
4899  ARR_DIMS(origArray));
4900  int dest_offset,
4901  orig_offset,
4902  src_offset,
4903  prod[MAXDIM],
4904  span[MAXDIM],
4905  dist[MAXDIM],
4906  indx[MAXDIM];
4907  int i,
4908  j,
4909  inc;
4910 
4911  dest_offset = ArrayGetOffset(ndim, dim, lb, st);
4912  /* copy items before the slice start */
4913  inc = array_copy(destPtr, dest_offset,
4914  origPtr, 0, origBitmap,
4915  typlen, typbyval, typalign);
4916  destPtr += inc;
4917  origPtr += inc;
4918  if (destBitmap)
4919  array_bitmap_copy(destBitmap, 0, origBitmap, 0, dest_offset);
4920  orig_offset = dest_offset;
4921  mda_get_prod(ndim, dim, prod);
4922  mda_get_range(ndim, span, st, endp);
4923  mda_get_offset_values(ndim, dist, prod, span);
4924  for (i = 0; i < ndim; i++)
4925  indx[i] = 0;
4926  src_offset = 0;
4927  j = ndim - 1;
4928  do
4929  {
4930  /* Copy/advance over elements between here and next part of slice */
4931  if (dist[j])
4932  {
4933  inc = array_copy(destPtr, dist[j],
4934  origPtr, orig_offset, origBitmap,
4935  typlen, typbyval, typalign);
4936  destPtr += inc;
4937  origPtr += inc;
4938  if (destBitmap)
4939  array_bitmap_copy(destBitmap, dest_offset,
4940  origBitmap, orig_offset,
4941  dist[j]);
4942  dest_offset += dist[j];
4943  orig_offset += dist[j];
4944  }
4945  /* Copy new element at this slice position */
4946  inc = array_copy(destPtr, 1,
4947  srcPtr, src_offset, srcBitmap,
4948  typlen, typbyval, typalign);
4949  if (destBitmap)
4950  array_bitmap_copy(destBitmap, dest_offset,
4951  srcBitmap, src_offset,
4952  1);
4953  destPtr += inc;
4954  srcPtr += inc;
4955  dest_offset++;
4956  src_offset++;
4957  /* Advance over old element at this slice position */
4958  origPtr = array_seek(origPtr, orig_offset, origBitmap, 1,
4959  typlen, typbyval, typalign);
4960  orig_offset++;
4961  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4962 
4963  /* don't miss any data at the end */
4964  array_copy(destPtr, orignitems - orig_offset,
4965  origPtr, orig_offset, origBitmap,
4966  typlen, typbyval, typalign);
4967  if (destBitmap)
4968  array_bitmap_copy(destBitmap, dest_offset,
4969  origBitmap, orig_offset,
4970  orignitems - orig_offset);
4971 }
#define MAXDIM
Definition: c.h:467
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
void mda_get_prod(int n, const int *range, int *prod)
Definition: arrayutils.c:134
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4676
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
static int array_copy(char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4646
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
void mda_get_offset_values(int n, int *dist, const int *prod, const int *span)
Definition: arrayutils.c:150
uint8 bits8
Definition: c.h:303
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:120
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4576
#define ARR_NDIM(a)
Definition: array.h:275
int mda_next_tuple(int n, int *curr, const int *span)
Definition: arrayutils.c:175
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:285

◆ array_isspace()

static bool array_isspace ( char  ch)
static

Definition at line 432 of file arrayfuncs.c.

Referenced by array_in(), array_out(), ArrayCount(), and ReadArrayStr().

433 {
434  if (ch == ' ' ||
435  ch == '\t' ||
436  ch == '\n' ||
437  ch == '\r' ||
438  ch == '\v' ||
439  ch == '\f')
440  return true;
441  return false;
442 }

◆ array_iterate()

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

Definition at line 4386 of file arrayfuncs.c.

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, and values.

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

4387 {
4388  /* Done if we have reached the end of the array */
4389  if (iterator->current_item >= iterator->nitems)
4390  return false;
4391 
4392  if (iterator->slice_ndim == 0)
4393  {
4394  /*
4395  * Scalar case: return one element.
4396  */
4397  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4398  {
4399  *isnull = true;
4400  *value = (Datum) 0;
4401  }
4402  else
4403  {
4404  /* non-NULL, so fetch the individual Datum to return */
4405  char *p = iterator->data_ptr;
4406 
4407  *isnull = false;
4408  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4409 
4410  /* Move our data pointer forward to the next element */
4411  p = att_addlength_pointer(p, iterator->typlen, p);
4412  p = (char *) att_align_nominal(p, iterator->typalign);
4413  iterator->data_ptr = p;
4414  }
4415  }
4416  else
4417  {
4418  /*
4419  * Slice case: build and return an array of the requested size.
4420  */
4421  ArrayType *result;
4422  Datum *values = iterator->slice_values;
4423  bool *nulls = iterator->slice_nulls;
4424  char *p = iterator->data_ptr;
4425  int i;
4426 
4427  for (i = 0; i < iterator->slice_len; i++)
4428  {
4429  if (array_get_isnull(iterator->nullbitmap,
4430  iterator->current_item++))
4431  {
4432  nulls[i] = true;
4433  values[i] = (Datum) 0;
4434  }
4435  else
4436  {
4437  nulls[i] = false;
4438  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4439 
4440  /* Move our data pointer forward to the next element */
4441  p = att_addlength_pointer(p, iterator->typlen, p);
4442  p = (char *) att_align_nominal(p, iterator->typalign);
4443  }
4444  }
4445 
4446  iterator->data_ptr = p;
4447 
4448  result = construct_md_array(values,
4449  nulls,
4450  iterator->slice_ndim,
4451  iterator->slice_dims,
4452  iterator->slice_lbound,
4453  ARR_ELEMTYPE(iterator->arr),
4454  iterator->typlen,
4455  iterator->typbyval,
4456  iterator->typalign);
4457 
4458  *isnull = false;
4459  *value = PointerGetDatum(result);
4460  }
4461 
4462  return true;
4463 }
bits8 * nullbitmap
Definition: arrayfuncs.c:71
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define PointerGetDatum(X)
Definition: postgres.h:562
bool * slice_nulls
Definition: arrayfuncs.c:83
Datum * slice_values
Definition: arrayfuncs.c:82
static struct @121 value
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
uintptr_t Datum
Definition: postgres.h:372
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4491
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
int i
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:3314
#define ARR_ELEMTYPE(a)
Definition: array.h:277
ArrayType * arr
Definition: arrayfuncs.c:70

◆ array_larger()

Datum array_larger ( PG_FUNCTION_ARGS  )

Definition at line 5571 of file arrayfuncs.c.

References array_cmp(), PG_GETARG_DATUM, and PG_RETURN_DATUM.

5572 {
5573  if (array_cmp(fcinfo) > 0)
5575  else
5577 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3734
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313

◆ array_le()

Datum array_le ( PG_FUNCTION_ARGS  )

Definition at line 3710 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3711 {
3712  PG_RETURN_BOOL(array_cmp(fcinfo) <= 0);
3713 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3734
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319

◆ array_length()

Datum array_length ( PG_FUNCTION_ARGS  )

Definition at line 1750 of file arrayfuncs.c.

References AARR_DIMS, AARR_NDIM, MAXDIM, PG_GETARG_ANY_ARRAY_P, PG_GETARG_INT32, PG_RETURN_INT32, and PG_RETURN_NULL.

1751 {
1753  int reqdim = PG_GETARG_INT32(1);
1754  int *dimv;
1755  int result;
1756 
1757  /* Sanity check: does it look like an array at all? */
1758  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1759  PG_RETURN_NULL();
1760 
1761  /* Sanity check: was the requested dim valid */
1762  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1763  PG_RETURN_NULL();
1764 
1765  dimv = AARR_DIMS(v);
1766 
1767  result = dimv[reqdim - 1];
1768 
1769  PG_RETURN_INT32(result);
1770 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:259
#define MAXDIM
Definition: c.h:467
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
#define AARR_DIMS(a)
Definition: array.h:321
#define AARR_NDIM(a)
Definition: array.h:313
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ array_lower()

Datum array_lower ( PG_FUNCTION_ARGS  )

Definition at line 1693 of file arrayfuncs.c.

References AARR_LBOUND, AARR_NDIM, MAXDIM, PG_GETARG_ANY_ARRAY_P, PG_GETARG_INT32, PG_RETURN_INT32, and PG_RETURN_NULL.

1694 {
1696  int reqdim = PG_GETARG_INT32(1);
1697  int *lb;
1698  int result;
1699 
1700  /* Sanity check: does it look like an array at all? */
1701  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1702  PG_RETURN_NULL();
1703 
1704  /* Sanity check: was the requested dim valid */
1705  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1706  PG_RETURN_NULL();
1707 
1708  lb = AARR_LBOUND(v);
1709  result = lb[reqdim - 1];
1710 
1711  PG_RETURN_INT32(result);
1712 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:259
#define MAXDIM
Definition: c.h:467
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
#define AARR_LBOUND(a)
Definition: array.h:323
#define AARR_NDIM(a)
Definition: array.h:313
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ array_lt()

Datum array_lt ( PG_FUNCTION_ARGS  )

Definition at line 3698 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3699 {
3700  PG_RETURN_BOOL(array_cmp(fcinfo) < 0);
3701 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3734
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319

◆ array_map()

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

Definition at line 3119 of file arrayfuncs.c.

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, ArrayIteratorData::nitems, palloc(), palloc0(), pfree(), PG_DETOAST_DATUM, PointerGetDatum, ArrayMapState::ret_extra, SET_VARSIZE, ArrayIteratorData::typalign, ArrayMetaState::typalign, ArrayIteratorData::typbyval, ArrayMetaState::typbyval, ArrayIteratorData::typlen, ArrayMetaState::typlen, and values.

Referenced by ExecEvalArrayCoerce().

3122 {
3123  AnyArrayType *v = DatumGetAnyArrayP(arrayd);
3124  ArrayType *result;
3125  Datum *values;
3126  bool *nulls;
3127  int *dim;
3128  int ndim;
3129  int nitems;
3130  int i;
3131  int32 nbytes = 0;
3132  int32 dataoffset;
3133  bool hasnulls;
3134  Oid inpType;
3135  int inp_typlen;
3136  bool inp_typbyval;
3137  char inp_typalign;
3138  int typlen;
3139  bool typbyval;
3140  char typalign;
3141  array_iter iter;
3142  ArrayMetaState *inp_extra;
3143  ArrayMetaState *ret_extra;
3144  Datum *transform_source = exprstate->innermost_caseval;
3145  bool *transform_source_isnull = exprstate->innermost_casenull;
3146 
3147  inpType = AARR_ELEMTYPE(v);
3148  ndim = AARR_NDIM(v);
3149  dim = AARR_DIMS(v);
3150  nitems = ArrayGetNItems(ndim, dim);
3151 
3152  /* Check for empty array */
3153  if (nitems <= 0)
3154  {
3155  /* Return empty array */
3156  return PointerGetDatum(construct_empty_array(retType));
3157  }
3158 
3159  /*
3160  * We arrange to look up info about input and return element types only
3161  * once per series of calls, assuming the element type doesn't change
3162  * underneath us.
3163  */
3164  inp_extra = &amstate->inp_extra;
3165  ret_extra = &amstate->ret_extra;
3166 
3167  if (inp_extra->element_type != inpType)
3168  {
3169  get_typlenbyvalalign(inpType,
3170  &inp_extra->typlen,
3171  &inp_extra->typbyval,
3172  &inp_extra->typalign);
3173  inp_extra->element_type = inpType;
3174  }
3175  inp_typlen = inp_extra->typlen;
3176  inp_typbyval = inp_extra->typbyval;
3177  inp_typalign = inp_extra->typalign;
3178 
3179  if (ret_extra->element_type != retType)
3180  {
3181  get_typlenbyvalalign(retType,
3182  &ret_extra->typlen,
3183  &ret_extra->typbyval,
3184  &ret_extra->typalign);
3185  ret_extra->element_type = retType;
3186  }
3187  typlen = ret_extra->typlen;
3188  typbyval = ret_extra->typbyval;
3189  typalign = ret_extra->typalign;
3190 
3191  /* Allocate temporary arrays for new values */
3192  values = (Datum *) palloc(nitems * sizeof(Datum));
3193  nulls = (bool *) palloc(nitems * sizeof(bool));
3194 
3195  /* Loop over source data */
3196  array_iter_setup(&iter, v);
3197  hasnulls = false;
3198 
3199  for (i = 0; i < nitems; i++)
3200  {
3201  /* Get source element, checking for NULL */
3202  *transform_source =
3203  array_iter_next(&iter, transform_source_isnull, i,
3204  inp_typlen, inp_typbyval, inp_typalign);
3205 
3206  /* Apply the given expression to source element */
3207  values[i] = ExecEvalExpr(exprstate, econtext, &nulls[i]);
3208 
3209  if (nulls[i])
3210  hasnulls = true;
3211  else
3212  {
3213  /* Ensure data is not toasted */
3214  if (typlen == -1)
3215  values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
3216  /* Update total result size */
3217  nbytes = att_addlength_datum(nbytes, typlen, values[i]);
3218  nbytes = att_align_nominal(nbytes, typalign);
3219  /* check for overflow of total request */
3220  if (!AllocSizeIsValid(nbytes))
3221  ereport(ERROR,
3222  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3223  errmsg("array size exceeds the maximum allowed (%d)",
3224  (int) MaxAllocSize)));
3225  }
3226  }
3227 
3228  /* Allocate and fill the result array */
3229  if (hasnulls)
3230  {
3231  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3232  nbytes += dataoffset;
3233  }
3234  else
3235  {
3236  dataoffset = 0; /* marker for no null bitmap */
3237  nbytes += ARR_OVERHEAD_NONULLS(ndim);
3238  }
3239  result = (ArrayType *) palloc0(nbytes);
3240  SET_VARSIZE(result, nbytes);
3241  result->ndim = ndim;
3242  result->dataoffset = dataoffset;
3243  result->elemtype = retType;
3244  memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
3245  memcpy(ARR_LBOUND(result), AARR_LBOUND(v), ndim * sizeof(int));
3246 
3247  CopyArrayEls(result,
3248  values, nulls, nitems,
3249  typlen, typbyval, typalign,
3250  false);
3251 
3252  /*
3253  * Note: do not risk trying to pfree the results of the called expression
3254  */
3255  pfree(values);
3256  pfree(nulls);
3257 
3258  return PointerGetDatum(result);
3259 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2040
#define PointerGetDatum(X)
Definition: postgres.h:562
bool * innermost_casenull
Definition: execnodes.h:94
int32 dataoffset
Definition: array.h:84
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3398
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:297
signed int int32
Definition: c.h:284
AnyArrayType * DatumGetAnyArrayP(Datum d)
#define ARR_LBOUND(a)
Definition: array.h:281
bool typbyval
Definition: array.h:225
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:279
ArrayMetaState inp_extra
Definition: array.h:238
int16 typlen
Definition: array.h:224
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:276
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
Datum * innermost_caseval
Definition: execnodes.h:93
#define ereport(elevel, rest)
Definition: elog.h:122
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
#define AARR_DIMS(a)
Definition: array.h:321
#define AARR_ELEMTYPE(a)
Definition: array.h:319
#define AARR_LBOUND(a)
Definition: array.h:323
#define AARR_NDIM(a)
Definition: array.h:313
ArrayMetaState ret_extra
Definition: array.h:239
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:957
char typalign
Definition: array.h:226
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
Oid element_type
Definition: array.h:223
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:205
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
int ndim
Definition: array.h:83

◆ array_ndims()

Datum array_ndims ( PG_FUNCTION_ARGS  )

Definition at line 1639 of file arrayfuncs.c.

References AARR_NDIM, MAXDIM, PG_GETARG_ANY_ARRAY_P, PG_RETURN_INT32, and PG_RETURN_NULL.

1640 {
1642 
1643  /* Sanity check: does it look like an array at all? */
1644  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1645  PG_RETURN_NULL();
1646 
1648 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:259
#define MAXDIM
Definition: c.h:467
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
#define AARR_NDIM(a)
Definition: array.h:313
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ array_ne()

Datum array_ne ( PG_FUNCTION_ARGS  )

Definition at line 3692 of file arrayfuncs.c.

References array_eq(), DatumGetBool, and PG_RETURN_BOOL.

3693 {
3695 }
#define DatumGetBool(X)
Definition: postgres.h:399
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
Datum array_eq(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:3563

◆ array_nelems_size()

static int array_nelems_size ( char *  ptr,
int  offset,
bits8 nullbitmap,
int  nitems,
int  typlen,
bool  typbyval,
char  typalign 
)
static

Definition at line 4624 of file arrayfuncs.c.

References array_seek().

Referenced by array_copy(), and array_set_slice().

4626 {
4627  return array_seek(ptr, offset, nullbitmap, nitems,
4628  typlen, typbyval, typalign) - ptr;
4629 }
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4576

◆ array_out()

Datum array_out ( PG_FUNCTION_ARGS  )

Definition at line 1012 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_LBOUND, AARR_NDIM, APPENDCHAR, APPENDSTR, array_isspace(), array_iter_next(), array_iter_setup(), ArrayGetNItems(), ASSGN, ArrayMetaState::element_type, fmgr_info_cxt(), FmgrInfo::fn_mcxt, get_type_io_data(), i, IOFunc_output, MAXDIM, MemoryContextAlloc(), ArrayIteratorData::nitems, OutputFunctionCall(), palloc(), pfree(), PG_GETARG_ANY_ARRAY_P, PG_RETURN_CSTRING, pg_strcasecmp(), ArrayMetaState::proc, pstrdup(), ArrayIteratorData::typalign, ArrayMetaState::typalign, ArrayIteratorData::typbyval, ArrayMetaState::typbyval, ArrayMetaState::typdelim, ArrayMetaState::typiofunc, ArrayMetaState::typioparam, ArrayIteratorData::typlen, ArrayMetaState::typlen, and values.

Referenced by anyarray_out().

1013 {
1015  Oid element_type = AARR_ELEMTYPE(v);
1016  int typlen;
1017  bool typbyval;
1018  char typalign;
1019  char typdelim;
1020  char *p,
1021  *tmp,
1022  *retval,
1023  **values,
1024  dims_str[(MAXDIM * 33) + 2];
1025 
1026  /*
1027  * 33 per dim since we assume 15 digits per number + ':' +'[]'
1028  *
1029  * +2 allows for assignment operator + trailing null
1030  */
1031  bool *needquotes,
1032  needdims = false;
1033  int nitems,
1034  overall_length,
1035  i,
1036  j,
1037  k,
1038  indx[MAXDIM];
1039  int ndim,
1040  *dims,
1041  *lb;
1042  array_iter iter;
1043  ArrayMetaState *my_extra;
1044 
1045  /*
1046  * We arrange to look up info about element type, including its output
1047  * conversion proc, only once per series of calls, assuming the element
1048  * type doesn't change underneath us.
1049  */
1050  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1051  if (my_extra == NULL)
1052  {
1053  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1054  sizeof(ArrayMetaState));
1055  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1056  my_extra->element_type = ~element_type;
1057  }
1058 
1059  if (my_extra->element_type != element_type)
1060  {
1061  /*
1062  * Get info about element type, including its output conversion proc
1063  */
1064  get_type_io_data(element_type, IOFunc_output,
1065  &my_extra->typlen, &my_extra->typbyval,
1066  &my_extra->typalign, &my_extra->typdelim,
1067  &my_extra->typioparam, &my_extra->typiofunc);
1068  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1069  fcinfo->flinfo->fn_mcxt);
1070  my_extra->element_type = element_type;
1071  }
1072  typlen = my_extra->typlen;
1073  typbyval = my_extra->typbyval;
1074  typalign = my_extra->typalign;
1075  typdelim = my_extra->typdelim;
1076 
1077  ndim = AARR_NDIM(v);
1078  dims = AARR_DIMS(v);
1079  lb = AARR_LBOUND(v);
1080  nitems = ArrayGetNItems(ndim, dims);
1081 
1082  if (nitems == 0)
1083  {
1084  retval = pstrdup("{}");
1085  PG_RETURN_CSTRING(retval);
1086  }
1087 
1088  /*
1089  * we will need to add explicit dimensions if any dimension has a lower
1090  * bound other than one
1091  */
1092  for (i = 0; i < ndim; i++)
1093  {
1094  if (lb[i] != 1)
1095  {
1096  needdims = true;
1097  break;
1098  }
1099  }
1100 
1101  /*
1102  * Convert all values to string form, count total space needed (including
1103  * any overhead such as escaping backslashes), and detect whether each
1104  * item needs double quotes.
1105  */
1106  values = (char **) palloc(nitems * sizeof(char *));
1107  needquotes = (bool *) palloc(nitems * sizeof(bool));
1108  overall_length = 1; /* don't forget to count \0 at end. */
1109 
1110  array_iter_setup(&iter, v);
1111 
1112  for (i = 0; i < nitems; i++)
1113  {
1114  Datum itemvalue;
1115  bool isnull;
1116  bool needquote;
1117 
1118  /* Get source element, checking for NULL */
1119  itemvalue = array_iter_next(&iter, &isnull, i,
1120  typlen, typbyval, typalign);
1121 
1122  if (isnull)
1123  {
1124  values[i] = pstrdup("NULL");
1125  overall_length += 4;
1126  needquote = false;
1127  }
1128  else
1129  {
1130  values[i] = OutputFunctionCall(&my_extra->proc, itemvalue);
1131 
1132  /* count data plus backslashes; detect chars needing quotes */
1133  if (values[i][0] == '\0')
1134  needquote = true; /* force quotes for empty string */
1135  else if (pg_strcasecmp(values[i], "NULL") == 0)
1136  needquote = true; /* force quotes for literal NULL */
1137  else
1138  needquote = false;
1139 
1140  for (tmp = values[i]; *tmp != '\0'; tmp++)
1141  {
1142  char ch = *tmp;
1143 
1144  overall_length += 1;
1145  if (ch == '"' || ch == '\\')
1146  {
1147  needquote = true;
1148  overall_length += 1;
1149  }
1150  else if (ch == '{' || ch == '}' || ch == typdelim ||
1151  array_isspace(ch))
1152  needquote = true;
1153  }
1154  }
1155 
1156  needquotes[i] = needquote;
1157 
1158  /* Count the pair of double quotes, if needed */
1159  if (needquote)
1160  overall_length += 2;
1161  /* and the comma */
1162  overall_length += 1;
1163  }
1164 
1165  /*
1166  * count total number of curly braces in output string
1167  */
1168  for (i = j = 0, k = 1; i < ndim; i++)
1169  k *= dims[i], j += k;
1170 
1171  dims_str[0] = '\0';
1172 
1173  /* add explicit dimensions if required */
1174  if (needdims)
1175  {
1176  char *ptr = dims_str;
1177 
1178  for (i = 0; i < ndim; i++)
1179  {
1180  sprintf(ptr, "[%d:%d]", lb[i], lb[i] + dims[i] - 1);
1181  ptr += strlen(ptr);
1182  }
1183  *ptr++ = *ASSGN;
1184  *ptr = '\0';
1185  }
1186 
1187  retval = (char *) palloc(strlen(dims_str) + overall_length + 2 * j);
1188  p = retval;
1189 
1190 #define APPENDSTR(str) (strcpy(p, (str)), p += strlen(p))
1191 #define APPENDCHAR(ch) (*p++ = (ch), *p = '\0')
1192 
1193  if (needdims)
1194  APPENDSTR(dims_str);
1195  APPENDCHAR('{');
1196  for (i = 0; i < ndim; i++)
1197  indx[i] = 0;
1198  j = 0;
1199  k = 0;
1200  do
1201  {
1202  for (i = j; i < ndim - 1; i++)
1203  APPENDCHAR('{');
1204 
1205  if (needquotes[k])
1206  {
1207  APPENDCHAR('"');
1208  for (tmp = values[k]; *tmp; tmp++)
1209  {
1210  char ch = *tmp;
1211 
1212  if (ch == '"' || ch == '\\')
1213  *p++ = '\\';
1214  *p++ = ch;
1215  }
1216  *p = '\0';
1217  APPENDCHAR('"');
1218  }
1219  else
1220  APPENDSTR(values[k]);
1221  pfree(values[k++]);
1222 
1223  for (i = ndim - 1; i >= 0; i--)
1224  {
1225  indx[i] = (indx[i] + 1) % dims[i];
1226  if (indx[i])
1227  {
1228  APPENDCHAR(typdelim);
1229  break;
1230  }
1231  else
1232  APPENDCHAR('}');
1233  }
1234  j = i;
1235  } while (j != -1);
1236 
1237 #undef APPENDSTR
1238 #undef APPENDCHAR
1239 
1240  pfree(values);
1241  pfree(needquotes);
1242 
1243  PG_RETURN_CSTRING(retval);
1244 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:259
static bool array_isspace(char ch)
Definition: arrayfuncs.c:432
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define MAXDIM
Definition: c.h:467
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
char * pstrdup(const char *in)
Definition: mcxt.c:1076
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
unsigned int Oid
Definition: postgres_ext.h:31
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1662
bool typbyval
Definition: array.h:225
void pfree(void *pointer)
Definition: mcxt.c:949
#define APPENDCHAR(ch)
#define APPENDSTR(str)
int16 typlen
Definition: array.h:224
char typdelim
Definition: array.h:227
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
#define ASSGN
Definition: arrayfuncs.c:45
uintptr_t Datum
Definition: postgres.h:372
#define AARR_DIMS(a)
Definition: array.h:321
#define AARR_ELEMTYPE(a)
Definition: array.h:319
#define AARR_LBOUND(a)
Definition: array.h:323
Oid typioparam
Definition: array.h:228
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:322
#define AARR_NDIM(a)
Definition: array.h:313
Oid typiofunc
Definition: array.h:229
char typalign
Definition: array.h:226
static Datum values[MAXATTR]
Definition: bootstrap.c:164
void * palloc(Size size)
Definition: mcxt.c:848
FmgrInfo proc
Definition: array.h:230
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
int i
Oid element_type
Definition: array.h:223
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition: lsyscache.c:2094

◆ array_recv()

Datum array_recv ( PG_FUNCTION_ARGS  )

Definition at line 1255 of file arrayfuncs.c.

References ARR_DIMS, ARR_LBOUND, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ArrayGetNItems(), buf, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, ArrayMetaState::element_type, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, fmgr_info_cxt(), FmgrInfo::fn_mcxt, format_type_be(), get_type_io_data(), i, IOFunc_receive, MAXDIM, MemoryContextAlloc(), ArrayType::ndim, ArrayIteratorData::nitems, OidIsValid, palloc(), palloc0(), pfree(), PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_ARRAYTYPE_P, pq_getmsgint(), ArrayMetaState::proc, ReadArrayBinary(), SET_VARSIZE, ArrayIteratorData::typalign, ArrayMetaState::typalign, ArrayIteratorData::typbyval, ArrayMetaState::typbyval, ArrayMetaState::typdelim, ArrayMetaState::typiofunc, ArrayMetaState::typioparam, ArrayIteratorData::typlen, and ArrayMetaState::typlen.

Referenced by int2vectorrecv(), and oidvectorrecv().

1256 {
1258  Oid spec_element_type = PG_GETARG_OID(1); /* type of an array
1259  * element */
1260  int32 typmod = PG_GETARG_INT32(2); /* typmod for array elements */
1261  Oid element_type;
1262  int typlen;
1263  bool typbyval;
1264  char typalign;
1265  Oid typioparam;
1266  int i,
1267  nitems;
1268  Datum *dataPtr;
1269  bool *nullsPtr;
1270  bool hasnulls;
1271  int32 nbytes;
1272  int32 dataoffset;
1273  ArrayType *retval;
1274  int ndim,
1275  flags,
1276  dim[MAXDIM],
1277  lBound[MAXDIM];
1278  ArrayMetaState *my_extra;
1279 
1280  /* Get the array header information */
1281  ndim = pq_getmsgint(buf, 4);
1282  if (ndim < 0) /* we do allow zero-dimension arrays */
1283  ereport(ERROR,
1284  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1285  errmsg("invalid number of dimensions: %d", ndim)));
1286  if (ndim > MAXDIM)
1287  ereport(ERROR,
1288  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1289  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
1290  ndim, MAXDIM)));
1291 
1292  flags = pq_getmsgint(buf, 4);
1293  if (flags != 0 && flags != 1)
1294  ereport(ERROR,
1295  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1296  errmsg("invalid array flags")));
1297 
1298  element_type = pq_getmsgint(buf, sizeof(Oid));
1299  if (element_type != spec_element_type)
1300  {
1301  /* XXX Can we allow taking the input element type in any cases? */
1302  ereport(ERROR,
1303  (errcode(ERRCODE_DATATYPE_MISMATCH),
1304  errmsg("wrong element type")));
1305  }
1306 
1307  for (i = 0; i < ndim; i++)
1308  {
1309  dim[i] = pq_getmsgint(buf, 4);
1310  lBound[i] = pq_getmsgint(buf, 4);
1311 
1312  /*
1313  * Check overflow of upper bound. (ArrayNItems() below checks that
1314  * dim[i] >= 0)
1315  */
1316  if (dim[i] != 0)
1317  {
1318  int ub = lBound[i] + dim[i] - 1;
1319 
1320  if (lBound[i] > ub)
1321  ereport(ERROR,
1322  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1323  errmsg("integer out of range")));
1324  }
1325  }
1326 
1327  /* This checks for overflow of array dimensions */
1328  nitems = ArrayGetNItems(ndim, dim);
1329 
1330  /*
1331  * We arrange to look up info about element type, including its receive
1332  * conversion proc, only once per series of calls, assuming the element
1333  * type doesn't change underneath us.
1334  */
1335  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1336  if (my_extra == NULL)
1337  {
1338  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1339  sizeof(ArrayMetaState));
1340  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1341  my_extra->element_type = ~element_type;
1342  }
1343 
1344  if (my_extra->element_type != element_type)
1345  {
1346  /* Get info about element type, including its receive proc */
1347  get_type_io_data(element_type, IOFunc_receive,
1348  &my_extra->typlen, &my_extra->typbyval,
1349  &my_extra->typalign, &my_extra->typdelim,
1350  &my_extra->typioparam, &my_extra->typiofunc);
1351  if (!OidIsValid(my_extra->typiofunc))
1352  ereport(ERROR,
1353  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1354  errmsg("no binary input function available for type %s",
1355  format_type_be(element_type))));
1356  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1357  fcinfo->flinfo->fn_mcxt);
1358  my_extra->element_type = element_type;
1359  }
1360 
1361  if (nitems == 0)
1362  {
1363  /* Return empty array ... but not till we've validated element_type */
1365  }
1366 
1367  typlen = my_extra->typlen;
1368  typbyval = my_extra->typbyval;
1369  typalign = my_extra->typalign;
1370  typioparam = my_extra->typioparam;
1371 
1372  dataPtr = (Datum *) palloc(nitems * sizeof(Datum));
1373  nullsPtr = (bool *) palloc(nitems * sizeof(bool));
1374  ReadArrayBinary(buf, nitems,
1375  &my_extra->proc, typioparam, typmod,
1376  typlen, typbyval, typalign,
1377  dataPtr, nullsPtr,
1378  &hasnulls, &nbytes);
1379  if (hasnulls)
1380  {
1381  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
1382  nbytes += dataoffset;
1383  }
1384  else
1385  {
1386  dataoffset = 0; /* marker for no null bitmap */
1387  nbytes += ARR_OVERHEAD_NONULLS(ndim);
1388  }
1389  retval = (ArrayType *) palloc0(nbytes);
1390  SET_VARSIZE(retval, nbytes);
1391  retval->ndim = ndim;
1392  retval->dataoffset = dataoffset;
1393  retval->elemtype = element_type;
1394  memcpy(ARR_DIMS(retval), dim, ndim * sizeof(int));
1395  memcpy(ARR_LBOUND(retval), lBound, ndim * sizeof(int));
1396 
1397  CopyArrayEls(retval,
1398  dataPtr, nullsPtr, nitems,
1399  typlen, typbyval, typalign,
1400  true);
1401 
1402  pfree(dataPtr);
1403  pfree(nullsPtr);
1404 
1405  PG_RETURN_ARRAYTYPE_P(retval);
1406 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define MAXDIM
Definition: c.h:467
int32 dataoffset
Definition: array.h:84
StringInfoData * StringInfo
Definition: stringinfo.h:43
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3398
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:297
signed int int32
Definition: c.h:284
#define ARR_LBOUND(a)
Definition: array.h:281
bool typbyval
Definition: array.h:225
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:279
int16 typlen
Definition: array.h:224
static char * buf
Definition: pg_test_fsync.c:67
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
char typdelim
Definition: array.h:227
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define ereport(elevel, rest)
Definition: elog.h:122
static void ReadArrayBinary(StringInfo buf, int nitems, FmgrInfo *receiveproc, Oid typioparam, int32 typmod, int typlen, bool typbyval, char typalign, Datum *values, bool *nulls, bool *hasnulls, int32 *nbytes)
Definition: arrayfuncs.c:1430
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
Oid typioparam
Definition: array.h:228
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:957
Oid typiofunc
Definition: array.h:229
char typalign
Definition: array.h:226
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
FmgrInfo proc
Definition: array.h:230
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
int i
Oid element_type
Definition: array.h:223
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
int ndim
Definition: array.h:83
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition: lsyscache.c:2094

◆ array_ref()

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

Definition at line 3064 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3067 {
3068  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3069  arraytyplen, elmlen, elmbyval, elmalign,
3070  isNull);
3071 }
#define PointerGetDatum(X)
Definition: postgres.h:562
Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1807

◆ array_remove()

Datum array_remove ( PG_FUNCTION_ARGS  )

Definition at line 6288 of file arrayfuncs.c.

References array_replace_internal(), PG_ARGISNULL, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_ARRAYTYPE_P, and PG_RETURN_NULL.

6289 {
6290  ArrayType *array;
6291  Datum search = PG_GETARG_DATUM(1);
6292  bool search_isnull = PG_ARGISNULL(1);
6293 
6294  if (PG_ARGISNULL(0))
6295  PG_RETURN_NULL();
6296  array = PG_GETARG_ARRAYTYPE_P(0);
6297 
6298  array = array_replace_internal(array,
6299  search, search_isnull,
6300  (Datum) 0, true,
6301  true, PG_GET_COLLATION(),
6302  fcinfo);
6303  PG_RETURN_ARRAYTYPE_P(array);
6304 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GET_COLLATION()
Definition: fmgr.h:163
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
uintptr_t Datum
Definition: postgres.h:372
static ArrayType * array_replace_internal(ArrayType *array, Datum search, bool search_isnull, Datum replace, bool replace_isnull, bool remove, Oid collation, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:6030
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ array_replace()

Datum array_replace ( PG_FUNCTION_ARGS  )

Definition at line 6310 of file arrayfuncs.c.

References array_replace_internal(), PG_ARGISNULL, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_ARRAYTYPE_P, and PG_RETURN_NULL.

6311 {
6312  ArrayType *array;
6313  Datum search = PG_GETARG_DATUM(1);
6314  bool search_isnull = PG_ARGISNULL(1);
6315  Datum replace = PG_GETARG_DATUM(2);
6316  bool replace_isnull = PG_ARGISNULL(2);
6317 
6318  if (PG_ARGISNULL(0))
6319  PG_RETURN_NULL();
6320  array = PG_GETARG_ARRAYTYPE_P(0);
6321 
6322  array = array_replace_internal(array,
6323  search, search_isnull,
6324  replace, replace_isnull,
6325  false, PG_GET_COLLATION(),
6326  fcinfo);
6327  PG_RETURN_ARRAYTYPE_P(array);
6328 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GET_COLLATION()
Definition: fmgr.h:163
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
uintptr_t Datum
Definition: postgres.h:372
static ArrayType * array_replace_internal(ArrayType *array, Datum search, bool search_isnull, Datum replace, bool replace_isnull, bool remove, Oid collation, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:6030
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ array_replace_internal()

static ArrayType * array_replace_internal ( ArrayType array,
Datum  search,
bool  search_isnull,
Datum  replace,
bool  replace_isnull,
bool  remove,
Oid  collation,
FunctionCallInfo  fcinfo 
)
static

Definition at line 6030 of file arrayfuncs.c.

References AllocSizeIsValid, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ArrayGetNItems(), att_addlength_datum, att_align_nominal, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, DatumGetBool, ArrayType::elemtype, TypeCacheEntry::eq_opr_finfo, ereport, errcode(), errmsg(), ERROR, fetch_att, FunctionCallInfoData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_oid, format_type_be(), FunctionCallInvoke, i, InitFunctionCallInfoData, FunctionCallInfoData::isnull, lookup_type_cache(), MaxAllocSize, ArrayType::ndim, ArrayIteratorData::nitems, OidIsValid, palloc(), palloc0(), pfree(), PG_DETOAST_DATUM, PointerGetDatum, SET_VARSIZE, skip(), TypeCacheEntry::typalign, ArrayIteratorData::typalign, TypeCacheEntry::typbyval, ArrayIteratorData::typbyval, TypeCacheEntry::type_id, TYPECACHE_EQ_OPR_FINFO, TypeCacheEntry::typlen, ArrayIteratorData::typlen, and values.

Referenced by array_remove(), and array_replace().

6035 {
6036  ArrayType *result;
6037  Oid element_type;
6038  Datum *values;
6039  bool *nulls;
6040  int *dim;
6041  int ndim;
6042  int nitems,
6043  nresult;
6044  int i;
6045  int32 nbytes = 0;
6046  int32 dataoffset;
6047  bool hasnulls;
6048  int typlen;
6049  bool typbyval;
6050  char typalign;
6051  char *arraydataptr;
6052  bits8 *bitmap;
6053  int bitmask;
6054  bool changed = false;
6055  TypeCacheEntry *typentry;
6056  FunctionCallInfoData locfcinfo;
6057 
6058  element_type = ARR_ELEMTYPE(array);
6059  ndim = ARR_NDIM(array);
6060  dim = ARR_DIMS(array);
6061  nitems = ArrayGetNItems(ndim, dim);
6062 
6063  /* Return input array unmodified if it is empty */
6064  if (nitems <= 0)
6065  return array;
6066 
6067  /*
6068  * We can't remove elements from multi-dimensional arrays, since the
6069  * result might not be rectangular.
6070  */
6071  if (remove && ndim > 1)
6072  ereport(ERROR,
6073  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6074  errmsg("removing elements from multidimensional arrays is not supported")));
6075 
6076  /*
6077  * We arrange to look up the equality function only once per series of
6078  * calls, assuming the element type doesn't change underneath us.
6079  */
6080  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
6081  if (typentry == NULL ||
6082  typentry->type_id != element_type)
6083  {
6084  typentry = lookup_type_cache(element_type,
6086  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
6087  ereport(ERROR,
6088  (errcode(ERRCODE_UNDEFINED_FUNCTION),
6089  errmsg("could not identify an equality operator for type %s",
6090  format_type_be(element_type))));
6091  fcinfo->flinfo->fn_extra = (void *) typentry;
6092  }
6093  typlen = typentry->typlen;
6094  typbyval = typentry->typbyval;
6095  typalign = typentry->typalign;
6096 
6097  /*
6098  * Detoast values if they are toasted. The replacement value must be
6099  * detoasted for insertion into the result array, while detoasting the
6100  * search value only once saves cycles.
6101  */
6102  if (typlen == -1)
6103  {
6104  if (!search_isnull)
6105  search = PointerGetDatum(PG_DETOAST_DATUM(search));
6106  if (!replace_isnull)
6107  replace = PointerGetDatum(PG_DETOAST_DATUM(replace));
6108  }
6109 
6110  /* Prepare to apply the comparison operator */
6111  InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
6112  collation, NULL, NULL);
6113 
6114  /* Allocate temporary arrays for new values */
6115  values = (Datum *) palloc(nitems * sizeof(Datum));
6116  nulls = (bool *) palloc(nitems * sizeof(bool));
6117 
6118  /* Loop over source data */
6119  arraydataptr = ARR_DATA_PTR(array);
6120  bitmap = ARR_NULLBITMAP(array);
6121  bitmask = 1;
6122  hasnulls = false;
6123  nresult = 0;
6124 
6125  for (i = 0; i < nitems; i++)
6126  {
6127  Datum elt;
6128  bool isNull;
6129  bool oprresult;
6130  bool skip = false;
6131 
6132  /* Get source element, checking for NULL */
6133  if (bitmap && (*bitmap & bitmask) == 0)
6134  {
6135  isNull = true;
6136  /* If searching for NULL, we have a match */
6137  if (search_isnull)
6138  {
6139  if (remove)
6140  {
6141  skip = true;
6142  changed = true;
6143  }
6144  else if (!replace_isnull)
6145  {
6146  values[nresult] = replace;
6147  isNull = false;
6148  changed = true;
6149  }
6150  }
6151  }
6152  else
6153  {
6154  isNull = false;
6155  elt = fetch_att(arraydataptr, typbyval, typlen);
6156  arraydataptr = att_addlength_datum(arraydataptr, typlen, elt);
6157  arraydataptr = (char *) att_align_nominal(arraydataptr, typalign);
6158 
6159  if (search_isnull)
6160  {
6161  /* no match possible, keep element */
6162  values[nresult] = elt;
6163  }
6164  else
6165  {
6166  /*
6167  * Apply the operator to the element pair
6168  */
6169  locfcinfo.arg[0] = elt;
6170  locfcinfo.arg[1] = search;
6171  locfcinfo.argnull[0] = false;
6172  locfcinfo.argnull[1] = false;
6173  locfcinfo.isnull = false;
6174  oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
6175  if (!oprresult)
6176  {
6177  /* no match, keep element */
6178  values[nresult] = elt;
6179  }
6180  else
6181  {
6182  /* match, so replace or delete */
6183  changed = true;
6184  if (remove)
6185  skip = true;
6186  else
6187  {
6188  values[nresult] = replace;
6189  isNull = replace_isnull;
6190  }
6191  }
6192  }
6193  }
6194 
6195  if (!skip)
6196  {
6197  nulls[nresult] = isNull;
6198  if (isNull)
6199  hasnulls = true;
6200  else
6201  {
6202  /* Update total result size */
6203  nbytes = att_addlength_datum(nbytes, typlen, values[nresult]);
6204  nbytes = att_align_nominal(nbytes, typalign);
6205  /* check for overflow of total request */
6206  if (!AllocSizeIsValid(nbytes))
6207  ereport(ERROR,
6208  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
6209  errmsg("array size exceeds the maximum allowed (%d)",
6210  (int) MaxAllocSize)));
6211  }
6212  nresult++;
6213  }
6214 
6215  /* advance bitmap pointer if any */
6216  if (bitmap)
6217  {
6218  bitmask <<= 1;
6219  if (bitmask == 0x100)
6220  {
6221  bitmap++;
6222  bitmask = 1;
6223  }
6224  }
6225  }
6226 
6227  /*
6228  * If not changed just return the original array
6229  */
6230  if (!changed)
6231  {
6232  pfree(values);
6233  pfree(nulls);
6234  return array;
6235  }
6236 
6237  /* If all elements were removed return an empty array */
6238  if (nresult == 0)
6239  {
6240  pfree(values);
6241  pfree(nulls);
6242  return construct_empty_array(element_type);
6243  }
6244 
6245  /* Allocate and initialize the result array */
6246  if (hasnulls)
6247  {
6248  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nresult);
6249  nbytes += dataoffset;
6250  }
6251  else
6252  {
6253  dataoffset = 0; /* marker for no null bitmap */
6254  nbytes += ARR_OVERHEAD_NONULLS(ndim);
6255  }
6256  result = (ArrayType *) palloc0(nbytes);
6257  SET_VARSIZE(result, nbytes);
6258  result->ndim = ndim;
6259  result->dataoffset = dataoffset;
6260  result->elemtype = element_type;
6261  memcpy(ARR_DIMS(result), ARR_DIMS(array), ndim * sizeof(int));
6262  memcpy(ARR_LBOUND(result), ARR_LBOUND(array), ndim * sizeof(int));
6263 
6264  if (remove)
6265  {
6266  /* Adjust the result length */
6267  ARR_DIMS(result)[0] = nresult;
6268  }
6269 
6270  /* Insert data into result array */
6271  CopyArrayEls(result,
6272  values, nulls, nresult,
6273  typlen, typbyval, typalign,
6274  false);
6275 
6276  pfree(values);
6277  pfree(nulls);
6278 
6279  return result;
6280 }
static void skip(struct vars *v)
Definition: regc_lex.c:1109
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define PointerGetDatum(X)
Definition: postgres.h:562
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:129
int32 dataoffset
Definition: array.h:84
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3398
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
bool typbyval
Definition: typcache.h:38
#define OidIsValid(objectId)
Definition: c.h:576
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:297
signed int int32
Definition: c.h:284
#define ARR_LBOUND(a)
Definition: array.h:281
FmgrInfo * flinfo
Definition: fmgr.h:79
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:137
#define DatumGetBool(X)
Definition: postgres.h:399
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:86
#define ereport(elevel, rest)
Definition: elog.h:122
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
uint8 bits8
Definition: c.h:303
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
FmgrInfo eq_opr_finfo
Definition: typcache.h:71
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:311
Oid fn_oid
Definition: fmgr.h:59
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:85
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:120
void * fn_extra
Definition: fmgr.h:64
#define ARR_NDIM(a)
Definition: array.h:275
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:957
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
char typalign
Definition: typcache.h:39
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
int i
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:205
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
#define ARR_ELEMTYPE(a)
Definition: array.h:277
#define ARR_NULLBITMAP(a)
Definition: array.h:285
int ndim
Definition: array.h:83

◆ array_seek()

static char * array_seek ( char *  ptr,
int  offset,
bits8 nullbitmap,
int  nitems,
int  typlen,
bool  typbyval,
char  typalign 
)
static

Definition at line 4576 of file arrayfuncs.c.

References att_addlength_pointer, att_align_nominal, i, and ArrayIteratorData::nitems.

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

4578 {
4579  int bitmask;
4580  int i;
4581 
4582  /* easy if fixed-size elements and no NULLs */
4583  if (typlen > 0 && !nullbitmap)
4584  return ptr + nitems * ((Size) att_align_nominal(typlen, typalign));
4585 
4586  /* seems worth having separate loops for NULL and no-NULLs cases */
4587  if (nullbitmap)
4588  {
4589  nullbitmap += offset / 8;
4590  bitmask = 1 << (offset % 8);
4591 
4592  for (i = 0; i < nitems; i++)
4593  {
4594  if (*nullbitmap & bitmask)
4595  {
4596  ptr = att_addlength_pointer(ptr, typlen, ptr);
4597  ptr = (char *) att_align_nominal(ptr, typalign);
4598  }
4599  bitmask <<= 1;
4600  if (bitmask == 0x100)
4601  {
4602  nullbitmap++;
4603  bitmask = 1;
4604  }
4605  }
4606  }
4607  else
4608  {
4609  for (i = 0; i < nitems; i++)
4610  {
4611  ptr = att_addlength_pointer(ptr, typlen, ptr);
4612  ptr = (char *) att_align_nominal(ptr, typalign);
4613  }
4614  }
4615  return ptr;
4616 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
size_t Size
Definition: c.h:404
int i

◆ array_send()

Datum array_send ( PG_FUNCTION_ARGS  )

Definition at line 1535 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_HASNULL, AARR_LBOUND, AARR_NDIM, array_iter_next(), array_iter_setup(), ArrayGetNItems(), buf, ArrayMetaState::element_type, ereport, errcode(), errmsg(), ERROR, fmgr_info_cxt(), FmgrInfo::fn_mcxt, format_type_be(), get_type_io_data(), i, IOFunc_send, MemoryContextAlloc(), ArrayIteratorData::nitems, OidIsValid, pfree(), PG_GETARG_ANY_ARRAY_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendbytes(), pq_sendint32(), ArrayMetaState::proc, SendFunctionCall(), ArrayIteratorData::typalign, ArrayMetaState::typalign, ArrayIteratorData::typbyval, ArrayMetaState::typbyval, ArrayMetaState::typdelim, ArrayMetaState::typiofunc, ArrayMetaState::typioparam, ArrayIteratorData::typlen, ArrayMetaState::typlen, VARDATA, VARHDRSZ, and VARSIZE.

Referenced by anyarray_send(), int2vectorsend(), and oidvectorsend().

1536 {
1538  Oid element_type = AARR_ELEMTYPE(v);
1539  int typlen;
1540  bool typbyval;
1541  char typalign;
1542  int nitems,
1543  i;
1544  int ndim,
1545  *dim,
1546  *lb;
1548  array_iter iter;
1549  ArrayMetaState *my_extra;
1550 
1551  /*
1552  * We arrange to look up info about element type, including its send
1553  * conversion proc, only once per series of calls, assuming the element
1554  * type doesn't change underneath us.
1555  */
1556  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1557  if (my_extra == NULL)
1558  {
1559  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1560  sizeof(ArrayMetaState));
1561  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1562  my_extra->element_type = ~element_type;
1563  }
1564 
1565  if (my_extra->element_type != element_type)
1566  {
1567  /* Get info about element type, including its send proc */
1568  get_type_io_data(element_type, IOFunc_send,
1569  &my_extra->typlen, &my_extra->typbyval,
1570  &my_extra->typalign, &my_extra->typdelim,
1571  &my_extra->typioparam, &my_extra->typiofunc);
1572  if (!OidIsValid(my_extra->typiofunc))
1573  ereport(ERROR,
1574  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1575  errmsg("no binary output function available for type %s",
1576  format_type_be(element_type))));
1577  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1578  fcinfo->flinfo->fn_mcxt);
1579  my_extra->element_type = element_type;
1580  }
1581  typlen = my_extra->typlen;
1582  typbyval = my_extra->typbyval;
1583  typalign = my_extra->typalign;
1584 
1585  ndim = AARR_NDIM(v);
1586  dim = AARR_DIMS(v);
1587  lb = AARR_LBOUND(v);
1588  nitems = ArrayGetNItems(ndim, dim);
1589 
1590  pq_begintypsend(&buf);
1591 
1592  /* Send the array header information */
1593  pq_sendint32(&buf, ndim);
1594  pq_sendint32(&buf, AARR_HASNULL(v) ? 1 : 0);
1595  pq_sendint32(&buf, element_type);
1596  for (i = 0; i < ndim; i++)
1597  {
1598  pq_sendint32(&buf, dim[i]);
1599  pq_sendint32(&buf, lb[i]);
1600  }
1601 
1602  /* Send the array elements using the element's own sendproc */
1603  array_iter_setup(&iter, v);
1604 
1605  for (i = 0; i < nitems; i++)
1606  {
1607  Datum itemvalue;
1608  bool isnull;
1609 
1610  /* Get source element, checking for NULL */
1611  itemvalue = array_iter_next(&iter, &isnull, i,
1612  typlen, typbyval, typalign);
1613 
1614  if (isnull)
1615  {
1616  /* -1 length means a NULL */
1617  pq_sendint32(&buf, -1);
1618  }
1619  else
1620  {
1621  bytea *outputbytes;
1622 
1623  outputbytes = SendFunctionCall(&my_extra->proc, itemvalue);
1624  pq_sendint32(&buf, VARSIZE(outputbytes) - VARHDRSZ);
1625  pq_sendbytes(&buf, VARDATA(outputbytes),
1626  VARSIZE(outputbytes) - VARHDRSZ);
1627  pfree(outputbytes);
1628  }
1629  }
1630 
1632 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:259
#define VARDATA(PTR)
Definition: postgres.h:303
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define VARSIZE(PTR)
Definition: postgres.h:304
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
static void pq_sendint32(StringInfo buf, int32 i)
Definition: pqformat.h:148
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
#define VARHDRSZ
Definition: c.h:493
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define AARR_HASNULL(a)
Definition: array.h:315
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:330
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
bool typbyval
Definition: array.h:225
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
int16 typlen
Definition: array.h:224
static char * buf
Definition: pg_test_fsync.c:67
char typdelim
Definition: array.h:227
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1723
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define AARR_DIMS(a)
Definition: array.h:321
#define AARR_ELEMTYPE(a)
Definition: array.h:319
#define AARR_LBOUND(a)
Definition: array.h:323
Oid typioparam
Definition: array.h:228
#define AARR_NDIM(a)
Definition: array.h:313
Oid typiofunc
Definition: array.h:229
char typalign
Definition: array.h:226
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
int errmsg(const char *fmt,...)
Definition: elog.c:797
FmgrInfo proc
Definition: array.h:230
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
int i
Oid element_type
Definition: array.h:223
Definition: c.h:487
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition: lsyscache.c:2094

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

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3084 {
3086  nSubscripts, indx,
3087  dataValue, isNull,
3088  arraytyplen,
3089  elmlen, elmbyval, elmalign));
3090 }
#define PointerGetDatum(X)
Definition: postgres.h:562
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:2187
#define DatumGetArrayTypeP(X)
Definition: array.h:246

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

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(), ArrayGetNItems(), ArrayGetOffset(), att_addlength_datum, att_addlength_pointer, att_align_nominal, construct_md_array(), ArrayType::dataoffset, DatumGetArrayTypeP, DatumGetPointer, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, MAXDIM, MemSet, ArrayType::ndim, palloc(), palloc0(), PG_DETOAST_DATUM, PointerGetDatum, SET_VARSIZE, and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by array_append(), array_prepend(), array_set(), exec_assign_value(), and ExecEvalArrayRefAssign().

2196 {
2197  ArrayType *array;
2198  ArrayType *newarray;
2199  int i,
2200  ndim,
2201  dim[MAXDIM],
2202  lb[MAXDIM],
2203  offset;
2204  char *elt_ptr;
2205  bool newhasnulls;
2206  bits8 *oldnullbitmap;
2207  int oldnitems,
2208  newnitems,
2209  olddatasize,
2210  newsize,
2211  olditemlen,
2212  newitemlen,
2213  overheadlen,
2214  oldoverheadlen,
2215  addedbefore,
2216  addedafter,
2217  lenbefore,
2218  lenafter;
2219 
2220  if (arraytyplen > 0)
2221  {
2222  /*
2223  * fixed-length arrays -- these are assumed to be 1-d, 0-based. We
2224  * cannot extend them, either.
2225  */
2226  char *resultarray;
2227 
2228  if (nSubscripts != 1)
2229  ereport(ERROR,
2230  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2231  errmsg("wrong number of array subscripts")));
2232 
2233  if (indx[0] < 0 || indx[0] * elmlen >= arraytyplen)
2234  ereport(ERROR,
2235  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2236  errmsg("array subscript out of range")));
2237 
2238  if (isNull)
2239  ereport(ERROR,
2240  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
2241  errmsg("cannot assign null value to an element of a fixed-length array")));
2242 
2243  resultarray = (char *) palloc(arraytyplen);
2244  memcpy(resultarray, DatumGetPointer(arraydatum), arraytyplen);
2245  elt_ptr = (char *) resultarray + indx[0] * elmlen;
2246  ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elt_ptr);
2247  return PointerGetDatum(resultarray);
2248  }
2249 
2250  if (nSubscripts <= 0 || nSubscripts > MAXDIM)
2251  ereport(ERROR,
2252  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2253  errmsg("wrong number of array subscripts")));
2254 
2255  /* make sure item to be inserted is not toasted */
2256  if (elmlen == -1 && !isNull)
2257  dataValue = PointerGetDatum(PG_DETOAST_DATUM(dataValue));
2258 
2260  {
2261  /* expanded array: let's do this in a separate function */
2262  return array_set_element_expanded(arraydatum,
2263  nSubscripts,
2264  indx,
2265  dataValue,
2266  isNull,
2267  arraytyplen,
2268  elmlen,
2269  elmbyval,
2270  elmalign);
2271  }
2272 
2273  /* detoast input array if necessary */
2274  array = DatumGetArrayTypeP(arraydatum);
2275 
2276  ndim = ARR_NDIM(array);
2277 
2278  /*
2279  * if number of dims is zero, i.e. an empty array, create an array with
2280  * nSubscripts dimensions, and set the lower bounds to the supplied
2281  * subscripts
2282  */
2283  if (ndim == 0)
2284  {
2285  Oid elmtype = ARR_ELEMTYPE(array);
2286 
2287  for (i = 0; i < nSubscripts; i++)
2288  {
2289  dim[i] = 1;
2290  lb[i] = indx[i];
2291  }
2292 
2293  return PointerGetDatum(construct_md_array(&dataValue, &isNull,
2294  nSubscripts, dim, lb,
2295  elmtype,
2296  elmlen, elmbyval, elmalign));
2297  }
2298 
2299  if (ndim != nSubscripts)
2300  ereport(ERROR,
2301  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2302  errmsg("wrong number of array subscripts")));
2303 
2304  /* copy dim/lb since we may modify them */
2305  memcpy(dim, ARR_DIMS(array), ndim * sizeof(int));
2306  memcpy(lb, ARR_LBOUND(array), ndim * sizeof(int));
2307 
2308  newhasnulls = (ARR_HASNULL(array) || isNull);
2309  addedbefore = addedafter = 0;
2310 
2311  /*
2312  * Check subscripts
2313  */
2314  if (ndim == 1)
2315  {
2316  if (indx[0] < lb[0])
2317  {
2318  addedbefore = lb[0] - indx[0];
2319  dim[0] += addedbefore;
2320  lb[0] = indx[0];
2321  if (addedbefore > 1)
2322  newhasnulls = true; /* will insert nulls */
2323  }
2324  if (indx[0] >= (dim[0] + lb[0]))
2325  {
2326  addedafter = indx[0] - (dim[0] + lb[0]) + 1;
2327  dim[0] += addedafter;
2328  if (addedafter > 1)
2329  newhasnulls = true; /* will insert nulls */
2330  }
2331  }
2332  else
2333  {
2334  /*
2335  * XXX currently we do not support extending multi-dimensional arrays
2336  * during assignment
2337  */
2338  for (i = 0; i < ndim; i++)
2339  {
2340  if (indx[i] < lb[i] ||
2341  indx[i] >= (dim[i] + lb[i]))
2342  ereport(ERROR,
2343  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2344  errmsg("array subscript out of range")));
2345  }
2346  }
2347 
2348  /*
2349  * Compute sizes of items and areas to copy
2350  */
2351  newnitems = ArrayGetNItems(ndim, dim);
2352  if (newhasnulls)
2353  overheadlen = ARR_OVERHEAD_WITHNULLS(ndim, newnitems);
2354  else
2355  overheadlen = ARR_OVERHEAD_NONULLS(ndim);
2356  oldnitems = ArrayGetNItems(ndim, ARR_DIMS(array));
2357  oldnullbitmap = ARR_NULLBITMAP(array);
2358  oldoverheadlen = ARR_DATA_OFFSET(array);
2359  olddatasize = ARR_SIZE(array) - oldoverheadlen;
2360  if (addedbefore)
2361  {
2362  offset = 0;
2363  lenbefore = 0;
2364  olditemlen = 0;
2365  lenafter = olddatasize;
2366  }
2367  else if (addedafter)
2368  {
2369  offset = oldnitems;
2370  lenbefore = olddatasize;
2371  olditemlen = 0;
2372  lenafter = 0;
2373  }
2374  else
2375  {
2376  offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
2377  elt_ptr = array_seek(ARR_DATA_PTR(array), 0, oldnullbitmap, offset,
2378  elmlen, elmbyval, elmalign);
2379  lenbefore = (int) (elt_ptr - ARR_DATA_PTR(array));
2380  if (array_get_isnull(oldnullbitmap, offset))
2381  olditemlen = 0;
2382  else
2383  {
2384  olditemlen = att_addlength_pointer(0, elmlen, elt_ptr);
2385  olditemlen = att_align_nominal(olditemlen, elmalign);
2386  }
2387  lenafter = (int) (olddatasize - lenbefore - olditemlen);
2388  }
2389 
2390  if (isNull)
2391  newitemlen = 0;
2392  else
2393  {
2394  newitemlen = att_addlength_datum(0, elmlen, dataValue);
2395  newitemlen = att_align_nominal(newitemlen, elmalign);
2396  }
2397 
2398  newsize = overheadlen + lenbefore + newitemlen + lenafter;
2399 
2400  /*
2401  * OK, create the new array and fill in header/dimensions
2402  */
2403  newarray = (ArrayType *) palloc0(newsize);
2404  SET_VARSIZE(newarray, newsize);
2405  newarray->ndim = ndim;
2406  newarray->dataoffset = newhasnulls ? overheadlen : 0;
2407  newarray->elemtype = ARR_ELEMTYPE(array);
2408  memcpy(ARR_DIMS(newarray), dim, ndim * sizeof(int));
2409  memcpy(ARR_LBOUND(newarray), lb, ndim * sizeof(int));
2410 
2411  /*
2412  * Fill in data
2413  */
2414  memcpy((char *) newarray + overheadlen,
2415  (char *) array + oldoverheadlen,
2416  lenbefore);
2417  if (!isNull)
2418  ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign,
2419  (char *) newarray + overheadlen + lenbefore);
2420  memcpy((char *) newarray + overheadlen + lenbefore + newitemlen,
2421  (char *) array + oldoverheadlen + lenbefore + olditemlen,
2422  lenafter);
2423 
2424  /*
2425  * Fill in nulls bitmap if needed
2426  *
2427  * Note: it's possible we just replaced the last NULL with a non-NULL, and
2428  * could get rid of the bitmap. Seems not worth testing for though.
2429  */
2430  if (newhasnulls)
2431  {
2432  bits8 *newnullbitmap = ARR_NULLBITMAP(newarray);
2433 
2434  /* Zero the bitmap to take care of marking inserted positions null */
2435  MemSet(newnullbitmap, 0, (newnitems + 7) / 8);
2436  /* Fix the inserted value */
2437  if (addedafter)
2438  array_set_isnull(newnullbitmap, newnitems - 1, isNull);
2439  else
2440  array_set_isnull(newnullbitmap, offset, isNull);
2441  /* Fix the copied range(s) */
2442  if (addedbefore)
2443  array_bitmap_copy(newnullbitmap, addedbefore,
2444  oldnullbitmap, 0,
2445  oldnitems);
2446  else
2447  {
2448  array_bitmap_copy(newnullbitmap, 0,
2449  oldnullbitmap, 0,
2450  offset);
2451  if (addedafter == 0)
2452  array_bitmap_copy(newnullbitmap, offset + 1,
2453  oldnullbitmap, offset + 1,
2454  oldnitems - offset - 1);
2455  }
2456  }
2457 
2458  return PointerGetDatum(newarray);
2459 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define ARR_SIZE(a)
Definition: array.h:274
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:323
#define MAXDIM
Definition: c.h:467
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
static int ArrayCastAndSet(Datum src, int typlen, bool typbyval, char typalign, char *dest)
Definition: arrayfuncs.c:4537
#define PointerGetDatum(X)
Definition: postgres.h:562
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4676
int32 dataoffset
Definition: array.h:84
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:853
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:297
#define ARR_DATA_OFFSET(a)
Definition: array.h:301
#define ARR_LBOUND(a)
Definition: array.h:281
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
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:2469
#define ARR_HASNULL(a)
Definition: array.h:276
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
#define ereport(elevel, rest)
Definition: elog.h:122
uint8 bits8
Definition: c.h:303
void * palloc0(Size size)
Definition: mcxt.c:877
static void array_set_isnull(bits8 *nullbitmap, int offset, bool isNull)
Definition: arrayfuncs.c:4508
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4576
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4491
#define ARR_NDIM(a)
Definition: array.h:275
#define DatumGetPointer(X)
Definition: postgres.h:555
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:205
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
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:3314
#define ARR_ELEMTYPE(a)
Definition: array.h:277
#define ARR_NULLBITMAP(a)
Definition: array.h:285
int ndim
Definition: array.h:83
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ array_set_element_expanded()

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

Definition at line 2469 of file arrayfuncs.c.

References ArrayGetOffset(), Assert, datumCopy(), DatumGetExpandedArray(), DatumGetPointer, deconstruct_expanded_array(), ExpandedArrayHeader::dims, ExpandedArrayHeader::dnulls, ExpandedArrayHeader::dvalues, ExpandedArrayHeader::dvalueslen, ExpandedObjectHeader::eoh_context, EOHPGetRWDatum, ereport, errcode(), errmsg(), ERROR, ExpandedArrayHeader::fendptr, ExpandedArrayHeader::flat_size, ExpandedArrayHeader::fvalue, ExpandedArrayHeader::hdr, i, ExpandedArrayHeader::lbound, Max, MAXDIM, memmove, MemoryContextAllocZero(), MemoryContextSwitchTo(), ExpandedArrayHeader::ndims, ExpandedArrayHeader::nelems, pfree(), repalloc(), ExpandedArrayHeader::typalign, ExpandedArrayHeader::typbyval, and ExpandedArrayHeader::typlen.

Referenced by array_set_element().

2474 {
2475  ExpandedArrayHeader *eah;
2476  Datum *dvalues;
2477  bool *dnulls;
2478  int i,
2479  ndim,
2480  dim[MAXDIM],
2481  lb[MAXDIM],
2482  offset;
2483  bool dimschanged,
2484  newhasnulls;
2485  int addedbefore,
2486  addedafter;
2487  char *oldValue;
2488 
2489  /* Convert to R/W object if not so already */
2490  eah = DatumGetExpandedArray(arraydatum);
2491 
2492  /* Sanity-check caller's info against object; we don't use it otherwise */
2493  Assert(arraytyplen == -1);
2494  Assert(elmlen == eah->typlen);
2495  Assert(elmbyval == eah->typbyval);
2496  Assert(elmalign == eah->typalign);
2497 
2498  /*
2499  * Copy dimension info into local storage. This allows us to modify the
2500  * dimensions if needed, while not messing up the expanded value if we
2501  * fail partway through.
2502  */
2503  ndim = eah->ndims;
2504  Assert(ndim >= 0 && ndim <= MAXDIM);
2505  memcpy(dim, eah->dims, ndim * sizeof(int));
2506  memcpy(lb, eah->lbound, ndim * sizeof(int));
2507  dimschanged = false;
2508 
2509  /*
2510  * if number of dims is zero, i.e. an empty array, create an array with
2511  * nSubscripts dimensions, and set the lower bounds to the supplied
2512  * subscripts.
2513  */
2514  if (ndim == 0)
2515  {
2516  /*
2517  * Allocate adequate space for new dimension info. This is harmless
2518  * if we fail later.
2519  */
2520  Assert(nSubscripts > 0 && nSubscripts <= MAXDIM);
2521  eah->dims = (int *) MemoryContextAllocZero(eah->hdr.eoh_context,
2522  nSubscripts * sizeof(int));
2523  eah->lbound = (int *) MemoryContextAllocZero(eah->hdr.eoh_context,
2524  nSubscripts * sizeof(int));
2525 
2526  /* Update local copies of dimension info */
2527  ndim = nSubscripts;
2528  for (i = 0; i < nSubscripts; i++)
2529  {
2530  dim[i] = 0;
2531  lb[i] = indx[i];
2532  }
2533  dimschanged = true;
2534  }
2535  else if (ndim != nSubscripts)
2536  ereport(ERROR,
2537  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2538  errmsg("wrong number of array subscripts")));
2539 
2540  /*
2541  * Deconstruct array if we didn't already. (Someday maybe add a special
2542  * case path for fixed-length, no-nulls cases, where we can overwrite an
2543  * element in place without ever deconstructing. But today is not that
2544  * day.)
2545  */
2547 
2548  /*
2549  * Copy new element into array's context, if needed (we assume it's
2550  * already detoasted, so no junk should be created). If we fail further
2551  * down, this memory is leaked, but that's reasonably harmless.
2552  */
2553  if (!eah->typbyval && !isNull)
2554  {
2556 
2557  dataValue = datumCopy(dataValue, false, eah->typlen);
2558  MemoryContextSwitchTo(oldcxt);
2559  }
2560 
2561  dvalues = eah->dvalues;
2562  dnulls = eah->dnulls;
2563 
2564  newhasnulls = ((dnulls != NULL) || isNull);
2565  addedbefore = addedafter = 0;
2566 
2567  /*
2568  * Check subscripts (this logic matches original array_set_element)
2569  */
2570  if (ndim == 1)
2571  {
2572  if (indx[0] < lb[0])
2573&