PostgreSQL Source Code  git master
arrayfuncs.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <math.h>
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "nodes/nodeFuncs.h"
#include "nodes/supportnodes.h"
#include "optimizer/optimizer.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/selfuncs.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 *lbsv, 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_unnest_support (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 5053 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(), pg_stats_ext_mcvlist_items(), populate_array_element(), regexp_split_to_array(), SPI_sql_row_to_xmlelement(), text_to_array_internal(), transformRelOptions(), and tuple_data_split_internal().

5057 {
5058  MemoryContext oldcontext;
5059 
5060  if (astate == NULL)
5061  {
5062  /* First time through --- initialize */
5063  astate = initArrayResult(element_type, rcontext, true);
5064  }
5065  else
5066  {
5067  Assert(astate->element_type == element_type);
5068  }
5069 
5070  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5071 
5072  /* enlarge dvalues[]/dnulls[] if needed */
5073  if (astate->nelems >= astate->alen)
5074  {
5075  astate->alen *= 2;
5076  astate->dvalues = (Datum *)
5077  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5078  astate->dnulls = (bool *)
5079  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5080  }
5081 
5082  /*
5083  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5084  * it's varlena. (You might think that detoasting is not needed here
5085  * because construct_md_array can detoast the array elements later.
5086  * However, we must not let construct_md_array modify the ArrayBuildState
5087  * because that would mean array_agg_finalfn damages its input, which is
5088  * verboten. Also, this way frequently saves one copying step.)
5089  */
5090  if (!disnull && !astate->typbyval)
5091  {
5092  if (astate->typlen == -1)
5093  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5094  else
5095  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5096  }
5097 
5098  astate->dvalues[astate->nelems] = dvalue;
5099  astate->dnulls[astate->nelems] = disnull;
5100  astate->nelems++;
5101 
5102  MemoryContextSwitchTo(oldcontext);
5103 
5104  return astate;
5105 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:237
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5014
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum * dvalues
Definition: array.h:178
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:184
Oid element_type
Definition: array.h:182
bool * dnulls
Definition: array.h:179
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:130
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:732
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
MemoryContext mcontext
Definition: array.h:177
int16 typlen
Definition: array.h:183

◆ accumArrayResultAny()

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

Definition at line 5524 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5528 {
5529  if (astate == NULL)
5530  astate = initArrayResultAny(input_type, rcontext, true);
5531 
5532  if (astate->scalarstate)
5533  (void) accumArrayResult(astate->scalarstate,
5534  dvalue, disnull,
5535  input_type, rcontext);
5536  else
5537  (void) accumArrayResultArr(astate->arraystate,
5538  dvalue, disnull,
5539  input_type, rcontext);
5540 
5541  return astate;
5542 }
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5479
ArrayBuildState * scalarstate
Definition: array.h:217
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5247
ArrayBuildStateArr * arraystate
Definition: array.h:218
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5053

◆ accumArrayResultArr()

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

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

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

◆ array_bitmap_copy()

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

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

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

◆ array_cardinality()

Datum array_cardinality ( PG_FUNCTION_ARGS  )

Definition at line 1789 of file arrayfuncs.c.

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

1790 {
1792 
1794 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:262
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define PG_RETURN_INT32(x)
Definition: fmgr.h:344
#define AARR_DIMS(a)
Definition: array.h:326
#define AARR_NDIM(a)
Definition: array.h:316

◆ array_cmp()

static int array_cmp ( FunctionCallInfo  fcinfo)
static

Definition at line 3746 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_FREE_IF_COPY, AARR_LBOUND, AARR_NDIM, array_iter_next(), array_iter_setup(), ArrayGetNItems(), TypeCacheEntry::cmp_proc_finfo, DatumGetInt32, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_oid, format_type_be(), FunctionCallInvoke, i, InitFunctionCallInfoData, LOCAL_FCINFO, 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().

3747 {
3748  LOCAL_FCINFO(locfcinfo, 2);
3749  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY_P(0);
3750  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY_P(1);
3751  Oid collation = PG_GET_COLLATION();
3752  int ndims1 = AARR_NDIM(array1);
3753  int ndims2 = AARR_NDIM(array2);
3754  int *dims1 = AARR_DIMS(array1);
3755  int *dims2 = AARR_DIMS(array2);
3756  int nitems1 = ArrayGetNItems(ndims1, dims1);
3757  int nitems2 = ArrayGetNItems(ndims2, dims2);
3758  Oid element_type = AARR_ELEMTYPE(array1);
3759  int result = 0;
3760  TypeCacheEntry *typentry;
3761  int typlen;
3762  bool typbyval;
3763  char typalign;
3764  int min_nitems;
3765  array_iter it1;
3766  array_iter it2;
3767  int i;
3768 
3769  if (element_type != AARR_ELEMTYPE(array2))
3770  ereport(ERROR,
3771  (errcode(ERRCODE_DATATYPE_MISMATCH),
3772  errmsg("cannot compare arrays of different element types")));
3773 
3774  /*
3775  * We arrange to look up the comparison function only once per series of
3776  * calls, assuming the element type doesn't change underneath us. The
3777  * typcache is used so that we have no memory leakage when being used as
3778  * an index support function.
3779  */
3780  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3781  if (typentry == NULL ||
3782  typentry->type_id != element_type)
3783  {
3784  typentry = lookup_type_cache(element_type,
3786  if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
3787  ereport(ERROR,
3788  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3789  errmsg("could not identify a comparison function for type %s",
3790  format_type_be(element_type))));
3791  fcinfo->flinfo->fn_extra = (void *) typentry;
3792  }
3793  typlen = typentry->typlen;
3794  typbyval = typentry->typbyval;
3795  typalign = typentry->typalign;
3796 
3797  /*
3798  * apply the operator to each pair of array elements.
3799  */
3800  InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2,
3801  collation, NULL, NULL);
3802 
3803  /* Loop over source data */
3804  min_nitems = Min(nitems1, nitems2);
3805  array_iter_setup(&it1, array1);
3806  array_iter_setup(&it2, array2);
3807 
3808  for (i = 0; i < min_nitems; i++)
3809  {
3810  Datum elt1;
3811  Datum elt2;
3812  bool isnull1;
3813  bool isnull2;
3814  int32 cmpresult;
3815 
3816  /* Get elements, checking for NULL */
3817  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
3818  elt2 = array_iter_next(&it2, &isnull2, i, typlen, typbyval, typalign);
3819 
3820  /*
3821  * We consider two NULLs equal; NULL > not-NULL.
3822  */
3823  if (isnull1 && isnull2)
3824  continue;
3825  if (isnull1)
3826  {
3827  /* arg1 is greater than arg2 */
3828  result = 1;
3829  break;
3830  }
3831  if (isnull2)
3832  {
3833  /* arg1 is less than arg2 */
3834  result = -1;
3835  break;
3836  }
3837 
3838  /* Compare the pair of elements */
3839  locfcinfo->args[0].value = elt1;
3840  locfcinfo->args[0].isnull = false;
3841  locfcinfo->args[1].value = elt2;
3842  locfcinfo->args[1].isnull = false;
3843  locfcinfo->isnull = false;
3844  cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo));
3845 
3846  if (cmpresult == 0)
3847  continue; /* equal */
3848 
3849  if (cmpresult < 0)
3850  {
3851  /* arg1 is less than arg2 */
3852  result = -1;
3853  break;
3854  }
3855  else
3856  {
3857  /* arg1 is greater than arg2 */
3858  result = 1;
3859  break;
3860  }
3861  }
3862 
3863  /*
3864  * If arrays contain same data (up to end of shorter one), apply
3865  * additional rules to sort by dimensionality. The relative significance
3866  * of the different bits of information is historical; mainly we just care
3867  * that we don't say "equal" for arrays of different dimensionality.
3868  */
3869  if (result == 0)
3870  {
3871  if (nitems1 != nitems2)
3872  result = (nitems1 < nitems2) ? -1 : 1;
3873  else if (ndims1 != ndims2)
3874  result = (ndims1 < ndims2) ? -1 : 1;
3875  else
3876  {
3877  for (i = 0; i < ndims1; i++)
3878  {
3879  if (dims1[i] != dims2[i])
3880  {
3881  result = (dims1[i] < dims2[i]) ? -1 : 1;
3882  break;
3883  }
3884  }
3885  if (result == 0)
3886  {
3887  int *lbound1 = AARR_LBOUND(array1);
3888  int *lbound2 = AARR_LBOUND(array2);
3889 
3890  for (i = 0; i < ndims1; i++)
3891  {
3892  if (lbound1[i] != lbound2[i])
3893  {
3894  result = (lbound1[i] < lbound2[i]) ? -1 : 1;
3895  break;
3896  }
3897  }
3898  }
3899  }
3900  }
3901 
3902  /* Avoid leaking memory when handed toasted input. */
3903  AARR_FREE_IF_COPY(array1, 0);
3904  AARR_FREE_IF_COPY(array2, 1);
3905 
3906  return result;
3907 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:262
#define DatumGetInt32(X)
Definition: postgres.h:472
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:904
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
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:638
#define PG_GET_COLLATION()
Definition: fmgr.h:193
signed int int32
Definition: c.h:346
FmgrInfo cmp_proc_finfo
Definition: typcache.h:73
char typalign
Definition: pg_type.h:170
#define ERROR
Definition: elog.h:43
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:167
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
FmgrInfo * flinfo
Definition: fmgr.h:87
#define AARR_DIMS(a)
Definition: array.h:326
#define AARR_ELEMTYPE(a)
Definition: array.h:323
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
Oid fn_oid
Definition: fmgr.h:59
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define AARR_LBOUND(a)
Definition: array.h:329
#define AARR_NDIM(a)
Definition: array.h:316
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#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:784
int i
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:134

