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 "port/pg_bitutils.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 48 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 46 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 54 of file arrayfuncs.c.

Function Documentation

◆ accumArrayResult()

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

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

5063 {
5064  MemoryContext oldcontext;
5065 
5066  if (astate == NULL)
5067  {
5068  /* First time through --- initialize */
5069  astate = initArrayResult(element_type, rcontext, true);
5070  }
5071  else
5072  {
5073  Assert(astate->element_type == element_type);
5074  }
5075 
5076  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5077 
5078  /* enlarge dvalues[]/dnulls[] if needed */
5079  if (astate->nelems >= astate->alen)
5080  {
5081  astate->alen *= 2;
5082  astate->dvalues = (Datum *)
5083  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5084  astate->dnulls = (bool *)
5085  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5086  }
5087 
5088  /*
5089  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5090  * it's varlena. (You might think that detoasting is not needed here
5091  * because construct_md_array can detoast the array elements later.
5092  * However, we must not let construct_md_array modify the ArrayBuildState
5093  * because that would mean array_agg_finalfn damages its input, which is
5094  * verboten. Also, this way frequently saves one copying step.)
5095  */
5096  if (!disnull && !astate->typbyval)
5097  {
5098  if (astate->typlen == -1)
5099  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5100  else
5101  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5102  }
5103 
5104  astate->dvalues[astate->nelems] = dvalue;
5105  astate->dnulls[astate->nelems] = disnull;
5106  astate->nelems++;
5107 
5108  MemoryContextSwitchTo(oldcontext);
5109 
5110  return astate;
5111 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5020
#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:131
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:738
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
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 5526 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

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

◆ accumArrayResultArr()

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

Definition at line 5253 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(), pg_nextpower2_32(), and repalloc().

Referenced by accumArrayResultAny(), and array_agg_array_transfn().

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

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

◆ array_cardinality()

Datum array_cardinality ( PG_FUNCTION_ARGS  )

Definition at line 1790 of file arrayfuncs.c.

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

1791 {
1793 
1795 }
#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:353
#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 3747 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_FREE_IF_COPY, AARR_LBOUND, AARR_NDIM, array_iter_next(), array_iter_setup(), ArrayGetNItems(), Assert, 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().

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

◆ array_contain_compare()

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

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

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

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

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

3530 {
3531  int nelems;
3532  bits8 *bitmap;
3533  int bitmask;
3534 
3535  /* Easy answer if there's no null bitmap */
3536  if (!ARR_HASNULL(array))
3537  return false;
3538 
3539  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3540 
3541  bitmap = ARR_NULLBITMAP(array);
3542 
3543  /* check whole bytes of the bitmap byte-at-a-time */
3544  while (nelems >= 8)
3545  {
3546  if (*bitmap != 0xFF)
3547  return true;
3548  bitmap++;
3549  nelems -= 8;
3550  }
3551 
3552  /* check last partial byte */
3553  bitmask = 1;
3554  while (nelems > 0)
3555  {
3556  if ((*bitmap & bitmask) == 0)
3557  return true;
3558  bitmask <<= 1;
3559  nelems--;
3560  }
3561 
3562  return false;
3563 }
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:374
#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 4663 of file arrayfuncs.c.

References array_nelems_size().

Referenced by array_extract_slice(), and array_insert_slice().

4666 {
4667  int numbytes;
4668 
4669  numbytes = array_nelems_size(srcptr, offset, nullbitmap, nitems,
4670  typlen, typbyval, typalign);
4671  memcpy(destptr, srcptr, numbytes);
4672  return numbytes;
4673 }
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:4641

◆ array_create_iterator()

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

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

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

◆ array_dims()

Datum array_dims ( PG_FUNCTION_ARGS  )

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

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

◆ array_eq()

Datum array_eq ( PG_FUNCTION_ARGS  )

Definition at line 3576 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(), and CompareOpclassOptions().

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

4835 {
4836  char *destdataptr = ARR_DATA_PTR(newarray);
4837  bits8 *destnullsptr = ARR_NULLBITMAP(newarray);
4838  char *srcdataptr;
4839  int src_offset,
4840  dest_offset,
4841  prod[MAXDIM],
4842  span[MAXDIM],
4843  dist[MAXDIM],
4844  indx[MAXDIM];
4845  int i,
4846  j,
4847  inc;
4848 
4849  src_offset = ArrayGetOffset(ndim, dim, lb, st);
4850  srcdataptr = array_seek(arraydataptr, 0, arraynullsptr, src_offset,
4851  typlen, typbyval, typalign);
4852  mda_get_prod(ndim, dim, prod);
4853  mda_get_range(ndim, span, st, endp);
4854  mda_get_offset_values(ndim, dist, prod, span);
4855  for (i = 0; i < ndim; i++)
4856  indx[i] = 0;
4857  dest_offset = 0;
4858  j = ndim - 1;
4859  do
4860  {
4861  if (dist[j])
4862  {
4863  /* skip unwanted elements */
4864  srcdataptr = array_seek(srcdataptr, src_offset, arraynullsptr,
4865  dist[j],
4866  typlen, typbyval, typalign);
4867  src_offset += dist[j];
4868  }
4869  inc = array_copy(destdataptr, 1,
4870  srcdataptr, src_offset, arraynullsptr,
4871  typlen, typbyval, typalign);
4872  if (destnullsptr)
4873  array_bitmap_copy(destnullsptr, dest_offset,
4874  arraynullsptr, src_offset,
4875  1);
4876  destdataptr += inc;
4877  srcdataptr += inc;
4878  src_offset++;
4879  dest_offset++;
4880  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4881 }
#define MAXDIM
Definition: c.h:535
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:4693
static int array_copy(char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4663
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:374
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:4593
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 5730 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.

5731 {
5732  ArrayType *dims;
5733  ArrayType *result;
5734  Oid elmtype;
5735  Datum value;
5736  bool isnull;
5737 
5738  if (PG_ARGISNULL(1))
5739  ereport(ERROR,
5740  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5741  errmsg("dimension array or low bound array cannot be null")));
5742 
5743  dims = PG_GETARG_ARRAYTYPE_P(1);
5744 
5745  if (!PG_ARGISNULL(0))
5746  {
5747  value = PG_GETARG_DATUM(0);
5748  isnull = false;
5749  }
5750  else
5751  {
5752  value = 0;
5753  isnull = true;
5754  }
5755 
5756  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5757  if (!OidIsValid(elmtype))
5758  elog(ERROR, "could not determine data type of input");
5759 
5760  result = array_fill_internal(dims, NULL, value, isnull, elmtype, fcinfo);
5761  PG_RETURN_ARRAYTYPE_P(result);
5762 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5782
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
#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:1804
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
uintptr_t Datum
Definition: postgres.h:367
static struct @143 value
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214

◆ array_fill_internal()

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

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

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

◆ array_fill_with_lower_bounds()

Datum array_fill_with_lower_bounds ( PG_FUNCTION_ARGS  )

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

5690 {
5691  ArrayType *dims;
5692  ArrayType *lbs;
5693  ArrayType *result;
5694  Oid elmtype;
5695  Datum value;
5696  bool isnull;
5697 
5698  if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
5699  ereport(ERROR,
5700  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5701  errmsg("dimension array or low bound array cannot be null")));
5702 
5703  dims = PG_GETARG_ARRAYTYPE_P(1);
5704  lbs = PG_GETARG_ARRAYTYPE_P(2);
5705 
5706  if (!PG_ARGISNULL(0))
5707  {
5708  value = PG_GETARG_DATUM(0);
5709  isnull = false;
5710  }
5711  else
5712  {
5713  value = 0;
5714  isnull = true;
5715  }
5716 
5717  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5718  if (!OidIsValid(elmtype))
5719  elog(ERROR, "could not determine data type of input");
5720 
5721  result = array_fill_internal(dims, lbs, value, isnull, elmtype, fcinfo);
5722  PG_RETURN_ARRAYTYPE_P(result);
5723 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5782
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
#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:1804
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
uintptr_t Datum
Definition: postgres.h:367
static struct @143 value
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214

◆ array_free_iterator()

void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4486 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4487 {
4488  if (iterator->slice_ndim > 0)
4489  {
4490  pfree(iterator->slice_values);
4491  pfree(iterator->slice_nulls);
4492  }
4493  pfree(iterator);
4494 }
bool * slice_nulls
Definition: arrayfuncs.c:84
void pfree(void *pointer)
Definition: mcxt.c:1056
Datum * slice_values
Definition: arrayfuncs.c:83

◆ array_ge()

Datum array_ge ( PG_FUNCTION_ARGS  )

Definition at line 3729 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

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

◆ array_get_element()

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

Definition at line 1820 of file arrayfuncs.c.

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

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

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

◆ array_get_isnull()

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

Definition at line 4508 of file arrayfuncs.c.

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

4509 {
4510  if (nullbitmap == NULL)
4511  return false; /* assume not null */
4512  if (nullbitmap[offset / 8] & (1 << (offset % 8)))
4513  return false; /* not null */
4514  return true;
4515 }

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

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

References array_cmp(), and PG_RETURN_BOOL.

3718 {
3719  PG_RETURN_BOOL(array_cmp(fcinfo) > 0);
3720 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3747
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358

◆ array_in()

Datum array_in ( PG_FUNCTION_ARGS  )

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

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

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

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

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

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

◆ array_iterate()

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

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

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

◆ array_larger()

Datum array_larger ( PG_FUNCTION_ARGS  )

Definition at line 5584 of file arrayfuncs.c.

References array_cmp(), PG_GETARG_DATUM, and PG_RETURN_DATUM.

5585 {
5586  if (array_cmp(fcinfo) > 0)
5588  else
5590 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3747
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:352

◆ array_le()

Datum array_le ( PG_FUNCTION_ARGS  )

Definition at line 3723 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

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

◆ array_length()

Datum array_length ( PG_FUNCTION_ARGS  )

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

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

◆ array_lower()

Datum array_lower ( PG_FUNCTION_ARGS  )

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

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

◆ array_lt()

Datum array_lt ( PG_FUNCTION_ARGS  )

Definition at line 3711 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3712 {
3713  PG_RETURN_BOOL(array_cmp(fcinfo) < 0);
3714 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3747
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358

◆ array_map()

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

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

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

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

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

◆ array_ne()

Datum array_ne ( PG_FUNCTION_ARGS  )

Definition at line 3705 of file arrayfuncs.c.

References array_eq(), DatumGetBool, and PG_RETURN_BOOL.

3706 {
3708 }
#define DatumGetBool(X)
Definition: postgres.h:393
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358
Datum array_eq(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:3576

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

References array_seek().

Referenced by array_copy(), and array_set_slice().

4643 {
4644  return array_seek(ptr, offset, nullbitmap, nitems,
4645  typlen, typbyval, typalign) - ptr;
4646 }
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:4593

◆ array_out()

Datum array_out ( PG_FUNCTION_ARGS  )

Definition at line 1013 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(), and anycompatiblearray_out().

1014 {
1016  Oid element_type = AARR_ELEMTYPE(v);
1017  int typlen;
1018  bool typbyval;
1019  char typalign;
1020  char typdelim;
1021  char *p,
1022  *tmp,
1023  *retval,
1024  **values,
1025  dims_str[(MAXDIM * 33) + 2];
1026 
1027  /*
1028  * 33 per dim since we assume 15 digits per number + ':' +'[]'
1029  *
1030  * +2 allows for assignment operator + trailing null
1031  */
1032  bool *needquotes,
1033  needdims = false;
1034  size_t overall_length;
1035  int nitems,
1036  i,
1037  j,
1038  k,
1039  indx[MAXDIM];
1040  int ndim,
1041  *dims,
1042  *lb;
1043  array_iter iter;
1044  ArrayMetaState *my_extra;
1045 
1046  /*
1047  * We arrange to look up info about element type, including its output
1048  * conversion proc, only once per series of calls, assuming the element
1049  * type doesn't change underneath us.
1050  */
1051  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1052  if (my_extra == NULL)
1053  {
1054  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1055  sizeof(ArrayMetaState));
1056  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1057  my_extra->element_type = ~element_type;
1058  }
1059 
1060  if (my_extra->element_type != element_type)
1061  {
1062  /*
1063  * Get info about element type, including its output conversion proc
1064  */
1065  get_type_io_data(element_type, IOFunc_output,
1066  &my_extra->typlen, &my_extra->typbyval,
1067  &my_extra->typalign, &my_extra->typdelim,
1068  &my_extra->typioparam, &my_extra->typiofunc);
1069  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1070  fcinfo->flinfo->fn_mcxt);
1071  my_extra->element_type = element_type;
1072  }
1073  typlen = my_extra->typlen;
1074  typbyval = my_extra->typbyval;
1075  typalign = my_extra->typalign;
1076  typdelim = my_extra->typdelim;
1077 
1078  ndim = AARR_NDIM(v);
1079  dims = AARR_DIMS(v);
1080  lb = AARR_LBOUND(v);
1081  nitems = ArrayGetNItems(ndim, dims);
1082 
1083  if (nitems == 0)
1084  {
1085  retval = pstrdup("{}");
1086  PG_RETURN_CSTRING(retval);
1087  }
1088 
1089  /*
1090  * we will need to add explicit dimensions if any dimension has a lower
1091  * bound other than one
1092  */
1093  for (i = 0; i < ndim; i++)
1094  {
1095  if (lb[i] != 1)
1096  {
1097  needdims = true;
1098  break;
1099  }
1100  }
1101 
1102  /*
1103  * Convert all values to string form, count total space needed (including
1104  * any overhead such as escaping backslashes), and detect whether each
1105  * item needs double quotes.
1106  */
1107  values = (char **) palloc(nitems * sizeof(char *));
1108  needquotes = (bool *) palloc(nitems * sizeof(bool));
1109  overall_length = 0;
1110 
1111  array_iter_setup(&iter, v);
1112 
1113  for (i = 0; i < nitems; i++)
1114  {
1115  Datum itemvalue;
1116  bool isnull;
1117  bool needquote;
1118 
1119  /* Get source element, checking for NULL */
1120  itemvalue = array_iter_next(&iter, &isnull, i,
1121  typlen, typbyval, typalign);
1122 
1123  if (isnull)
1124  {
1125  values[i] = pstrdup("NULL");
1126  overall_length += 4;
1127  needquote = false;
1128  }
1129  else
1130  {
1131  values[i] = OutputFunctionCall(&my_extra->proc, itemvalue);
1132 
1133  /* count data plus backslashes; detect chars needing quotes */
1134  if (values[i][0] == '\0')
1135  needquote = true; /* force quotes for empty string */
1136  else if (pg_strcasecmp(values[i], "NULL") == 0)
1137  needquote = true; /* force quotes for literal NULL */
1138  else
1139  needquote = false;
1140 
1141  for (tmp = values[i]; *tmp != '\0'; tmp++)
1142  {
1143  char ch = *tmp;
1144 
1145  overall_length += 1;
1146  if (ch == '"' || ch == '\\')
1147  {
1148  needquote = true;
1149  overall_length += 1;
1150  }
1151  else if (ch == '{' || ch == '}' || ch == typdelim ||
1152  array_isspace(ch))
1153  needquote = true;
1154  }
1155  }
1156 
1157  needquotes[i] = needquote;
1158 
1159  /* Count the pair of double quotes, if needed */
1160  if (needquote)
1161  overall_length += 2;
1162  /* and the comma (or other typdelim delimiter) */
1163  overall_length += 1;
1164  }
1165 
1166  /*
1167  * The very last array element doesn't have a typdelim delimiter after it,
1168  * but that's OK; that space is needed for the trailing '\0'.
1169  *
1170  * Now count total number of curly brace pairs in output string.
1171  */
1172  for (i = j = 0, k = 1; i < ndim; i++)
1173  {
1174  j += k, k *= dims[i];
1175  }
1176  overall_length += 2 * j;
1177 
1178  /* Format explicit dimensions if required */
1179  dims_str[0] = '\0';
1180  if (needdims)
1181  {
1182  char *ptr = dims_str;
1183 
1184  for (i = 0; i < ndim; i++)
1185  {
1186  sprintf(ptr, "[%d:%d]", lb[i], lb[i] + dims[i] - 1);
1187  ptr += strlen(ptr);
1188  }
1189  *ptr++ = *ASSGN;
1190  *ptr = '\0';
1191  overall_length += ptr - dims_str;
1192  }
1193 
1194  /* Now construct the output string */
1195  retval = (char *) palloc(overall_length);
1196  p = retval;
1197 
1198 #define APPENDSTR(str) (strcpy(p, (str)), p += strlen(p))
1199 #define APPENDCHAR(ch) (*p++ = (ch), *p = '\0')
1200 
1201  if (needdims)
1202  APPENDSTR(dims_str);
1203  APPENDCHAR('{');
1204  for (i = 0; i < ndim; i++)
1205  indx[i] = 0;
1206  j = 0;
1207  k = 0;
1208  do
1209  {
1210  for (i = j; i < ndim - 1; i++)
1211  APPENDCHAR('{');
1212 
1213  if (needquotes[k])
1214  {
1215  APPENDCHAR('"');
1216  for (tmp = values[k]; *tmp; tmp++)
1217  {
1218  char ch = *tmp;
1219 
1220  if (ch == '"' || ch == '\\')
1221  *p++ = '\\';
1222  *p++ = ch;
1223  }
1224  *p = '\0';
1225  APPENDCHAR('"');
1226  }
1227  else
1228  APPENDSTR(values[k]);
1229  pfree(values[k++]);
1230 
1231  for (i = ndim - 1; i >= 0; i--)
1232  {
1233  if (++(indx[i]) < dims[i])
1234  {
1235  APPENDCHAR(typdelim);
1236  break;
1237  }
1238  else
1239  {
1240  indx[i] = 0;
1241  APPENDCHAR('}');
1242  }
1243  }
1244  j = i;
1245  } while (j != -1);
1246 
1247 #undef APPENDSTR
1248 #undef APPENDCHAR
1249 
1250  /* Assert that we calculated the string length accurately */
1251  Assert(overall_length == (p - retval + 1));
1252 
1253  pfree(values);
1254  pfree(needquotes);
1255 
1256  PG_RETURN_CSTRING(retval);
1257 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:262
static bool array_isspace(char ch)
Definition: arrayfuncs.c:433
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define MAXDIM
Definition: c.h:535
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:1186
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:1577
bool typbyval
Definition: array.h:228
#define sprintf
Definition: port.h:195
void pfree(void *pointer)
Definition: mcxt.c:1056
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:136
#define ASSGN
Definition: arrayfuncs.c:46
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:738
Oid typioparam
Definition: array.h:231
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:361
#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:949
FmgrInfo proc
Definition: array.h:233
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
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:2213

◆ array_recv()

Datum array_recv ( PG_FUNCTION_ARGS  )

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

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

◆ array_ref()

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

Definition at line 3077 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3080 {
3081  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3082  arraytyplen, elmlen, elmbyval, elmalign,
3083  isNull);
3084 }
#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:1820

◆ array_remove()

Datum array_remove ( PG_FUNCTION_ARGS  )

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

6332 {
6333  ArrayType *array;
6334  Datum search = PG_GETARG_DATUM(1);
6335  bool search_isnull = PG_ARGISNULL(1);
6336 
6337  if (PG_ARGISNULL(0))
6338  PG_RETURN_NULL();
6339  array = PG_GETARG_ARRAYTYPE_P(0);
6340 
6341  array = array_replace_internal(array,
6342  search, search_isnull,
6343  (Datum) 0, true,
6344  true, PG_GET_COLLATION(),
6345  fcinfo);
6346  PG_RETURN_ARRAYTYPE_P(array);
6347 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GET_COLLATION()
Definition: fmgr.h:198
#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:6073
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ array_replace()

Datum array_replace ( PG_FUNCTION_ARGS  )

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

6354 {
6355  ArrayType *array;
6356  Datum search = PG_GETARG_DATUM(1);
6357  bool search_isnull = PG_ARGISNULL(1);
6358  Datum replace = PG_GETARG_DATUM(2);
6359  bool replace_isnull = PG_ARGISNULL(2);
6360 
6361  if (PG_ARGISNULL(0))
6362  PG_RETURN_NULL();
6363  array = PG_GETARG_ARRAYTYPE_P(0);
6364 
6365  array = array_replace_internal(array,
6366  search, search_isnull,
6367  replace, replace_isnull,
6368  false, PG_GET_COLLATION(),
6369  fcinfo);
6370  PG_RETURN_ARRAYTYPE_P(array);
6371 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GET_COLLATION()
Definition: fmgr.h:198
#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:6073
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_RETURN_NULL()
Definition: fmgr.h:344

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

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

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

◆ array_send()

Datum array_send ( PG_FUNCTION_ARGS  )

Definition at line 1548 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(), anycompatiblearray_send(), int2vectorsend(), and oidvectorsend().

1549 {
1551  Oid element_type = AARR_ELEMTYPE(v);
1552  int typlen;
1553  bool typbyval;
1554  char typalign;
1555  int nitems,
1556  i;
1557  int ndim,
1558  *dim,
1559  *lb;
1561  array_iter iter;
1562  ArrayMetaState *my_extra;
1563 
1564  /*
1565  * We arrange to look up info about element type, including its send
1566  * conversion proc, only once per series of calls, assuming the element
1567  * type doesn't change underneath us.
1568  */
1569  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1570  if (my_extra == NULL)
1571  {
1572  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1573  sizeof(ArrayMetaState));
1574  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1575  my_extra->element_type = ~element_type;
1576  }
1577 
1578  if (my_extra->element_type != element_type)
1579  {
1580  /* Get info about element type, including its send proc */
1581  get_type_io_data(element_type, IOFunc_send,
1582  &my_extra->typlen, &my_extra->typbyval,
1583  &my_extra->typalign, &my_extra->typdelim,
1584  &my_extra->typioparam, &my_extra->typiofunc);
1585  if (!OidIsValid(my_extra->typiofunc))
1586  ereport(ERROR,
1587  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1588  errmsg("no binary output function available for type %s",
1589  format_type_be(element_type))));
1590  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1591  fcinfo->flinfo->fn_mcxt);
1592  my_extra->element_type = element_type;
1593  }
1594  typlen = my_extra->typlen;
1595  typbyval = my_extra->typbyval;
1596  typalign = my_extra->typalign;
1597 
1598  ndim = AARR_NDIM(v);
1599  dim = AARR_DIMS(v);
1600  lb = AARR_LBOUND(v);
1601  nitems = ArrayGetNItems(ndim, dim);
1602 
1603  pq_begintypsend(&buf);
1604 
1605  /* Send the array header information */
1606  pq_sendint32(&buf, ndim);
1607  pq_sendint32(&buf, AARR_HASNULL(v) ? 1 : 0);
1608  pq_sendint32(&buf, element_type);
1609  for (i = 0; i < ndim; i++)
1610  {
1611  pq_sendint32(&buf, dim[i]);
1612  pq_sendint32(&buf, lb[i]);
1613  }
1614 
1615  /* Send the array elements using the element's own sendproc */
1616  array_iter_setup(&iter, v);
1617 
1618  for (i = 0; i < nitems; i++)
1619  {
1620  Datum itemvalue;
1621  bool isnull;
1622 
1623  /* Get source element, checking for NULL */
1624  itemvalue = array_iter_next(&iter, &isnull, i,
1625  typlen, typbyval, typalign);
1626 
1627  if (isnull)
1628  {
1629  /* -1 length means a NULL */
1630  pq_sendint32(&buf, -1);
1631  }
1632  else
1633  {
1634  bytea *outputbytes;
1635 
1636  outputbytes = SendFunctionCall(&my_extra->proc, itemvalue);
1637  pq_sendint32(&buf, VARSIZE(outputbytes) - VARHDRSZ);
1638  pq_sendbytes(&buf, VARDATA(outputbytes),
1639  VARSIZE(outputbytes) - VARHDRSZ);
1640  pfree(outputbytes);
1641  }
1642  }
1643 
1645 }
#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:561
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:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:327
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:369
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
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:1056
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:67
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:1638
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
uintptr_t Datum
Definition: postgres.h:367
#define AARR_DIMS(a)
Definition: array.h:326
#define AARR_ELEMTYPE(a)
Definition: array.h:323
#define ereport(elevel,...)
Definition: elog.h:144
#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:824
FmgrInfo proc
Definition: array.h:233
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
int i
Oid element_type
Definition: array.h:226
Definition: c.h:555
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:2213

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

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3097 {
3099  nSubscripts, indx,
3100  dataValue, isNull,
3101  arraytyplen,
3102  elmlen, elmbyval, elmalign));
3103 }
#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:2200
#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 2200 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().

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

Referenced by array_set_element().

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