◆ array_contain_compare()

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

Definition at line 4102 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_NDIM, 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, FmgrInfo::fn_oid, format_type_be(), FunctionCallInvoke, i, InitFunctionCallInfoData, LOCAL_FCINFO, 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().

4104 {
4105  LOCAL_FCINFO(locfcinfo, 2);
4106  bool result = matchall;
4107  Oid element_type = AARR_ELEMTYPE(array1);
4108  TypeCacheEntry *typentry;
4109  int nelems1;
4110  Datum *values2;
4111  bool *nulls2;
4112  int nelems2;
4113  int typlen;
4114  bool typbyval;
4115  char typalign;
4116  int i;
4117  int j;
4118  array_iter it1;
4119 
4120  if (element_type != AARR_ELEMTYPE(array2))
4121  ereport(ERROR,
4122  (errcode(ERRCODE_DATATYPE_MISMATCH),
4123  errmsg("cannot compare arrays of different element types")));
4124 
4125  /*
4126  * We arrange to look up the equality function only once per series of
4127  * calls, assuming the element type doesn't change underneath us. The
4128  * typcache is used so that we have no memory leakage when being used as
4129  * an index support function.
4130  */
4131  typentry = (TypeCacheEntry *) *fn_extra;
4132  if (typentry == NULL ||
4133  typentry->type_id != element_type)
4134  {
4135  typentry = lookup_type_cache(element_type,
4137  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
4138  ereport(ERROR,
4139  (errcode(ERRCODE_UNDEFINED_FUNCTION),
4140  errmsg("could not identify an equality operator for type %s",
4141  format_type_be(element_type))));
4142  *fn_extra = (void *) typentry;
4143  }
4144  typlen = typentry->typlen;
4145  typbyval = typentry->typbyval;
4146  typalign = typentry->typalign;
4147 
4148  /*
4149  * Since we probably will need to scan array2 multiple times, it's
4150  * worthwhile to use deconstruct_array on it. We scan array1 the hard way
4151  * however, since we very likely won't need to look at all of it.
4152  */
4153  if (VARATT_IS_EXPANDED_HEADER(array2))
4154  {
4155  /* This should be safe even if input is read-only */
4156  deconstruct_expanded_array(&(array2->xpn));
4157  values2 = array2->xpn.dvalues;
4158  nulls2 = array2->xpn.dnulls;
4159  nelems2 = array2->xpn.nelems;
4160  }
4161  else
4162  deconstruct_array((ArrayType *) array2,
4163  element_type, typlen, typbyval, typalign,
4164  &values2, &nulls2, &nelems2);
4165 
4166  /*
4167  * Apply the comparison operator to each pair of array elements.
4168  */
4169  InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
4170  collation, NULL, NULL);
4171 
4172  /* Loop over source data */
4173  nelems1 = ArrayGetNItems(AARR_NDIM(array1), AARR_DIMS(array1));
4174  array_iter_setup(&it1, array1);
4175 
4176  for (i = 0; i < nelems1; i++)
4177  {
4178  Datum elt1;
4179  bool isnull1;
4180 
4181  /* Get element, checking for NULL */
4182  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
4183 
4184  /*
4185  * We assume that the comparison operator is strict, so a NULL can't
4186  * match anything. XXX this diverges from the "NULL=NULL" behavior of
4187  * array_eq, should we act like that?
4188  */
4189  if (isnull1)
4190  {
4191  if (matchall)
4192  {
4193  result = false;
4194  break;
4195  }
4196  continue;
4197  }
4198 
4199  for (j = 0; j < nelems2; j++)
4200  {
4201  Datum elt2 = values2[j];
4202  bool isnull2 = nulls2 ? nulls2[j] : false;
4203  bool oprresult;
4204 
4205  if (isnull2)
4206  continue; /* can't match */
4207 
4208  /*
4209  * Apply the operator to the element pair
4210  */
4211  locfcinfo->args[0].value = elt1;
4212  locfcinfo->args[0].isnull = false;
4213  locfcinfo->args[1].value = elt2;
4214  locfcinfo->args[1].isnull = false;
4215  locfcinfo->isnull = false;
4216  oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
4217  if (oprresult)
4218  break;
4219  }
4220 
4221  if (j < nelems2)
4222  {
4223  /* found a match for elt1 */
4224  if (!matchall)
4225  {
4226  result = true;
4227  break;
4228  }
4229  }
4230  else
4231  {
4232  /* no match for elt1 */
4233  if (matchall)
4234  {
4235  result = false;
4236  break;
4237  }
4238  }
4239  }
4240 
4241  return result;
4242 }
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:133
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
ExpandedArrayHeader xpn
Definition: array.h:168
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
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:638
char typalign
Definition: pg_type.h:170
#define ERROR
Definition: elog.h:43
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:167
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
#define DatumGetBool(X)
Definition: postgres.h:393
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
#define AARR_DIMS(a)
Definition: array.h:326
#define AARR_ELEMTYPE(a)
Definition: array.h:323
FmgrInfo eq_opr_finfo
Definition: typcache.h:72
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
Oid fn_oid
Definition: fmgr.h:59
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define AARR_NDIM(a)
Definition: array.h:316
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#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:3461
char typalign
Definition: typcache.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

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

3529 {
3530  int nelems;
3531  bits8 *bitmap;
3532  int bitmask;
3533 
3534  /* Easy answer if there's no null bitmap */
3535  if (!ARR_HASNULL(array))
3536  return false;
3537 
3538  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3539 
3540  bitmap = ARR_NULLBITMAP(array);
3541 
3542  /* check whole bytes of the bitmap byte-at-a-time */
3543  while (nelems >= 8)
3544  {
3545  if (*bitmap != 0xFF)
3546  return true;
3547  bitmap++;
3548  nelems -= 8;
3549  }
3550 
3551  /* check last partial byte */
3552  bitmask = 1;
3553  while (nelems > 0)
3554  {
3555  if ((*bitmap & bitmask) == 0)
3556  return true;
3557  bitmask <<= 1;
3558  nelems--;
3559  }
3560 
3561  return false;
3562 }
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_HASNULL(a)
Definition: array.h:279
uint8 bits8
Definition: c.h:365
#define ARR_NDIM(a)
Definition: array.h:278
#define ARR_NULLBITMAP(a)
Definition: array.h:288

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

References array_nelems_size().

Referenced by array_extract_slice(), and array_insert_slice().

4660 {
4661  int numbytes;
4662 
4663  numbytes = array_nelems_size(srcptr, offset, nullbitmap, nitems,
4664  typlen, typbyval, typalign);
4665  memcpy(destptr, srcptr, numbytes);
4666  return numbytes;
4667 }
char typalign
Definition: pg_type.h:170
static int array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4635

◆ array_create_iterator()

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

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

4319 {
4320  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4321 
4322  /*
4323  * Sanity-check inputs --- caller should have got this right already
4324  */
4325  Assert(PointerIsValid(arr));
4326  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4327  elog(ERROR, "invalid arguments to array_create_iterator");
4328 
4329  /*
4330  * Remember basic info about the array and its element type
4331  */
4332  iterator->arr = arr;
4333  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4334  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4335 
4336  if (mstate != NULL)
4337  {
4338  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4339 
4340  iterator->typlen = mstate->typlen;
4341  iterator->typbyval = mstate->typbyval;
4342  iterator->typalign = mstate->typalign;
4343  }
4344  else
4346  &iterator->typlen,
4347  &iterator->typbyval,
4348  &iterator->typalign);
4349 
4350  /*
4351  * Remember the slicing parameters.
4352  */
4353  iterator->slice_ndim = slice_ndim;
4354 
4355  if (slice_ndim > 0)
4356  {
4357  /*
4358  * Get pointers into the array's dims and lbound arrays to represent
4359  * the dims/lbound arrays of a slice. These are the same as the
4360  * rightmost N dimensions of the array.
4361  */
4362  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4363  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4364 
4365  /*
4366  * Compute number of elements in a slice.
4367  */
4368  iterator->slice_len = ArrayGetNItems(slice_ndim,
4369  iterator->slice_dims);
4370 
4371  /*
4372  * Create workspace for building sub-arrays.
4373  */
4374  iterator->slice_values = (Datum *)
4375  palloc(iterator->slice_len * sizeof(Datum));
4376  iterator->slice_nulls = (bool *)
4377  palloc(iterator->slice_len * sizeof(bool));
4378  }
4379 
4380  /*
4381  * Initialize our data pointer and linear element number. These will
4382  * advance through the array during array_iterate().
4383  */
4384  iterator->data_ptr = ARR_DATA_PTR(arr);
4385  iterator->current_item = 0;
4386 
4387  return iterator;
4388 }
bits8 * nullbitmap
Definition: arrayfuncs.c:71
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2049
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_LBOUND(a)
Definition: array.h:284
bool typbyval
Definition: array.h:228
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:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
int16 typlen
Definition: array.h:227
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:732
#define ARR_NDIM(a)
Definition: array.h:278
char typalign
Definition: array.h:229
void * palloc(Size size)
Definition: mcxt.c:924
#define elog(elevel,...)
Definition: elog.h:226
Oid element_type
Definition: array.h:226
#define PointerIsValid(pointer)
Definition: c.h:626
#define ARR_ELEMTYPE(a)
Definition: array.h:280
#define ARR_NULLBITMAP(a)
Definition: array.h:288
ArrayType * arr
Definition: arrayfuncs.c:70

◆ array_dims()

Datum array_dims ( PG_FUNCTION_ARGS  )

Definition at line 1667 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, PG_RETURN_TEXT_P, and sprintf.

1668 {
1670  char *p;
1671  int i;
1672  int *dimv,
1673  *lb;
1674 
1675  /*
1676  * 33 since we assume 15 digits per number + ':' +'[]'
1677  *
1678  * +1 for trailing null
1679  */
1680  char buf[MAXDIM * 33 + 1];
1681 
1682  /* Sanity check: does it look like an array at all? */
1683  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1684  PG_RETURN_NULL();
1685 
1686  dimv = AARR_DIMS(v);
1687  lb = AARR_LBOUND(v);
1688 
1689  p = buf;
1690  for (i = 0; i < AARR_NDIM(v); i++)
1691  {
1692  sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1);
1693  p += strlen(p);
1694  }
1695 
1697 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:262
#define MAXDIM
Definition: c.h:529
#define sprintf
Definition: port.h:194
static char * buf
Definition: pg_test_fsync.c:68
#define AARR_DIMS(a)
Definition: array.h:326
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
text * cstring_to_text(const char *s)
Definition: varlena.c:171
#define AARR_LBOUND(a)
Definition: array.h:329
#define AARR_NDIM(a)
Definition: array.h:316
int i
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ array_eq()

Datum array_eq ( PG_FUNCTION_ARGS  )

Definition at line 3575 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_FREE_IF_COPY, AARR_LBOUND, AARR_NDIM, 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, LOCAL_FCINFO, 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().

3576 {
3577  LOCAL_FCINFO(locfcinfo, 2);
3578  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY_P(0);
3579  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY_P(1);
3580  Oid collation = PG_GET_COLLATION();
3581  int ndims1 = AARR_NDIM(array1);
3582  int ndims2 = AARR_NDIM(array2);
3583  int *dims1 = AARR_DIMS(array1);
3584  int *dims2 = AARR_DIMS(array2);
3585  int *lbs1 = AARR_LBOUND(array1);
3586  int *lbs2 = AARR_LBOUND(array2);
3587  Oid element_type = AARR_ELEMTYPE(array1);
3588  bool result = true;
3589  int nitems;
3590  TypeCacheEntry *typentry;
3591  int typlen;
3592  bool typbyval;
3593  char typalign;
3594  array_iter it1;
3595  array_iter it2;
3596  int i;
3597 
3598  if (element_type != AARR_ELEMTYPE(array2))
3599  ereport(ERROR,
3600  (errcode(ERRCODE_DATATYPE_MISMATCH),
3601  errmsg("cannot compare arrays of different element types")));
3602 
3603  /* fast path if the arrays do not have the same dimensionality */
3604  if (ndims1 != ndims2 ||
3605  memcmp(dims1, dims2, ndims1 * sizeof(int)) != 0 ||
3606  memcmp(lbs1, lbs2, ndims1 * sizeof(int)) != 0)
3607  result = false;
3608  else
3609  {
3610  /*
3611  * We arrange to look up the equality function only once per series of
3612  * calls, assuming the element type doesn't change underneath us. The
3613  * typcache is used so that we have no memory leakage when being used
3614  * as an index support function.
3615  */
3616  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3617  if (typentry == NULL ||
3618  typentry->type_id != element_type)
3619  {
3620  typentry = lookup_type_cache(element_type,
3622  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
3623  ereport(ERROR,
3624  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3625  errmsg("could not identify an equality operator for type %s",
3626  format_type_be(element_type))));
3627  fcinfo->flinfo->fn_extra = (void *) typentry;
3628  }
3629  typlen = typentry->typlen;
3630  typbyval = typentry->typbyval;
3631  typalign = typentry->typalign;
3632 
3633  /*
3634  * apply the operator to each pair of array elements.
3635  */
3636  InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
3637  collation, NULL, NULL);
3638 
3639  /* Loop over source data */
3640  nitems = ArrayGetNItems(ndims1, dims1);
3641  array_iter_setup(&it1, array1);
3642  array_iter_setup(&it2, array2);
3643 
3644  for (i = 0; i < nitems; i++)
3645  {
3646  Datum elt1;
3647  Datum elt2;
3648  bool isnull1;
3649  bool isnull2;
3650  bool oprresult;
3651 
3652  /* Get elements, checking for NULL */
3653  elt1 = array_iter_next(&it1, &isnull1, i,
3654  typlen, typbyval, typalign);
3655  elt2 = array_iter_next(&it2, &isnull2, i,
3656  typlen, typbyval, typalign);
3657 
3658  /*
3659  * We consider two NULLs equal; NULL and not-NULL are unequal.
3660  */
3661  if (isnull1 && isnull2)
3662  continue;
3663  if (isnull1 || isnull2)
3664  {
3665  result = false;
3666  break;
3667  }
3668 
3669  /*
3670  * Apply the operator to the element pair
3671  */
3672  locfcinfo->args[0].value = elt1;
3673  locfcinfo->args[0].isnull = false;
3674  locfcinfo->args[1].value = elt2;
3675  locfcinfo->args[1].isnull = false;
3676  locfcinfo->isnull = false;
3677  oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
3678  if (!oprresult)
3679  {
3680  result = false;
3681  break;
3682  }
3683  }
3684  }
3685 
3686  /* Avoid leaking memory when handed toasted input. */
3687  AARR_FREE_IF_COPY(array1, 0);
3688  AARR_FREE_IF_COPY(array2, 1);
3689 
3690  PG_RETURN_BOOL(result);
3691 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:262
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:133
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
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:638
#define PG_GET_COLLATION()
Definition: fmgr.h:193
char typalign
Definition: pg_type.h:170
#define ERROR
Definition: elog.h:43
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:167
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
#define DatumGetBool(X)
Definition: postgres.h:393
#define ereport(elevel, rest)
Definition: elog.h:141
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
uintptr_t Datum
Definition: postgres.h:367
#define AARR_DIMS(a)
Definition: array.h:326
#define AARR_ELEMTYPE(a)
Definition: array.h:323
FmgrInfo eq_opr_finfo
Definition: typcache.h:72
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
Oid fn_oid
Definition: fmgr.h:59
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define AARR_LBOUND(a)
Definition: array.h:329
#define AARR_NDIM(a)
Definition: array.h:316
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#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:784
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 4818 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().

4829 {
4830  char *destdataptr = ARR_DATA_PTR(newarray);
4831  bits8 *destnullsptr = ARR_NULLBITMAP(newarray);
4832  char *srcdataptr;
4833  int src_offset,
4834  dest_offset,
4835  prod[MAXDIM],
4836  span[MAXDIM],
4837  dist[MAXDIM],
4838  indx[MAXDIM];
4839  int i,
4840  j,
4841  inc;
4842 
4843  src_offset = ArrayGetOffset(ndim, dim, lb, st);
4844  srcdataptr = array_seek(arraydataptr, 0, arraynullsptr, src_offset,
4845  typlen, typbyval, typalign);
4846  mda_get_prod(ndim, dim, prod);
4847  mda_get_range(ndim, span, st, endp);
4848  mda_get_offset_values(ndim, dist, prod, span);
4849  for (i = 0; i < ndim; i++)
4850  indx[i] = 0;
4851  dest_offset = 0;
4852  j = ndim - 1;
4853  do
4854  {
4855  if (dist[j])
4856  {
4857  /* skip unwanted elements */
4858  srcdataptr = array_seek(srcdataptr, src_offset, arraynullsptr,
4859  dist[j],
4860  typlen, typbyval, typalign);
4861  src_offset += dist[j];
4862  }
4863  inc = array_copy(destdataptr, 1,
4864  srcdataptr, src_offset, arraynullsptr,
4865  typlen, typbyval, typalign);
4866  if (destnullsptr)
4867  array_bitmap_copy(destnullsptr, dest_offset,
4868  arraynullsptr, src_offset,
4869  1);
4870  destdataptr += inc;
4871  srcdataptr += inc;
4872  src_offset++;
4873  dest_offset++;
4874  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4875 }
#define MAXDIM
Definition: c.h:529
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:4687
static int array_copy(char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4657
char typalign
Definition: pg_type.h:170
#define ARR_DATA_PTR(a)
Definition: array.h:310
void mda_get_offset_values(int n, int *dist, const int *prod, const int *span)
Definition: arrayutils.c:150
uint8 bits8
Definition: c.h:365
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:4587
int mda_next_tuple(int n, int *curr, const int *span)
Definition: arrayutils.c:175
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:288

◆ array_fill()

Datum array_fill ( PG_FUNCTION_ARGS  )

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

5729 {
5730  ArrayType *dims;
5731  ArrayType *result;
5732  Oid elmtype;
5733  Datum value;
5734  bool isnull;
5735 
5736  if (PG_ARGISNULL(1))
5737  ereport(ERROR,
5738  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5739  errmsg("dimension array or low bound array cannot be null")));
5740 
5741  dims = PG_GETARG_ARRAYTYPE_P(1);
5742 
5743  if (!PG_ARGISNULL(0))
5744  {
5745  value = PG_GETARG_DATUM(0);
5746  isnull = false;
5747  }
5748  else
5749  {
5750  value = 0;
5751  isnull = true;
5752  }
5753 
5754  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5755  if (!OidIsValid(elmtype))
5756  elog(ERROR, "could not determine data type of input");
5757 
5758  result = array_fill_internal(dims, NULL, value, isnull, elmtype, fcinfo);
5759  PG_RETURN_ARRAYTYPE_P(result);
5760 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5780
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
static struct @144 value
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1817
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226

◆ array_fill_internal()

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

Definition at line 5780 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, FunctionCallInfoBaseData::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().

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

◆ array_fill_with_lower_bounds()

Datum array_fill_with_lower_bounds ( PG_FUNCTION_ARGS  )

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

5688 {
5689  ArrayType *dims;
5690  ArrayType *lbs;
5691  ArrayType *result;
5692  Oid elmtype;
5693  Datum value;
5694  bool isnull;
5695 
5696  if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
5697  ereport(ERROR,
5698  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5699  errmsg("dimension array or low bound array cannot be null")));
5700 
5701  dims = PG_GETARG_ARRAYTYPE_P(1);
5702  lbs = PG_GETARG_ARRAYTYPE_P(2);
5703 
5704  if (!PG_ARGISNULL(0))
5705  {
5706  value = PG_GETARG_DATUM(0);
5707  isnull = false;
5708  }
5709  else
5710  {
5711  value = 0;
5712  isnull = true;
5713  }
5714 
5715  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5716  if (!OidIsValid(elmtype))
5717  elog(ERROR, "could not determine data type of input");
5718 
5719  result = array_fill_internal(dims, lbs, value, isnull, elmtype, fcinfo);
5720  PG_RETURN_ARRAYTYPE_P(result);
5721 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5780
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
static struct @144 value
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1817
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226

◆ array_free_iterator()

void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4480 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4481 {
4482  if (iterator->slice_ndim > 0)
4483  {
4484  pfree(iterator->slice_values);
4485  pfree(iterator->slice_nulls);
4486  }
4487  pfree(iterator);
4488 }
bool * slice_nulls
Definition: arrayfuncs.c:83
void pfree(void *pointer)
Definition: mcxt.c:1031
Datum * slice_values
Definition: arrayfuncs.c:82

◆ array_ge()

Datum array_ge ( PG_FUNCTION_ARGS  )

Definition at line 3728 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3729 {
3730  PG_RETURN_BOOL(array_cmp(fcinfo) >= 0);
3731 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3746
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349

◆ 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 1819 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(), ATExecAlterColumnType(), ExecEvalSubscriptingRefFetch(), ExecEvalSubscriptingRefOld(), and RelationBuildTupleDesc().

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

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

1925 {
1926  ExpandedArrayHeader *eah;
1927  int i,
1928  ndim,
1929  *dim,
1930  *lb,
1931  offset;
1932  Datum *dvalues;
1933  bool *dnulls;
1934 
1935  eah = (ExpandedArrayHeader *) DatumGetEOHP(arraydatum);
1936  Assert(eah->ea_magic == EA_MAGIC);
1937 
1938  /* sanity-check caller's info against object */
1939  Assert(arraytyplen == -1);
1940  Assert(elmlen == eah->typlen);
1941  Assert(elmbyval == eah->typbyval);
1942  Assert(elmalign == eah->typalign);
1943 
1944  ndim = eah->ndims;
1945  dim = eah->dims;
1946  lb = eah->lbound;
1947 
1948  /*
1949  * Return NULL for invalid subscript
1950  */
1951  if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
1952  {
1953  *isNull = true;
1954  return (Datum) 0;
1955  }
1956  for (i = 0; i < ndim; i++)
1957  {
1958  if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
1959  {
1960  *isNull = true;
1961  return (Datum) 0;
1962  }
1963  }
1964 
1965  /*
1966  * Calculate the element number
1967  */
1968  offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
1969 
1970  /*
1971  * Deconstruct array if we didn't already. Note that we apply this even
1972  * if the input is nominally read-only: it should be safe enough.
1973  */
1975 
1976  dvalues = eah->dvalues;
1977  dnulls = eah->dnulls;
1978 
1979  /*
1980  * Check for NULL array element
1981  */
1982  if (dnulls && dnulls[offset])
1983  {
1984  *isNull = true;
1985  return (Datum) 0;
1986  }
1987 
1988  /*
1989  * OK, get the element. It's OK to return a pass-by-ref value as a
1990  * pointer into the expanded array, for the same reason that regular
1991  * array_get_element can return a pointer into flat arrays: the value is
1992  * assumed not to change for as long as the Datum reference can exist.
1993  */
1994  *isNull = false;
1995  return dvalues[offset];
1996 }
void deconstruct_expanded_array(ExpandedArrayHeader *eah)
#define MAXDIM
Definition: c.h:529
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:367
#define Assert(condition)
Definition: c.h:732
int i

◆ array_get_isnull()

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

Definition at line 4502 of file arrayfuncs.c.

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

4503 {
4504  if (nullbitmap == NULL)
4505  return false; /* assume not null */
4506  if (nullbitmap[offset / 8] & (1 << (offset % 8)))
4507  return false; /* not null */
4508  return true;
4509 }

◆ 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 2028 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(), generate_unaccent_rules::bytes(), 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 ExecEvalSubscriptingRefFetch(), and ExecEvalSubscriptingRefOld().

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

◆ array_gt()

Datum array_gt ( 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:3746
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349

◆ 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, printf, 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:264
static bool array_isspace(char ch)
Definition: arrayfuncs.c:432
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define MAXDIM
Definition: c.h:529
char * pstrdup(const char *in)
Definition: mcxt.c:1161
int32 dataoffset
Definition: array.h:84
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:570
#define printf(...)
Definition: port.h:198
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3410
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:300
signed int int32
Definition: c.h:346
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:284
bool typbyval
Definition: array.h:228
void pfree(void *pointer)
Definition: mcxt.c:1031
char typalign
Definition: pg_type.h:170
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:282
int16 typlen
Definition: array.h:227
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
char typdelim
Definition: array.h:230
int errdetail(const char *fmt,...)
Definition: elog.c:860
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
#define ereport(elevel, rest)
Definition: elog.h:141
#define ASSGN
Definition: arrayfuncs.c:45
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
Oid typioparam
Definition: array.h:231
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:232
char typalign
Definition: array.h:229
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
FmgrInfo proc
Definition: array.h:233
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
int i
Oid element_type
Definition: array.h:226
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:272
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
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:2103

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

4902 {
4903  char *destPtr = ARR_DATA_PTR(destArray);
4904  char *origPtr = ARR_DATA_PTR(origArray);
4905  char *srcPtr = ARR_DATA_PTR(srcArray);
4906  bits8 *destBitmap = ARR_NULLBITMAP(destArray);
4907  bits8 *origBitmap = ARR_NULLBITMAP(origArray);
4908  bits8 *srcBitmap = ARR_NULLBITMAP(srcArray);
4909  int orignitems = ArrayGetNItems(ARR_NDIM(origArray),
4910  ARR_DIMS(origArray));
4911  int dest_offset,
4912  orig_offset,
4913  src_offset,
4914  prod[MAXDIM],
4915  span[MAXDIM],
4916  dist[MAXDIM],
4917  indx[MAXDIM];
4918  int i,
4919  j,
4920  inc;
4921 
4922  dest_offset = ArrayGetOffset(ndim, dim, lb, st);
4923  /* copy items before the slice start */
4924  inc = array_copy(destPtr, dest_offset,
4925  origPtr, 0, origBitmap,
4926  typlen, typbyval, typalign);
4927  destPtr += inc;
4928  origPtr += inc;
4929  if (destBitmap)
4930  array_bitmap_copy(destBitmap, 0, origBitmap, 0, dest_offset);
4931  orig_offset = dest_offset;
4932  mda_get_prod(ndim, dim, prod);
4933  mda_get_range(ndim, span, st, endp);
4934  mda_get_offset_values(ndim, dist, prod, span);
4935  for (i = 0; i < ndim; i++)
4936  indx[i] = 0;
4937  src_offset = 0;
4938  j = ndim - 1;
4939  do
4940  {
4941  /* Copy/advance over elements between here and next part of slice */
4942  if (dist[j])
4943  {
4944  inc = array_copy(destPtr, dist[j],
4945  origPtr, orig_offset, origBitmap,
4946  typlen, typbyval, typalign);
4947  destPtr += inc;
4948  origPtr += inc;
4949  if (destBitmap)
4950  array_bitmap_copy(destBitmap, dest_offset,
4951  origBitmap, orig_offset,
4952  dist[j]);
4953  dest_offset += dist[j];
4954  orig_offset += dist[j];
4955  }
4956  /* Copy new element at this slice position */
4957  inc = array_copy(destPtr, 1,
4958  srcPtr, src_offset, srcBitmap,
4959  typlen, typbyval, typalign);
4960  if (destBitmap)
4961  array_bitmap_copy(destBitmap, dest_offset,
4962  srcBitmap, src_offset,
4963  1);
4964  destPtr += inc;
4965  srcPtr += inc;
4966  dest_offset++;
4967  src_offset++;
4968  /* Advance over old element at this slice position */
4969  origPtr = array_seek(origPtr, orig_offset, origBitmap, 1,
4970  typlen, typbyval, typalign);
4971  orig_offset++;
4972  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4973 
4974  /* don't miss any data at the end */
4975  array_copy(destPtr, orignitems - orig_offset,
4976  origPtr, orig_offset, origBitmap,
4977  typlen, typbyval, typalign);
4978  if (destBitmap)
4979  array_bitmap_copy(destBitmap, dest_offset,
4980  origBitmap, orig_offset,
4981  orignitems - orig_offset);
4982 }
#define MAXDIM
Definition: c.h:529
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:4687
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:4657
char typalign
Definition: pg_type.h:170
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
void mda_get_offset_values(int n, int *dist, const int *prod, const int *span)
Definition: arrayutils.c:150
uint8 bits8
Definition: c.h:365
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:4587
#define ARR_NDIM(a)
Definition: array.h:278
int mda_next_tuple(int n, int *curr, const int *span)
Definition: arrayutils.c:175
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:288

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

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

◆ array_larger()

Datum array_larger ( PG_FUNCTION_ARGS  )

Definition at line 5582 of file arrayfuncs.c.

References array_cmp(), PG_GETARG_DATUM, and PG_RETURN_DATUM.

5583 {
5584  if (array_cmp(fcinfo) > 0)
5586  else
5588 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3746
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343

◆ array_le()

Datum array_le ( PG_FUNCTION_ARGS  )

Definition at line 3722 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3723 {
3724  PG_RETURN_BOOL(array_cmp(fcinfo) <= 0);
3725 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3746
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349

◆ array_length()

Datum array_length ( PG_FUNCTION_ARGS  )

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

1763 {
1765  int reqdim = PG_GETARG_INT32(1);
1766  int *dimv;
1767  int result;
1768 
1769  /* Sanity check: does it look like an array at all? */
1770  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1771  PG_RETURN_NULL();
1772 
1773  /* Sanity check: was the requested dim valid */
1774  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1775  PG_RETURN_NULL();
1776 
1777  dimv = AARR_DIMS(v);
1778 
1779  result = dimv[reqdim - 1];
1780 
1781  PG_RETURN_INT32(result);
1782 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:262
#define MAXDIM
Definition: c.h:529
#define PG_RETURN_INT32(x)
Definition: fmgr.h:344
#define AARR_DIMS(a)
Definition: array.h:326
#define AARR_NDIM(a)
Definition: array.h:316
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ array_lower()

Datum array_lower ( PG_FUNCTION_ARGS  )

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

1706 {
1708  int reqdim = PG_GETARG_INT32(1);
1709  int *lb;
1710  int result;
1711 
1712  /* Sanity check: does it look like an array at all? */
1713  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1714  PG_RETURN_NULL();
1715 
1716  /* Sanity check: was the requested dim valid */
1717  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1718  PG_RETURN_NULL();
1719 
1720  lb = AARR_LBOUND(v);
1721  result = lb[reqdim - 1];
1722 
1723  PG_RETURN_INT32(result);
1724 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:262
#define MAXDIM
Definition: c.h:529
#define PG_RETURN_INT32(x)
Definition: fmgr.h:344
#define AARR_LBOUND(a)
Definition: array.h:329
#define AARR_NDIM(a)
Definition: array.h:316
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ array_lt()

Datum array_lt ( 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:3746
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349

◆ array_map()

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

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

3134 {
3135  AnyArrayType *v = DatumGetAnyArrayP(arrayd);
3136  ArrayType *result;
3137  Datum *values;
3138  bool *nulls;
3139  int *dim;
3140  int ndim;
3141  int nitems;
3142  int i;
3143  int32 nbytes = 0;
3144  int32 dataoffset;
3145  bool hasnulls;
3146  Oid inpType;
3147  int inp_typlen;
3148  bool inp_typbyval;
3149  char inp_typalign;
3150  int typlen;
3151  bool typbyval;
3152  char typalign;
3153  array_iter iter;
3154  ArrayMetaState *inp_extra;
3155  ArrayMetaState *ret_extra;
3156  Datum *transform_source = exprstate->innermost_caseval;
3157  bool *transform_source_isnull = exprstate->innermost_casenull;
3158 
3159  inpType = AARR_ELEMTYPE(v);
3160  ndim = AARR_NDIM(v);
3161  dim = AARR_DIMS(v);
3162  nitems = ArrayGetNItems(ndim, dim);
3163 
3164  /* Check for empty array */
3165  if (nitems <= 0)
3166  {
3167  /* Return empty array */
3168  return PointerGetDatum(construct_empty_array(retType));
3169  }
3170 
3171  /*
3172  * We arrange to look up info about input and return element types only
3173  * once per series of calls, assuming the element type doesn't change
3174  * underneath us.
3175  */
3176  inp_extra = &amstate->inp_extra;
3177  ret_extra = &amstate->ret_extra;
3178 
3179  if (inp_extra->element_type != inpType)
3180  {
3181  get_typlenbyvalalign(inpType,
3182  &inp_extra->typlen,
3183  &inp_extra->typbyval,
3184  &inp_extra->typalign);
3185  inp_extra->element_type = inpType;
3186  }
3187  inp_typlen = inp_extra->typlen;
3188  inp_typbyval = inp_extra->typbyval;
3189  inp_typalign = inp_extra->typalign;
3190 
3191  if (ret_extra->element_type != retType)
3192  {
3193  get_typlenbyvalalign(retType,
3194  &ret_extra->typlen,
3195  &ret_extra->typbyval,
3196  &ret_extra->typalign);
3197  ret_extra->element_type = retType;
3198  }
3199  typlen = ret_extra->typlen;
3200  typbyval = ret_extra->typbyval;
3201  typalign = ret_extra->typalign;
3202 
3203  /* Allocate temporary arrays for new values */
3204  values = (Datum *) palloc(nitems * sizeof(Datum));
3205  nulls = (bool *) palloc(nitems * sizeof(bool));
3206 
3207  /* Loop over source data */
3208  array_iter_setup(&iter, v);
3209  hasnulls = false;
3210 
3211  for (i = 0; i < nitems; i++)
3212  {
3213  /* Get source element, checking for NULL */
3214  *transform_source =
3215  array_iter_next(&iter, transform_source_isnull, i,
3216  inp_typlen, inp_typbyval, inp_typalign);
3217 
3218  /* Apply the given expression to source element */
3219  values[i] = ExecEvalExpr(exprstate, econtext, &nulls[i]);
3220 
3221  if (nulls[i])
3222  hasnulls = true;
3223  else
3224  {
3225  /* Ensure data is not toasted */
3226  if (typlen == -1)
3227  values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
3228  /* Update total result size */
3229  nbytes = att_addlength_datum(nbytes, typlen, values[i]);
3230  nbytes = att_align_nominal(nbytes, typalign);
3231  /* check for overflow of total request */
3232  if (!AllocSizeIsValid(nbytes))
3233  ereport(ERROR,
3234  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3235  errmsg("array size exceeds the maximum allowed (%d)",
3236  (int) MaxAllocSize)));
3237  }
3238  }
3239 
3240  /* Allocate and fill the result array */
3241  if (hasnulls)
3242  {
3243  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3244  nbytes += dataoffset;
3245  }
3246  else
3247  {
3248  dataoffset = 0; /* marker for no null bitmap */
3249  nbytes += ARR_OVERHEAD_NONULLS(ndim);
3250  }
3251  result = (ArrayType *) palloc0(nbytes);
3252  SET_VARSIZE(result, nbytes);
3253  result->ndim = ndim;
3254  result->dataoffset = dataoffset;
3255  result->elemtype = retType;
3256  memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
3257  memcpy(ARR_LBOUND(result), AARR_LBOUND(v), ndim * sizeof(int));
3258 
3259  CopyArrayEls(result,
3260  values, nulls, nitems,
3261  typlen, typbyval, typalign,
3262  false);
3263 
3264  /*
3265  * Note: do not risk trying to pfree the results of the called expression
3266  */
3267  pfree(values);
3268  pfree(nulls);
3269 
3270  return PointerGetDatum(result);
3271 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:146
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:2049
#define PointerGetDatum(X)
Definition: postgres.h:556
bool * innermost_casenull
Definition: execnodes.h:112
int32 dataoffset
Definition: array.h:84
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:570
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3410
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:300
signed int int32
Definition: c.h:346
AnyArrayType * DatumGetAnyArrayP(Datum d)
#define ARR_LBOUND(a)
Definition: array.h:284
bool typbyval
Definition: array.h:228
void pfree(void *pointer)
Definition: mcxt.c:1031
char typalign
Definition: pg_type.h:170
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:282
ArrayMetaState inp_extra
Definition: array.h:241
int16 typlen
Definition: array.h:227
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:285
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
Datum * innermost_caseval
Definition: execnodes.h:111
#define ereport(elevel, rest)
Definition: elog.h:141
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
#define AARR_DIMS(a)
Definition: array.h:326
#define AARR_ELEMTYPE(a)
Definition: array.h:323
#define AARR_LBOUND(a)
Definition: array.h:329
#define AARR_NDIM(a)
Definition: array.h:316
ArrayMetaState ret_extra
Definition: array.h:242
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:229
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:162
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
Oid element_type
Definition: array.h:226
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:235
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
int ndim
Definition: array.h:83

◆ array_ndims()

Datum array_ndims ( PG_FUNCTION_ARGS  )

Definition at line 1651 of file arrayfuncs.c.

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

1652 {
1654 
1655  /* Sanity check: does it look like an array at all? */
1656  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1657  PG_RETURN_NULL();
1658 
1660 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:262
#define MAXDIM
Definition: c.h:529
#define PG_RETURN_INT32(x)
Definition: fmgr.h:344
#define AARR_NDIM(a)
Definition: array.h:316
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ array_ne()

Datum array_ne ( PG_FUNCTION_ARGS  )

Definition at line 3704 of file arrayfuncs.c.

References array_eq(), DatumGetBool, and PG_RETURN_BOOL.

3705 {
3707 }
#define DatumGetBool(X)
Definition: postgres.h:393
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
Datum array_eq(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:3575

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

References array_seek().

Referenced by array_copy(), and array_set_slice().

4637 {
4638  return array_seek(ptr, offset, nullbitmap, nitems,
4639  typlen, typbyval, typalign) - ptr;
4640 }
char typalign
Definition: pg_type.h:170
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4587

◆ 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(), Assert, 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(), sprintf, 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  size_t overall_length;
1034  int nitems,
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 = 0;
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 (or other typdelim delimiter) */
1162  overall_length += 1;
1163  }
1164 
1165  /*
1166  * The very last array element doesn't have a typdelim delimiter after it,
1167  * but that's OK; that space is needed for the trailing '\0'.
1168  *
1169  * Now count total number of curly brace pairs in output string.
1170  */
1171  for (i = j = 0, k = 1; i < ndim; i++)
1172  {
1173  j += k, k *= dims[i];
1174  }
1175  overall_length += 2 * j;
1176 
1177  /* Format explicit dimensions if required */
1178  dims_str[0] = '\0';
1179  if (needdims)
1180  {
1181  char *ptr = dims_str;
1182 
1183  for (i = 0; i < ndim; i++)
1184  {
1185  sprintf(ptr, "[%d:%d]", lb[i], lb[i] + dims[i] - 1);
1186  ptr += strlen(ptr);
1187  }
1188  *ptr++ = *ASSGN;
1189  *ptr = '\0';
1190  overall_length += ptr - dims_str;
1191  }
1192 
1193  /* Now construct the output string */
1194  retval = (char *) palloc(overall_length);
1195  p = retval;
1196 
1197 #define APPENDSTR(str) (strcpy(p, (str)), p += strlen(p))
1198 #define APPENDCHAR(ch) (*p++ = (ch), *p = '\0')
1199 
1200  if (needdims)
1201  APPENDSTR(dims_str);
1202  APPENDCHAR('{');
1203  for (i = 0; i < ndim; i++)
1204  indx[i] = 0;
1205  j = 0;
1206  k = 0;
1207  do
1208  {
1209  for (i = j; i < ndim - 1; i++)
1210  APPENDCHAR('{');
1211 
1212  if (needquotes[k])
1213  {
1214  APPENDCHAR('"');
1215  for (tmp = values[k]; *tmp; tmp++)
1216  {
1217  char ch = *tmp;
1218 
1219  if (ch == '"' || ch == '\\')
1220  *p++ = '\\';
1221  *p++ = ch;
1222  }
1223  *p = '\0';
1224  APPENDCHAR('"');
1225  }
1226  else
1227  APPENDSTR(values[k]);
1228  pfree(values[k++]);
1229 
1230  for (i = ndim - 1; i >= 0; i--)
1231  {
1232  if (++(indx[i]) < dims[i])
1233  {
1234  APPENDCHAR(typdelim);
1235  break;
1236  }
1237  else
1238  {
1239  indx[i] = 0;
1240  APPENDCHAR('}');
1241  }
1242  }
1243  j = i;
1244  } while (j != -1);
1245 
1246 #undef APPENDSTR
1247 #undef APPENDCHAR
1248 
1249  /* Assert that we calculated the string length accurately */
1250  Assert(overall_length == (p - retval + 1));
1251 
1252  pfree(values);
1253  pfree(needquotes);
1254 
1255  PG_RETURN_CSTRING(retval);
1256 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:262
static bool array_isspace(char ch)
Definition: arrayfuncs.c:432
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define MAXDIM
Definition: c.h:529
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:1161
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:1575
bool typbyval
Definition: array.h:228
#define sprintf
Definition: port.h:194
void pfree(void *pointer)
Definition: mcxt.c:1031
char typalign
Definition: pg_type.h:170
#define APPENDCHAR(ch)
#define APPENDSTR(str)
int16 typlen
Definition: array.h:227
char typdelim
Definition: array.h:230
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:134
#define ASSGN
Definition: arrayfuncs.c:45
uintptr_t Datum
Definition: postgres.h:367
#define AARR_DIMS(a)
Definition: array.h:326
#define AARR_ELEMTYPE(a)
Definition: array.h:323
#define AARR_LBOUND(a)
Definition: array.h:329
#define Assert(condition)
Definition: c.h:732
Oid typioparam
Definition: array.h:231
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:352
#define AARR_NDIM(a)
Definition: array.h:316
Oid typiofunc
Definition: array.h:232
char typalign
Definition: array.h:229
static Datum values[MAXATTR]
Definition: bootstrap.c:167
void * palloc(Size size)
Definition: mcxt.c:924
FmgrInfo proc
Definition: array.h:233
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
int i
Oid element_type
Definition: array.h:226
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:2103

◆ array_recv()

Datum array_recv ( PG_FUNCTION_ARGS  )

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

1268 {
1270  Oid spec_element_type = PG_GETARG_OID(1); /* type of an array
1271  * element */
1272  int32 typmod = PG_GETARG_INT32(2); /* typmod for array elements */
1273  Oid element_type;
1274  int typlen;
1275  bool typbyval;
1276  char typalign;
1277  Oid typioparam;
1278  int i,
1279  nitems;
1280  Datum *dataPtr;
1281  bool *nullsPtr;
1282  bool hasnulls;
1283  int32 nbytes;
1284  int32 dataoffset;
1285  ArrayType *retval;
1286  int ndim,
1287  flags,
1288  dim[MAXDIM],
1289  lBound[MAXDIM];
1290  ArrayMetaState *my_extra;
1291 
1292  /* Get the array header information */
1293  ndim = pq_getmsgint(buf, 4);
1294  if (ndim < 0) /* we do allow zero-dimension arrays */
1295  ereport(ERROR,
1296  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1297  errmsg("invalid number of dimensions: %d", ndim)));
1298  if (ndim > MAXDIM)
1299  ereport(ERROR,
1300  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1301  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
1302  ndim, MAXDIM)));
1303 
1304  flags = pq_getmsgint(buf, 4);
1305  if (flags != 0 && flags != 1)
1306  ereport(ERROR,
1307  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1308  errmsg("invalid array flags")));
1309 
1310  element_type = pq_getmsgint(buf, sizeof(Oid));
1311  if (element_type != spec_element_type)
1312  {
1313  /* XXX Can we allow taking the input element type in any cases? */
1314  ereport(ERROR,
1315  (errcode(ERRCODE_DATATYPE_MISMATCH),
1316  errmsg("wrong element type")));
1317  }
1318 
1319  for (i = 0; i < ndim; i++)
1320  {
1321  dim[i] = pq_getmsgint(buf, 4);
1322  lBound[i] = pq_getmsgint(buf, 4);
1323 
1324  /*
1325  * Check overflow of upper bound. (ArrayGetNItems() below checks that
1326  * dim[i] >= 0)
1327  */
1328  if (dim[i] != 0)
1329  {
1330  int ub = lBound[i] + dim[i] - 1;
1331 
1332  if (lBound[i] > ub)
1333  ereport(ERROR,
1334  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1335  errmsg("integer out of range")));
1336  }
1337  }
1338 
1339  /* This checks for overflow of array dimensions */
1340  nitems = ArrayGetNItems(ndim, dim);
1341 
1342  /*
1343  * We arrange to look up info about element type, including its receive
1344  * conversion proc, only once per series of calls, assuming the element
1345  * type doesn't change underneath us.
1346  */
1347  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1348  if (my_extra == NULL)
1349  {
1350  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1351  sizeof(ArrayMetaState));
1352  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1353  my_extra->element_type = ~element_type;
1354  }
1355 
1356  if (my_extra->element_type != element_type)
1357  {
1358  /* Get info about element type, including its receive proc */
1359  get_type_io_data(element_type, IOFunc_receive,
1360  &my_extra->typlen, &my_extra->typbyval,
1361  &my_extra->typalign, &my_extra->typdelim,
1362  &my_extra->typioparam, &my_extra->typiofunc);
1363  if (!OidIsValid(my_extra->typiofunc))
1364  ereport(ERROR,
1365  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1366  errmsg("no binary input function available for type %s",
1367  format_type_be(element_type))));
1368  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1369  fcinfo->flinfo->fn_mcxt);
1370  my_extra->element_type = element_type;
1371  }
1372 
1373  if (nitems == 0)
1374  {
1375  /* Return empty array ... but not till we've validated element_type */
1377  }
1378 
1379  typlen = my_extra->typlen;
1380  typbyval = my_extra->typbyval;
1381  typalign = my_extra->typalign;
1382  typioparam = my_extra->typioparam;
1383 
1384  dataPtr = (Datum *) palloc(nitems * sizeof(Datum));
1385  nullsPtr = (bool *) palloc(nitems * sizeof(bool));
1386  ReadArrayBinary(buf, nitems,
1387  &my_extra->proc, typioparam, typmod,
1388  typlen, typbyval, typalign,
1389  dataPtr, nullsPtr,
1390  &hasnulls, &nbytes);
1391  if (hasnulls)
1392  {
1393  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
1394  nbytes += dataoffset;
1395  }
1396  else
1397  {
1398  dataoffset = 0; /* marker for no null bitmap */
1399  nbytes += ARR_OVERHEAD_NONULLS(ndim);
1400  }
1401  retval = (ArrayType *) palloc0(nbytes);
1402  SET_VARSIZE(retval, nbytes);
1403  retval->ndim = ndim;
1404  retval->dataoffset = dataoffset;
1405  retval->elemtype = element_type;
1406  memcpy(ARR_DIMS(retval), dim, ndim * sizeof(int));
1407  memcpy(ARR_LBOUND(retval), lBound, ndim * sizeof(int));
1408 
1409  CopyArrayEls(retval,
1410  dataPtr, nullsPtr, nitems,
1411  typlen, typbyval, typalign,
1412  true);
1413 
1414  pfree(dataPtr);
1415  pfree(nullsPtr);
1416 
1417  PG_RETURN_ARRAYTYPE_P(retval);
1418 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define MAXDIM
Definition: c.h:529
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:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3410
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:300
signed int int32
Definition: c.h:346
#define ARR_LBOUND(a)
Definition: array.h:284
bool typbyval
Definition: array.h:228
void pfree(void *pointer)
Definition: mcxt.c:1031
char typalign
Definition: pg_type.h:170
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:282
int16 typlen
Definition: array.h:227
static char * buf
Definition: pg_test_fsync.c:68
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
char typdelim
Definition: array.h:230
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
#define ereport(elevel, rest)
Definition: elog.h:141
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:1442
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
Oid typioparam
Definition: array.h:231
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:232
char typalign
Definition: array.h:229
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
FmgrInfo proc
Definition: array.h:233
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
int i
Oid element_type
Definition: array.h:226
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
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:2103

◆ array_ref()

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

Definition at line 3076 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3079 {
3080  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3081  arraytyplen, elmlen, elmbyval, elmalign,
3082  isNull);
3083 }
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1819

◆ array_remove()

Datum array_remove ( PG_FUNCTION_ARGS  )

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

6330 {
6331  ArrayType *array;
6332  Datum search = PG_GETARG_DATUM(1);
6333  bool search_isnull = PG_ARGISNULL(1);
6334 
6335  if (PG_ARGISNULL(0))
6336  PG_RETURN_NULL();
6337  array = PG_GETARG_ARRAYTYPE_P(0);
6338 
6339  array = array_replace_internal(array,
6340  search, search_isnull,
6341  (Datum) 0, true,
6342  true, PG_GET_COLLATION(),
6343  fcinfo);
6344  PG_RETURN_ARRAYTYPE_P(array);
6345 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GET_COLLATION()
Definition: fmgr.h:193
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
uintptr_t Datum
Definition: postgres.h:367
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:6071
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ array_replace()

Datum array_replace ( PG_FUNCTION_ARGS  )

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

6352 {
6353  ArrayType *array;
6354  Datum search = PG_GETARG_DATUM(1);
6355  bool search_isnull = PG_ARGISNULL(1);
6356  Datum replace = PG_GETARG_DATUM(2);
6357  bool replace_isnull = PG_ARGISNULL(2);
6358 
6359  if (PG_ARGISNULL(0))
6360  PG_RETURN_NULL();
6361  array = PG_GETARG_ARRAYTYPE_P(0);
6362 
6363  array = array_replace_internal(array,
6364  search, search_isnull,
6365  replace, replace_isnull,
6366  false, PG_GET_COLLATION(),
6367  fcinfo);
6368  PG_RETURN_ARRAYTYPE_P(array);
6369 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GET_COLLATION()
Definition: fmgr.h:193
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
uintptr_t Datum
Definition: postgres.h:367
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:6071
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define PG_RETURN_NULL()
Definition: fmgr.h:335

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

References AllocSizeIsValid, 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, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_oid, format_type_be(), FunctionCallInvoke, i, InitFunctionCallInfoData, LOCAL_FCINFO, 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().

6076 {
6077  LOCAL_FCINFO(locfcinfo, 2);
6078  ArrayType *result;
6079  Oid element_type;
6080  Datum *values;
6081  bool *nulls;
6082  int *dim;
6083  int ndim;
6084  int nitems,
6085  nresult;
6086  int i;
6087  int32 nbytes = 0;
6088  int32 dataoffset;
6089  bool hasnulls;
6090  int typlen;
6091  bool typbyval;
6092  char typalign;
6093  char *arraydataptr;
6094  bits8 *bitmap;
6095  int bitmask;
6096  bool changed = false;
6097  TypeCacheEntry *typentry;
6098 
6099  element_type = ARR_ELEMTYPE(array);
6100  ndim = ARR_NDIM(array);
6101  dim = ARR_DIMS(array);
6102  nitems = ArrayGetNItems(ndim, dim);
6103 
6104  /* Return input array unmodified if it is empty */
6105  if (nitems <= 0)
6106  return array;
6107 
6108  /*
6109  * We can't remove elements from multi-dimensional arrays, since the
6110  * result might not be rectangular.
6111  */
6112  if (remove && ndim > 1)
6113  ereport(ERROR,
6114  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6115  errmsg("removing elements from multidimensional arrays is not supported")));
6116 
6117  /*
6118  * We arrange to look up the equality function only once per series of
6119  * calls, assuming the element type doesn't change underneath us.
6120  */
6121  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
6122  if (typentry == NULL ||
6123  typentry->type_id != element_type)
6124  {
6125  typentry = lookup_type_cache(element_type,
6127  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
6128  ereport(ERROR,
6129  (errcode(ERRCODE_UNDEFINED_FUNCTION),
6130  errmsg("could not identify an equality operator for type %s",
6131  format_type_be(element_type))));
6132  fcinfo->flinfo->fn_extra = (void *) typentry;
6133  }
6134  typlen = typentry->typlen;
6135  typbyval = typentry->typbyval;
6136  typalign = typentry->typalign;
6137 
6138  /*
6139  * Detoast values if they are toasted. The replacement value must be
6140  * detoasted for insertion into the result array, while detoasting the
6141  * search value only once saves cycles.
6142  */
6143  if (typlen == -1)
6144  {
6145  if (!search_isnull)
6146  search = PointerGetDatum(PG_DETOAST_DATUM(search));
6147  if (!replace_isnull)
6148  replace = PointerGetDatum(PG_DETOAST_DATUM(replace));
6149  }
6150 
6151  /* Prepare to apply the comparison operator */
6152  InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
6153  collation, NULL, NULL);
6154 
6155  /* Allocate temporary arrays for new values */
6156  values = (Datum *) palloc(nitems * sizeof(Datum));
6157  nulls = (bool *) palloc(nitems * sizeof(bool));
6158 
6159  /* Loop over source data */
6160  arraydataptr = ARR_DATA_PTR(array);
6161  bitmap = ARR_NULLBITMAP(array);
6162  bitmask = 1;
6163  hasnulls = false;
6164  nresult = 0;
6165 
6166  for (i = 0; i < nitems; i++)
6167  {
6168  Datum elt;
6169  bool isNull;
6170  bool oprresult;
6171  bool skip = false;
6172 
6173  /* Get source element, checking for NULL */
6174  if (bitmap && (*bitmap & bitmask) == 0)
6175  {
6176  isNull = true;
6177  /* If searching for NULL, we have a match */
6178  if (search_isnull)
6179  {
6180  if (remove)
6181  {
6182  skip = true;
6183  changed = true;
6184  }
6185  else if (!replace_isnull)
6186  {
6187  values[nresult] = replace;
6188  isNull = false;
6189  changed = true;
6190  }
6191  }
6192  }
6193  else
6194  {
6195  isNull = false;
6196  elt = fetch_att(arraydataptr, typbyval, typlen);
6197  arraydataptr = att_addlength_datum(arraydataptr, typlen, elt);
6198  arraydataptr = (char *) att_align_nominal(arraydataptr, typalign);
6199 
6200  if (search_isnull)
6201  {
6202  /* no match possible, keep element */
6203  values[nresult] = elt;
6204  }
6205  else
6206  {
6207  /*
6208  * Apply the operator to the element pair
6209  */
6210  locfcinfo->args[0].value = elt;
6211  locfcinfo->args[0].isnull = false;
6212  locfcinfo->args[1].value = search;
6213  locfcinfo->args[1].isnull = false;
6214  locfcinfo->isnull = false;
6215  oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
6216  if (!oprresult)
6217  {
6218  /* no match, keep element */
6219  values[nresult] = elt;
6220  }
6221  else
6222  {
6223  /* match, so replace or delete */
6224  changed = true;
6225  if (remove)
6226  skip = true;
6227  else
6228  {
6229  values[nresult] = replace;
6230  isNull = replace_isnull;
6231  }
6232  }
6233  }
6234  }
6235 
6236  if (!skip)
6237  {
6238  nulls[nresult] = isNull;
6239  if (isNull)
6240  hasnulls = true;
6241  else
6242  {
6243  /* Update total result size */
6244  nbytes = att_addlength_datum(nbytes, typlen, values[nresult]);
6245  nbytes = att_align_nominal(nbytes, typalign);
6246  /* check for overflow of total request */
6247  if (!AllocSizeIsValid(nbytes))
6248  ereport(ERROR,
6249  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
6250  errmsg("array size exceeds the maximum allowed (%d)",
6251  (int) MaxAllocSize)));
6252  }
6253  nresult++;
6254  }
6255 
6256  /* advance bitmap pointer if any */
6257  if (bitmap)
6258  {
6259  bitmask <<= 1;
6260  if (bitmask == 0x100)
6261  {
6262  bitmap++;
6263  bitmask = 1;
6264  }
6265  }
6266  }
6267 
6268  /*
6269  * If not changed just return the original array
6270  */
6271  if (!changed)
6272  {
6273  pfree(values);
6274  pfree(nulls);
6275  return array;
6276  }
6277 
6278  /* If all elements were removed return an empty array */
6279  if (nresult == 0)
6280  {
6281  pfree(values);
6282  pfree(nulls);
6283  return construct_empty_array(element_type);
6284  }
6285 
6286  /* Allocate and initialize the result array */
6287  if (hasnulls)
6288  {
6289  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nresult);
6290  nbytes += dataoffset;
6291  }
6292  else
6293  {
6294  dataoffset = 0; /* marker for no null bitmap */
6295  nbytes += ARR_OVERHEAD_NONULLS(ndim);
6296  }
6297  result = (ArrayType *) palloc0(nbytes);
6298  SET_VARSIZE(result, nbytes);
6299  result->ndim = ndim;
6300  result->dataoffset = dataoffset;
6301  result->elemtype = element_type;
6302  memcpy(ARR_DIMS(result), ARR_DIMS(array), ndim * sizeof(int));
6303  memcpy(ARR_LBOUND(result), ARR_LBOUND(array), ndim * sizeof(int));
6304 
6305  if (remove)
6306  {
6307  /* Adjust the result length */
6308  ARR_DIMS(result)[0] = nresult;
6309  }
6310 
6311  /* Insert data into result array */
6312  CopyArrayEls(result,
6313  values, nulls, nresult,
6314  typlen, typbyval, typalign,
6315  false);
6316 
6317  pfree(values);
6318  pfree(nulls);
6319 
6320  return result;
6321 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:146
#define PointerGetDatum(X)
Definition: postgres.h:556
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:133
int32 dataoffset
Definition: array.h:84
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3410
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:638
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:300
signed int int32
Definition: c.h:346
static const char *const skip[]
Definition: pg_checksums.c:99
#define ARR_LBOUND(a)
Definition: array.h:284
void pfree(void *pointer)
Definition: mcxt.c:1031
char typalign
Definition: pg_type.h:170
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:167
#define DatumGetBool(X)
Definition: postgres.h:393
#define ereport(elevel, rest)
Definition: elog.h:141
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
uint8 bits8
Definition: c.h:365
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
FmgrInfo * flinfo
Definition: fmgr.h:87
FmgrInfo eq_opr_finfo
Definition: typcache.h:72
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
Oid fn_oid
Definition: fmgr.h:59
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
void * fn_extra
Definition: fmgr.h:64
#define ARR_NDIM(a)
Definition: array.h:278
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:167
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:162
char typalign
Definition: typcache.h:39
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:73
int i
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:235
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
#define ARR_ELEMTYPE(a)
Definition: array.h:280
#define ARR_NULLBITMAP(a)
Definition: array.h:288
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 4587 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().

4589 {
4590  int bitmask;
4591  int i;
4592 
4593  /* easy if fixed-size elements and no NULLs */
4594  if (typlen > 0 && !nullbitmap)
4595  return ptr + nitems * ((Size) att_align_nominal(typlen, typalign));
4596 
4597  /* seems worth having separate loops for NULL and no-NULLs cases */
4598  if (nullbitmap)
4599  {
4600  nullbitmap += offset / 8;
4601  bitmask = 1 << (offset % 8);
4602 
4603  for (i = 0; i < nitems; i++)
4604  {
4605  if (*nullbitmap & bitmask)
4606  {
4607  ptr = att_addlength_pointer(ptr, typlen, ptr);
4608  ptr = (char *) att_align_nominal(ptr, typalign);
4609  }
4610  bitmask <<= 1;
4611  if (bitmask == 0x100)
4612  {
4613  nullbitmap++;
4614  bitmask = 1;
4615  }
4616  }
4617  }
4618  else
4619  {
4620  for (i = 0; i < nitems; i++)
4621  {
4622  ptr = att_addlength_pointer(ptr, typlen, ptr);
4623  ptr = (char *) att_align_nominal(ptr, typalign);
4624  }
4625  }
4626  return ptr;
4627 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:146
char typalign
Definition: pg_type.h:170
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:174
size_t Size
Definition: c.h:466
int i

◆ array_send()

Datum array_send ( PG_FUNCTION_ARGS  )

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

1548 {
1550  Oid element_type = AARR_ELEMTYPE(v);
1551  int typlen;
1552  bool typbyval;
1553  char typalign;
1554  int nitems,
1555  i;
1556  int ndim,
1557  *dim,
1558  *lb;
1560  array_iter iter;
1561  ArrayMetaState *my_extra;
1562 
1563  /*
1564  * We arrange to look up info about element type, including its send
1565  * conversion proc, only once per series of calls, assuming the element
1566  * type doesn't change underneath us.
1567  */
1568  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1569  if (my_extra == NULL)
1570  {
1571  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1572  sizeof(ArrayMetaState));
1573  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1574  my_extra->element_type = ~element_type;
1575  }
1576 
1577  if (my_extra->element_type != element_type)
1578  {
1579  /* Get info about element type, including its send proc */
1580  get_type_io_data(element_type, IOFunc_send,
1581  &my_extra->typlen, &my_extra->typbyval,
1582  &my_extra->typalign, &my_extra->typdelim,
1583  &my_extra->typioparam, &my_extra->typiofunc);
1584  if (!OidIsValid(my_extra->typiofunc))
1585  ereport(ERROR,
1586  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1587  errmsg("no binary output function available for type %s",
1588  format_type_be(element_type))));
1589  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1590  fcinfo->flinfo->fn_mcxt);
1591  my_extra->element_type = element_type;
1592  }
1593  typlen = my_extra->typlen;
1594  typbyval = my_extra->typbyval;
1595  typalign = my_extra->typalign;
1596 
1597  ndim = AARR_NDIM(v);
1598  dim = AARR_DIMS(v);
1599  lb = AARR_LBOUND(v);
1600  nitems = ArrayGetNItems(ndim, dim);
1601 
1602  pq_begintypsend(&buf);
1603 
1604  /* Send the array header information */
1605  pq_sendint32(&buf, ndim);
1606  pq_sendint32(&buf, AARR_HASNULL(v) ? 1 : 0);
1607  pq_sendint32(&buf, element_type);
1608  for (i = 0; i < ndim; i++)
1609  {
1610  pq_sendint32(&buf, dim[i]);
1611  pq_sendint32(&buf, lb[i]);
1612  }
1613 
1614  /* Send the array elements using the element's own sendproc */
1615  array_iter_setup(&iter, v);
1616 
1617  for (i = 0; i < nitems; i++)
1618  {
1619  Datum itemvalue;
1620  bool isnull;
1621 
1622  /* Get source element, checking for NULL */
1623  itemvalue = array_iter_next(&iter, &isnull, i,
1624  typlen, typbyval, typalign);
1625 
1626  if (isnull)
1627  {
1628  /* -1 length means a NULL */
1629  pq_sendint32(&buf, -1);
1630  }
1631  else
1632  {
1633  bytea *outputbytes;
1634 
1635  outputbytes = SendFunctionCall(&my_extra->proc, itemvalue);
1636  pq_sendint32(&buf, VARSIZE(outputbytes) - VARHDRSZ);
1637  pq_sendbytes(&buf, VARDATA(outputbytes),
1638  VARSIZE(outputbytes) - VARHDRSZ);
1639  pfree(outputbytes);
1640  }
1641  }
1642 
1644 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:262
#define VARDATA(PTR)
Definition: postgres.h:302
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define VARSIZE(PTR)
Definition: postgres.h:303
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
#define VARHDRSZ
Definition: c.h:555
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define AARR_HASNULL(a)
Definition: array.h:319
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:360
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
bool typbyval
Definition: array.h:228
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
void pfree(void *pointer)
Definition: mcxt.c:1031
char typalign
Definition: pg_type.h:170
#define ERROR
Definition: elog.h:43
int16 typlen
Definition: array.h:227
static char * buf
Definition: pg_test_fsync.c:68
char typdelim
Definition: array.h:230
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1636
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
#define AARR_DIMS(a)
Definition: array.h:326
#define AARR_ELEMTYPE(a)
Definition: array.h:323
#define AARR_LBOUND(a)
Definition: array.h:329
Oid typioparam
Definition: array.h:231
#define AARR_NDIM(a)
Definition: array.h:316
Oid typiofunc
Definition: array.h:232
char typalign
Definition: array.h:229
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
int errmsg(const char *fmt,...)
Definition: elog.c:784
FmgrInfo proc
Definition: array.h:233
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
int i
Oid element_type
Definition: array.h:226
Definition: c.h:549
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:2103

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

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3096 {
3098  nSubscripts, indx,
3099  dataValue, isNull,
3100  arraytyplen,
3101  elmlen, elmbyval, elmalign));
3102 }
#define PointerGetDatum(X)
Definition: postgres.h:556
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:2199
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ 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 2199 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 ExecEvalSubscriptingRefAssign().

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

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

2486 {
2487  ExpandedArrayHeader *eah;
2488  Datum *dvalues;
2489  bool *dnulls;
2490  int i,
2491  ndim,
2492  dim[MAXDIM],
2493  lb[MAXDIM],
2494  offset;
2495  bool dimschanged,
2496  newhasnulls;
2497  int addedbefore,
2498  addedafter;
2499  char *oldValue;
2500 
2501  /* Convert to R/W object if not so already */
2502  eah = DatumGetExpandedArray(arraydatum);
2503 
2504  /* Sanity-check caller's info against object; we don't use it otherwise */
2505  Assert(arraytyplen == -1);
2506  Assert(elmlen == eah->typlen);
2507  Assert(elmbyval == eah->typbyval);
2508  Assert(elmalign == eah->typalign);
2509 
2510  /*
2511  * Copy dimension info into local storage. This allows us to modify the
2512  * dimensions if needed, while not messing up the expanded value if we
2513  * fail partway through.
2514  */
2515  ndim = eah->ndims;
2516  Assert(ndim >= 0 && ndim <= MAXDIM);
2517  memcpy(dim, eah->dims, ndim * sizeof(int));
2518  memcpy(lb, eah->lbound, ndim * sizeof(int));
2519  dimschanged = false;
2520 
2521  /*
2522  * if number of dims is zero, i.e. an empty array, create an array with
2523  * nSubscripts dimensions, and set the lower bounds to the supplied
2524  * subscripts.
2525  */
2526  if (ndim == 0)
2527  {
2528  /*
2529  * Allocate adequate space for new dimension info. This is harmless
2530  * if we fail later.
2531  */
2532  Assert(nSubscripts > 0 && nSubscripts <= MAXDIM);
2533  eah->dims = (int *) MemoryContextAllocZero(eah->hdr.eoh_context,
2534  nSubscripts * sizeof(int));
2535  eah->lbound = (int *) MemoryContextAllocZero(eah->hdr.eoh_context,
2536  nSubscripts * sizeof(int));
2537 
2538  /* Update local copies of dimension info */
2539  ndim = nSubscripts;
2540  for (i = 0; i < nSubscripts; i++)
2541  {
2542  dim[i] = 0;
2543  lb[i] = indx[i];
2544  }
2545  dimschanged = true;
2546  }
2547  else if (ndim != nSubscripts)
2548  ereport(ERROR,
2549  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),