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)
 
Datum trim_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 5087 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(), brin_minmax_multi_summary_out(), dblink_get_connections(), get_altertable_subcmdtypes(), optionListToArray(), parse_ident(), pg_get_statisticsobjdef_expressions(), pg_stats_ext_mcvlist_items(), populate_array_element(), range_agg_transfn(), regexp_split_to_array(), serialize_expr_stats(), SPI_sql_row_to_xmlelement(), split_text_accum_result(), transformRelOptions(), and tuple_data_split_internal().

5091 {
5092  MemoryContext oldcontext;
5093 
5094  if (astate == NULL)
5095  {
5096  /* First time through --- initialize */
5097  astate = initArrayResult(element_type, rcontext, true);
5098  }
5099  else
5100  {
5101  Assert(astate->element_type == element_type);
5102  }
5103 
5104  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5105 
5106  /* enlarge dvalues[]/dnulls[] if needed */
5107  if (astate->nelems >= astate->alen)
5108  {
5109  astate->alen *= 2;
5110  astate->dvalues = (Datum *)
5111  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5112  astate->dnulls = (bool *)
5113  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5114  }
5115 
5116  /*
5117  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5118  * it's varlena. (You might think that detoasting is not needed here
5119  * because construct_md_array can detoast the array elements later.
5120  * However, we must not let construct_md_array modify the ArrayBuildState
5121  * because that would mean array_agg_finalfn damages its input, which is
5122  * verboten. Also, this way frequently saves one copying step.)
5123  */
5124  if (!disnull && !astate->typbyval)
5125  {
5126  if (astate->typlen == -1)
5127  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5128  else
5129  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5130  }
5131 
5132  astate->dvalues[astate->nelems] = dvalue;
5133  astate->dnulls[astate->nelems] = disnull;
5134  astate->nelems++;
5135 
5136  MemoryContextSwitchTo(oldcontext);
5137 
5138  return astate;
5139 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5048
#define PointerGetDatum(X)
Definition: postgres.h:600
Datum * dvalues
Definition: array.h:183
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:189
Oid element_type
Definition: array.h:187
bool * dnulls
Definition: array.h:184
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
uintptr_t Datum
Definition: postgres.h:411
#define Assert(condition)
Definition: c.h:804
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
MemoryContext mcontext
Definition: array.h:182
int16 typlen
Definition: array.h:188

◆ accumArrayResultAny()

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

Definition at line 5558 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5562 {
5563  if (astate == NULL)
5564  astate = initArrayResultAny(input_type, rcontext, true);
5565 
5566  if (astate->scalarstate)
5567  (void) accumArrayResult(astate->scalarstate,
5568  dvalue, disnull,
5569  input_type, rcontext);
5570  else
5571  (void) accumArrayResultArr(astate->arraystate,
5572  dvalue, disnull,
5573  input_type, rcontext);
5574 
5575  return astate;
5576 }
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5513
ArrayBuildState * scalarstate
Definition: array.h:222
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5281
ArrayBuildStateArr * arraystate
Definition: array.h:223
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5087

◆ accumArrayResultArr()

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

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

5285 {
5286  ArrayType *arg;
5287  MemoryContext oldcontext;
5288  int *dims,
5289  *lbs,
5290  ndims,
5291  nitems,
5292  ndatabytes;
5293  char *data;
5294  int i;
5295 
5296  /*
5297  * We disallow accumulating null subarrays. Another plausible definition
5298  * is to ignore them, but callers that want that can just skip calling
5299  * this function.
5300  */
5301  if (disnull)
5302  ereport(ERROR,
5303  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5304  errmsg("cannot accumulate null arrays")));
5305 
5306  /* Detoast input array in caller's context */
5307  arg = DatumGetArrayTypeP(dvalue);
5308 
5309  if (astate == NULL)
5310  astate = initArrayResultArr(array_type, InvalidOid, rcontext, true);
5311  else
5312  Assert(astate->array_type == array_type);
5313 
5314  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5315 
5316  /* Collect this input's dimensions */
5317  ndims = ARR_NDIM(arg);
5318  dims = ARR_DIMS(arg);
5319  lbs = ARR_LBOUND(arg);
5320  data = ARR_DATA_PTR(arg);
5321  nitems = ArrayGetNItems(ndims, dims);
5322  ndatabytes = ARR_SIZE(arg) - ARR_DATA_OFFSET(arg);
5323 
5324  if (astate->ndims == 0)
5325  {
5326  /* First input; check/save the dimensionality info */
5327 
5328  /* Should we allow empty inputs and just produce an empty output? */
5329  if (ndims == 0)
5330  ereport(ERROR,
5331  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5332  errmsg("cannot accumulate empty arrays")));
5333  if (ndims + 1 > MAXDIM)
5334  ereport(ERROR,
5335  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5336  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5337  ndims + 1, MAXDIM)));
5338 
5339  /*
5340  * The output array will have n+1 dimensions, with the ones after the
5341  * first matching the input's dimensions.
5342  */
5343  astate->ndims = ndims + 1;
5344  astate->dims[0] = 0;
5345  memcpy(&astate->dims[1], dims, ndims * sizeof(int));
5346  astate->lbs[0] = 1;
5347  memcpy(&astate->lbs[1], lbs, ndims * sizeof(int));
5348 
5349  /* Allocate at least enough data space for this item */
5350  astate->abytes = pg_nextpower2_32(Max(1024, ndatabytes + 1));
5351  astate->data = (char *) palloc(astate->abytes);
5352  }
5353  else
5354  {
5355  /* Second or later input: must match first input's dimensionality */
5356  if (astate->ndims != ndims + 1)
5357  ereport(ERROR,
5358  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5359  errmsg("cannot accumulate arrays of different dimensionality")));
5360  for (i = 0; i < ndims; i++)
5361  {
5362  if (astate->dims[i + 1] != dims[i] || astate->lbs[i + 1] != lbs[i])
5363  ereport(ERROR,
5364  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5365  errmsg("cannot accumulate arrays of different dimensionality")));
5366  }
5367 
5368  /* Enlarge data space if needed */
5369  if (astate->nbytes + ndatabytes > astate->abytes)
5370  {
5371  astate->abytes = Max(astate->abytes * 2,
5372  astate->nbytes + ndatabytes);
5373  astate->data = (char *) repalloc(astate->data, astate->abytes);
5374  }
5375  }
5376 
5377  /*
5378  * Copy the data portion of the sub-array. Note we assume that the
5379  * advertised data length of the sub-array is properly aligned. We do not
5380  * have to worry about detoasting elements since whatever's in the
5381  * sub-array should be OK already.
5382  */
5383  memcpy(astate->data + astate->nbytes, data, ndatabytes);
5384  astate->nbytes += ndatabytes;
5385 
5386  /* Deal with null bitmap if needed */
5387  if (astate->nullbitmap || ARR_HASNULL(arg))
5388  {
5389  int newnitems = astate->nitems + nitems;
5390 
5391  if (astate->nullbitmap == NULL)
5392  {
5393  /*
5394  * First input with nulls; we must retrospectively handle any
5395  * previous inputs by marking all their items non-null.
5396  */
5397  astate->aitems = pg_nextpower2_32(Max(256, newnitems + 1));
5398  astate->nullbitmap = (bits8 *) palloc((astate->aitems + 7) / 8);
5399  array_bitmap_copy(astate->nullbitmap, 0,
5400  NULL, 0,
5401  astate->nitems);
5402  }
5403  else if (newnitems > astate->aitems)
5404  {
5405  astate->aitems = Max(astate->aitems * 2, newnitems);
5406  astate->nullbitmap = (bits8 *)
5407  repalloc(astate->nullbitmap, (astate->aitems + 7) / 8);
5408  }
5409  array_bitmap_copy(astate->nullbitmap, astate->nitems,
5410  ARR_NULLBITMAP(arg), 0,
5411  nitems);
5412  }
5413 
5414  astate->nitems += nitems;
5415  astate->dims[0] += 1;
5416 
5417  MemoryContextSwitchTo(oldcontext);
5418 
5419  /* Release detoasted copy if any */
5420  if ((Pointer) arg != DatumGetPointer(dvalue))
5421  pfree(arg);
5422 
5423  return astate;
5424 }
#define ARR_SIZE(a)
Definition: array.h:282
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4721
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5235
#define ARR_DATA_OFFSET(a)
Definition: array.h:309
#define ARR_LBOUND(a)
Definition: array.h:289
bits8 * nullbitmap
Definition: array.h:202
void pfree(void *pointer)
Definition: mcxt.c:1169
char * Pointer
Definition: c.h:418
#define ERROR
Definition: elog.h:46
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define MAXDIM
Definition: array.h:75
static uint32 pg_nextpower2_32(uint32 num)
Definition: pg_bitutils.h:146
#define ARR_HASNULL(a)
Definition: array.h:284
uint8 bits8
Definition: c.h:448
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
int lbs[MAXDIM]
Definition: array.h:209
#define Max(x, y)
Definition: c.h:980
#define Assert(condition)
Definition: c.h:804
#define ARR_NDIM(a)
Definition: array.h:283
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
#define DatumGetPointer(X)
Definition: postgres.h:593
int dims[MAXDIM]
Definition: array.h:208
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
void * arg
#define ARR_NULLBITMAP(a)
Definition: array.h:293
MemoryContext mcontext
Definition: array.h:200
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ array_bitmap_copy()

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

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

4724 {
4725  int destbitmask,
4726  destbitval,
4727  srcbitmask,
4728  srcbitval;
4729 
4730  Assert(destbitmap);
4731  if (nitems <= 0)
4732  return; /* don't risk fetch off end of memory */
4733  destbitmap += destoffset / 8;
4734  destbitmask = 1 << (destoffset % 8);
4735  destbitval = *destbitmap;
4736  if (srcbitmap)
4737  {
4738  srcbitmap += srcoffset / 8;
4739  srcbitmask = 1 << (srcoffset % 8);
4740  srcbitval = *srcbitmap;
4741  while (nitems-- > 0)
4742  {
4743  if (srcbitval & srcbitmask)
4744  destbitval |= destbitmask;
4745  else
4746  destbitval &= ~destbitmask;
4747  destbitmask <<= 1;
4748  if (destbitmask == 0x100)
4749  {
4750  *destbitmap++ = destbitval;
4751  destbitmask = 1;
4752  if (nitems > 0)
4753  destbitval = *destbitmap;
4754  }
4755  srcbitmask <<= 1;
4756  if (srcbitmask == 0x100)
4757  {
4758  srcbitmap++;
4759  srcbitmask = 1;
4760  if (nitems > 0)
4761  srcbitval = *srcbitmap;
4762  }
4763  }
4764  if (destbitmask != 1)
4765  *destbitmap = destbitval;
4766  }
4767  else
4768  {
4769  while (nitems-- > 0)
4770  {
4771  destbitval |= destbitmask;
4772  destbitmask <<= 1;
4773  if (destbitmask == 0x100)
4774  {
4775  *destbitmap++ = destbitval;
4776  destbitmask = 1;
4777  if (nitems > 0)
4778  destbitval = *destbitmap;
4779  }
4780  }
4781  if (destbitmask != 1)
4782  *destbitmap = destbitval;
4783  }
4784 }
#define Assert(condition)
Definition: c.h:804

◆ array_cardinality()

Datum array_cardinality ( PG_FUNCTION_ARGS  )

Definition at line 1800 of file arrayfuncs.c.

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

1801 {
1803 
1805 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:267
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define AARR_DIMS(a)
Definition: array.h:331
#define AARR_NDIM(a)
Definition: array.h:321

◆ array_cmp()

static int array_cmp ( FunctionCallInfo  fcinfo)
static

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

3776 {
3777  LOCAL_FCINFO(locfcinfo, 2);
3778  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY_P(0);
3779  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY_P(1);
3780  Oid collation = PG_GET_COLLATION();
3781  int ndims1 = AARR_NDIM(array1);
3782  int ndims2 = AARR_NDIM(array2);
3783  int *dims1 = AARR_DIMS(array1);
3784  int *dims2 = AARR_DIMS(array2);
3785  int nitems1 = ArrayGetNItems(ndims1, dims1);
3786  int nitems2 = ArrayGetNItems(ndims2, dims2);
3787  Oid element_type = AARR_ELEMTYPE(array1);
3788  int result = 0;
3789  TypeCacheEntry *typentry;
3790  int typlen;
3791  bool typbyval;
3792  char typalign;
3793  int min_nitems;
3794  array_iter it1;
3795  array_iter it2;
3796  int i;
3797 
3798  if (element_type != AARR_ELEMTYPE(array2))
3799  ereport(ERROR,
3800  (errcode(ERRCODE_DATATYPE_MISMATCH),
3801  errmsg("cannot compare arrays of different element types")));
3802 
3803  /*
3804  * We arrange to look up the comparison function only once per series of
3805  * calls, assuming the element type doesn't change underneath us. The
3806  * typcache is used so that we have no memory leakage when being used as
3807  * an index support function.
3808  */
3809  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3810  if (typentry == NULL ||
3811  typentry->type_id != element_type)
3812  {
3813  typentry = lookup_type_cache(element_type,
3815  if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
3816  ereport(ERROR,
3817  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3818  errmsg("could not identify a comparison function for type %s",
3819  format_type_be(element_type))));
3820  fcinfo->flinfo->fn_extra = (void *) typentry;
3821  }
3822  typlen = typentry->typlen;
3823  typbyval = typentry->typbyval;
3824  typalign = typentry->typalign;
3825 
3826  /*
3827  * apply the operator to each pair of array elements.
3828  */
3829  InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2,
3830  collation, NULL, NULL);
3831 
3832  /* Loop over source data */
3833  min_nitems = Min(nitems1, nitems2);
3834  array_iter_setup(&it1, array1);
3835  array_iter_setup(&it2, array2);
3836 
3837  for (i = 0; i < min_nitems; i++)
3838  {
3839  Datum elt1;
3840  Datum elt2;
3841  bool isnull1;
3842  bool isnull2;
3843  int32 cmpresult;
3844 
3845  /* Get elements, checking for NULL */
3846  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
3847  elt2 = array_iter_next(&it2, &isnull2, i, typlen, typbyval, typalign);
3848 
3849  /*
3850  * We consider two NULLs equal; NULL > not-NULL.
3851  */
3852  if (isnull1 && isnull2)
3853  continue;
3854  if (isnull1)
3855  {
3856  /* arg1 is greater than arg2 */
3857  result = 1;
3858  break;
3859  }
3860  if (isnull2)
3861  {
3862  /* arg1 is less than arg2 */
3863  result = -1;
3864  break;
3865  }
3866 
3867  /* Compare the pair of elements */
3868  locfcinfo->args[0].value = elt1;
3869  locfcinfo->args[0].isnull = false;
3870  locfcinfo->args[1].value = elt2;
3871  locfcinfo->args[1].isnull = false;
3872  cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo));
3873 
3874  /* We don't expect comparison support functions to return null */
3875  Assert(!locfcinfo->isnull);
3876 
3877  if (cmpresult == 0)
3878  continue; /* equal */
3879 
3880  if (cmpresult < 0)
3881  {
3882  /* arg1 is less than arg2 */
3883  result = -1;
3884  break;
3885  }
3886  else
3887  {
3888  /* arg1 is greater than arg2 */
3889  result = 1;
3890  break;
3891  }
3892  }
3893 
3894  /*
3895  * If arrays contain same data (up to end of shorter one), apply
3896  * additional rules to sort by dimensionality. The relative significance
3897  * of the different bits of information is historical; mainly we just care
3898  * that we don't say "equal" for arrays of different dimensionality.
3899  */
3900  if (result == 0)
3901  {
3902  if (nitems1 != nitems2)
3903  result = (nitems1 < nitems2) ? -1 : 1;
3904  else if (ndims1 != ndims2)
3905  result = (ndims1 < ndims2) ? -1 : 1;
3906  else
3907  {
3908  for (i = 0; i < ndims1; i++)
3909  {
3910  if (dims1[i] != dims2[i])
3911  {
3912  result = (dims1[i] < dims2[i]) ? -1 : 1;
3913  break;
3914  }
3915  }
3916  if (result == 0)
3917  {
3918  int *lbound1 = AARR_LBOUND(array1);
3919  int *lbound2 = AARR_LBOUND(array2);
3920 
3921  for (i = 0; i < ndims1; i++)
3922  {
3923  if (lbound1[i] != lbound2[i])
3924  {
3925  result = (lbound1[i] < lbound2[i]) ? -1 : 1;
3926  break;
3927  }
3928  }
3929  }
3930  }
3931  }
3932 
3933  /* Avoid leaking memory when handed toasted input. */
3934  AARR_FREE_IF_COPY(array1, 0);
3935  AARR_FREE_IF_COPY(array2, 1);
3936 
3937  return result;
3938 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:267
#define DatumGetInt32(X)
Definition: postgres.h:516
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:986
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
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:710
#define PG_GET_COLLATION()
Definition: fmgr.h:198
signed int int32
Definition: c.h:429
FmgrInfo cmp_proc_finfo
Definition: typcache.h:76
char typalign
Definition: pg_type.h:176
#define ERROR
Definition: elog.h:46
#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:411
FmgrInfo * flinfo
Definition: fmgr.h:87
#define AARR_DIMS(a)
Definition: array.h:331
#define AARR_ELEMTYPE(a)
Definition: array.h:328
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:339
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:157
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define AARR_LBOUND(a)
Definition: array.h:334
#define Assert(condition)
Definition: c.h:804
#define AARR_NDIM(a)
Definition: array.h:321
#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:909
int i
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:142

◆ array_contain_compare()

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

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

4138 {
4139  LOCAL_FCINFO(locfcinfo, 2);
4140  bool result = matchall;
4141  Oid element_type = AARR_ELEMTYPE(array1);
4142  TypeCacheEntry *typentry;
4143  int nelems1;
4144  Datum *values2;
4145  bool *nulls2;
4146  int nelems2;
4147  int typlen;
4148  bool typbyval;
4149  char typalign;
4150  int i;
4151  int j;
4152  array_iter it1;
4153 
4154  if (element_type != AARR_ELEMTYPE(array2))
4155  ereport(ERROR,
4156  (errcode(ERRCODE_DATATYPE_MISMATCH),
4157  errmsg("cannot compare arrays of different element types")));
4158 
4159  /*
4160  * We arrange to look up the equality function only once per series of
4161  * calls, assuming the element type doesn't change underneath us. The
4162  * typcache is used so that we have no memory leakage when being used as
4163  * an index support function.
4164  */
4165  typentry = (TypeCacheEntry *) *fn_extra;
4166  if (typentry == NULL ||
4167  typentry->type_id != element_type)
4168  {
4169  typentry = lookup_type_cache(element_type,
4171  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
4172  ereport(ERROR,
4173  (errcode(ERRCODE_UNDEFINED_FUNCTION),
4174  errmsg("could not identify an equality operator for type %s",
4175  format_type_be(element_type))));
4176  *fn_extra = (void *) typentry;
4177  }
4178  typlen = typentry->typlen;
4179  typbyval = typentry->typbyval;
4180  typalign = typentry->typalign;
4181 
4182  /*
4183  * Since we probably will need to scan array2 multiple times, it's
4184  * worthwhile to use deconstruct_array on it. We scan array1 the hard way
4185  * however, since we very likely won't need to look at all of it.
4186  */
4187  if (VARATT_IS_EXPANDED_HEADER(array2))
4188  {
4189  /* This should be safe even if input is read-only */
4190  deconstruct_expanded_array(&(array2->xpn));
4191  values2 = array2->xpn.dvalues;
4192  nulls2 = array2->xpn.dnulls;
4193  nelems2 = array2->xpn.nelems;
4194  }
4195  else
4196  deconstruct_array((ArrayType *) array2,
4197  element_type, typlen, typbyval, typalign,
4198  &values2, &nulls2, &nelems2);
4199 
4200  /*
4201  * Apply the comparison operator to each pair of array elements.
4202  */
4203  InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
4204  collation, NULL, NULL);
4205 
4206  /* Loop over source data */
4207  nelems1 = ArrayGetNItems(AARR_NDIM(array1), AARR_DIMS(array1));
4208  array_iter_setup(&it1, array1);
4209 
4210  for (i = 0; i < nelems1; i++)
4211  {
4212  Datum elt1;
4213  bool isnull1;
4214 
4215  /* Get element, checking for NULL */
4216  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
4217 
4218  /*
4219  * We assume that the comparison operator is strict, so a NULL can't
4220  * match anything. XXX this diverges from the "NULL=NULL" behavior of
4221  * array_eq, should we act like that?
4222  */
4223  if (isnull1)
4224  {
4225  if (matchall)
4226  {
4227  result = false;
4228  break;
4229  }
4230  continue;
4231  }
4232 
4233  for (j = 0; j < nelems2; j++)
4234  {
4235  Datum elt2 = values2[j];
4236  bool isnull2 = nulls2 ? nulls2[j] : false;
4237  bool oprresult;
4238 
4239  if (isnull2)
4240  continue; /* can't match */
4241 
4242  /*
4243  * Apply the operator to the element pair; treat NULL as false
4244  */
4245  locfcinfo->args[0].value = elt1;
4246  locfcinfo->args[0].isnull = false;
4247  locfcinfo->args[1].value = elt2;
4248  locfcinfo->args[1].isnull = false;
4249  locfcinfo->isnull = false;
4250  oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
4251  if (!locfcinfo->isnull && oprresult)
4252  break;
4253  }
4254 
4255  if (j < nelems2)
4256  {
4257  /* found a match for elt1 */
4258  if (!matchall)
4259  {
4260  result = true;
4261  break;
4262  }
4263  }
4264  else
4265  {
4266  /* no match for elt1 */
4267  if (matchall)
4268  {
4269  result = false;
4270  break;
4271  }
4272  }
4273  }
4274 
4275  return result;
4276 }
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:141
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
ExpandedArrayHeader xpn
Definition: array.h:173
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
Datum * dvalues
Definition: array.h:139
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:710
char typalign
Definition: pg_type.h:176
#define ERROR
Definition: elog.h:46
#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:437
uintptr_t Datum
Definition: postgres.h:411
#define AARR_DIMS(a)
Definition: array.h:331
#define AARR_ELEMTYPE(a)
Definition: array.h:328
FmgrInfo eq_opr_finfo
Definition: typcache.h:75
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:339
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:157
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define AARR_NDIM(a)
Definition: array.h:321
#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:3490
char typalign
Definition: typcache.h:41
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

Definition at line 3557 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(), sanity_check_tid_array(), and width_bucket_array().

3558 {
3559  int nelems;
3560  bits8 *bitmap;
3561  int bitmask;
3562 
3563  /* Easy answer if there's no null bitmap */
3564  if (!ARR_HASNULL(array))
3565  return false;
3566 
3567  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3568 
3569  bitmap = ARR_NULLBITMAP(array);
3570 
3571  /* check whole bytes of the bitmap byte-at-a-time */
3572  while (nelems >= 8)
3573  {
3574  if (*bitmap != 0xFF)
3575  return true;
3576  bitmap++;
3577  nelems -= 8;
3578  }
3579 
3580  /* check last partial byte */
3581  bitmask = 1;
3582  while (nelems > 0)
3583  {
3584  if ((*bitmap & bitmask) == 0)
3585  return true;
3586  bitmask <<= 1;
3587  nelems--;
3588  }
3589 
3590  return false;
3591 }
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_HASNULL(a)
Definition: array.h:284
uint8 bits8
Definition: c.h:448
#define ARR_NDIM(a)
Definition: array.h:283
#define ARR_NULLBITMAP(a)
Definition: array.h:293

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

References array_nelems_size().

Referenced by array_extract_slice(), and array_insert_slice().

4694 {
4695  int numbytes;
4696 
4697  numbytes = array_nelems_size(srcptr, offset, nullbitmap, nitems,
4698  typlen, typbyval, typalign);
4699  memcpy(destptr, srcptr, numbytes);
4700  return numbytes;
4701 }
char typalign
Definition: pg_type.h:176
static int array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4669

◆ array_create_iterator()

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

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

4353 {
4354  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4355 
4356  /*
4357  * Sanity-check inputs --- caller should have got this right already
4358  */
4359  Assert(PointerIsValid(arr));
4360  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4361  elog(ERROR, "invalid arguments to array_create_iterator");
4362 
4363  /*
4364  * Remember basic info about the array and its element type
4365  */
4366  iterator->arr = arr;
4367  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4368  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4369 
4370  if (mstate != NULL)
4371  {
4372  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4373 
4374  iterator->typlen = mstate->typlen;
4375  iterator->typbyval = mstate->typbyval;
4376  iterator->typalign = mstate->typalign;
4377  }
4378  else
4380  &iterator->typlen,
4381  &iterator->typbyval,
4382  &iterator->typalign);
4383 
4384  /*
4385  * Remember the slicing parameters.
4386  */
4387  iterator->slice_ndim = slice_ndim;
4388 
4389  if (slice_ndim > 0)
4390  {
4391  /*
4392  * Get pointers into the array's dims and lbound arrays to represent
4393  * the dims/lbound arrays of a slice. These are the same as the
4394  * rightmost N dimensions of the array.
4395  */
4396  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4397  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4398 
4399  /*
4400  * Compute number of elements in a slice.
4401  */
4402  iterator->slice_len = ArrayGetNItems(slice_ndim,
4403  iterator->slice_dims);
4404 
4405  /*
4406  * Create workspace for building sub-arrays.
4407  */
4408  iterator->slice_values = (Datum *)
4409  palloc(iterator->slice_len * sizeof(Datum));
4410  iterator->slice_nulls = (bool *)
4411  palloc(iterator->slice_len * sizeof(bool));
4412  }
4413 
4414  /*
4415  * Initialize our data pointer and linear element number. These will
4416  * advance through the array during array_iterate().
4417  */
4418  iterator->data_ptr = ARR_DATA_PTR(arr);
4419  iterator->current_item = 0;
4420 
4421  return iterator;
4422 }
bits8 * nullbitmap
Definition: arrayfuncs.c:72
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2218
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
#define ARR_LBOUND(a)
Definition: array.h:289
bool typbyval
Definition: array.h:233
bool * slice_nulls
Definition: arrayfuncs.c:84
#define ERROR
Definition: elog.h:46
Datum * slice_values
Definition: arrayfuncs.c:83
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
int16 typlen
Definition: array.h:232
void * palloc0(Size size)
Definition: mcxt.c:1093
uintptr_t Datum
Definition: postgres.h:411
#define Assert(condition)
Definition: c.h:804
#define ARR_NDIM(a)
Definition: array.h:283
char typalign
Definition: array.h:234
void * palloc(Size size)
Definition: mcxt.c:1062
#define elog(elevel,...)
Definition: elog.h:232
Oid element_type
Definition: array.h:231
#define PointerIsValid(pointer)
Definition: c.h:698
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_NULLBITMAP(a)
Definition: array.h:293
ArrayType * arr
Definition: arrayfuncs.c:71

◆ array_dims()

Datum array_dims ( PG_FUNCTION_ARGS  )

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

1679 {
1681  char *p;
1682  int i;
1683  int *dimv,
1684  *lb;
1685 
1686  /*
1687  * 33 since we assume 15 digits per number + ':' +'[]'
1688  *
1689  * +1 for trailing null
1690  */
1691  char buf[MAXDIM * 33 + 1];
1692 
1693  /* Sanity check: does it look like an array at all? */
1694  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1695  PG_RETURN_NULL();
1696 
1697  dimv = AARR_DIMS(v);
1698  lb = AARR_LBOUND(v);
1699 
1700  p = buf;
1701  for (i = 0; i < AARR_NDIM(v); i++)
1702  {
1703  sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1);
1704  p += strlen(p);
1705  }
1706 
1708 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:267
#define sprintf
Definition: port.h:218
static char * buf
Definition: pg_test_fsync.c:68
#define MAXDIM
Definition: array.h:75
#define AARR_DIMS(a)
Definition: array.h:331
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:190
#define AARR_LBOUND(a)
Definition: array.h:334
#define AARR_NDIM(a)
Definition: array.h:321
int i
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ array_eq()

Datum array_eq ( PG_FUNCTION_ARGS  )

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

3605 {
3606  LOCAL_FCINFO(locfcinfo, 2);
3607  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY_P(0);
3608  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY_P(1);
3609  Oid collation = PG_GET_COLLATION();
3610  int ndims1 = AARR_NDIM(array1);
3611  int ndims2 = AARR_NDIM(array2);
3612  int *dims1 = AARR_DIMS(array1);
3613  int *dims2 = AARR_DIMS(array2);
3614  int *lbs1 = AARR_LBOUND(array1);
3615  int *lbs2 = AARR_LBOUND(array2);
3616  Oid element_type = AARR_ELEMTYPE(array1);
3617  bool result = true;
3618  int nitems;
3619  TypeCacheEntry *typentry;
3620  int typlen;
3621  bool typbyval;
3622  char typalign;
3623  array_iter it1;
3624  array_iter it2;
3625  int i;
3626 
3627  if (element_type != AARR_ELEMTYPE(array2))
3628  ereport(ERROR,
3629  (errcode(ERRCODE_DATATYPE_MISMATCH),
3630  errmsg("cannot compare arrays of different element types")));
3631 
3632  /* fast path if the arrays do not have the same dimensionality */
3633  if (ndims1 != ndims2 ||
3634  memcmp(dims1, dims2, ndims1 * sizeof(int)) != 0 ||
3635  memcmp(lbs1, lbs2, ndims1 * sizeof(int)) != 0)
3636  result = false;
3637  else
3638  {
3639  /*
3640  * We arrange to look up the equality function only once per series of
3641  * calls, assuming the element type doesn't change underneath us. The
3642  * typcache is used so that we have no memory leakage when being used
3643  * as an index support function.
3644  */
3645  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3646  if (typentry == NULL ||
3647  typentry->type_id != element_type)
3648  {
3649  typentry = lookup_type_cache(element_type,
3651  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
3652  ereport(ERROR,
3653  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3654  errmsg("could not identify an equality operator for type %s",
3655  format_type_be(element_type))));
3656  fcinfo->flinfo->fn_extra = (void *) typentry;
3657  }
3658  typlen = typentry->typlen;
3659  typbyval = typentry->typbyval;
3660  typalign = typentry->typalign;
3661 
3662  /*
3663  * apply the operator to each pair of array elements.
3664  */
3665  InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
3666  collation, NULL, NULL);
3667 
3668  /* Loop over source data */
3669  nitems = ArrayGetNItems(ndims1, dims1);
3670  array_iter_setup(&it1, array1);
3671  array_iter_setup(&it2, array2);
3672 
3673  for (i = 0; i < nitems; i++)
3674  {
3675  Datum elt1;
3676  Datum elt2;
3677  bool isnull1;
3678  bool isnull2;
3679  bool oprresult;
3680 
3681  /* Get elements, checking for NULL */
3682  elt1 = array_iter_next(&it1, &isnull1, i,
3683  typlen, typbyval, typalign);
3684  elt2 = array_iter_next(&it2, &isnull2, i,
3685  typlen, typbyval, typalign);
3686 
3687  /*
3688  * We consider two NULLs equal; NULL and not-NULL are unequal.
3689  */
3690  if (isnull1 && isnull2)
3691  continue;
3692  if (isnull1 || isnull2)
3693  {
3694  result = false;
3695  break;
3696  }
3697 
3698  /*
3699  * Apply the operator to the element pair; treat NULL as false
3700  */
3701  locfcinfo->args[0].value = elt1;
3702  locfcinfo->args[0].isnull = false;
3703  locfcinfo->args[1].value = elt2;
3704  locfcinfo->args[1].isnull = false;
3705  locfcinfo->isnull = false;
3706  oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
3707  if (locfcinfo->isnull || !oprresult)
3708  {
3709  result = false;
3710  break;
3711  }
3712  }
3713  }
3714 
3715  /* Avoid leaking memory when handed toasted input. */
3716  AARR_FREE_IF_COPY(array1, 0);
3717  AARR_FREE_IF_COPY(array2, 1);
3718 
3719  PG_RETURN_BOOL(result);
3720 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:267
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:141
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
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:710
#define PG_GET_COLLATION()
Definition: fmgr.h:198
char typalign
Definition: pg_type.h:176
#define ERROR
Definition: elog.h:46
#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:437
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
uintptr_t Datum
Definition: postgres.h:411
#define AARR_DIMS(a)
Definition: array.h:331
#define AARR_ELEMTYPE(a)
Definition: array.h:328
FmgrInfo eq_opr_finfo
Definition: typcache.h:75
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:339
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:157
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define AARR_LBOUND(a)
Definition: array.h:334
#define AARR_NDIM(a)
Definition: array.h:321
#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:909
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 4852 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().

4863 {
4864  char *destdataptr = ARR_DATA_PTR(newarray);
4865  bits8 *destnullsptr = ARR_NULLBITMAP(newarray);
4866  char *srcdataptr;
4867  int src_offset,
4868  dest_offset,
4869  prod[MAXDIM],
4870  span[MAXDIM],
4871  dist[MAXDIM],
4872  indx[MAXDIM];
4873  int i,
4874  j,
4875  inc;
4876 
4877  src_offset = ArrayGetOffset(ndim, dim, lb, st);
4878  srcdataptr = array_seek(arraydataptr, 0, arraynullsptr, src_offset,
4879  typlen, typbyval, typalign);
4880  mda_get_prod(ndim, dim, prod);
4881  mda_get_range(ndim, span, st, endp);
4882  mda_get_offset_values(ndim, dist, prod, span);
4883  for (i = 0; i < ndim; i++)
4884  indx[i] = 0;
4885  dest_offset = 0;
4886  j = ndim - 1;
4887  do
4888  {
4889  if (dist[j])
4890  {
4891  /* skip unwanted elements */
4892  srcdataptr = array_seek(srcdataptr, src_offset, arraynullsptr,
4893  dist[j],
4894  typlen, typbyval, typalign);
4895  src_offset += dist[j];
4896  }
4897  inc = array_copy(destdataptr, 1,
4898  srcdataptr, src_offset, arraynullsptr,
4899  typlen, typbyval, typalign);
4900  if (destnullsptr)
4901  array_bitmap_copy(destnullsptr, dest_offset,
4902  arraynullsptr, src_offset,
4903  1);
4904  destdataptr += inc;
4905  srcdataptr += inc;
4906  src_offset++;
4907  dest_offset++;
4908  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4909 }
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:32
void mda_get_prod(int n, const int *range, int *prod)
Definition: arrayutils.c:165
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4721
static int array_copy(char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4691
char typalign
Definition: pg_type.h:176
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define MAXDIM
Definition: array.h:75
void mda_get_offset_values(int n, int *dist, const int *prod, const int *span)
Definition: arrayutils.c:181
uint8 bits8
Definition: c.h:448
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:151
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4621
int mda_next_tuple(int n, int *curr, const int *span)
Definition: arrayutils.c:206
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:293

◆ array_fill()

Datum array_fill ( PG_FUNCTION_ARGS  )

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

5763 {
5764  ArrayType *dims;
5765  ArrayType *result;
5766  Oid elmtype;
5767  Datum value;
5768  bool isnull;
5769 
5770  if (PG_ARGISNULL(1))
5771  ereport(ERROR,
5772  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5773  errmsg("dimension array or low bound array cannot be null")));
5774 
5775  dims = PG_GETARG_ARRAYTYPE_P(1);
5776 
5777  if (!PG_ARGISNULL(0))
5778  {
5779  value = PG_GETARG_DATUM(0);
5780  isnull = false;
5781  }
5782  else
5783  {
5784  value = 0;
5785  isnull = true;
5786  }
5787 
5788  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5789  if (!OidIsValid(elmtype))
5790  elog(ERROR, "could not determine data type of input");
5791 
5792  result = array_fill_internal(dims, NULL, value, isnull, elmtype, fcinfo);
5793  PG_RETURN_ARRAYTYPE_P(result);
5794 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5814
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define ERROR
Definition: elog.h:46
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1800
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:258
uintptr_t Datum
Definition: postgres.h:411
static struct @143 value
#define ereport(elevel,...)
Definition: elog.h:157
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232

◆ array_fill_internal()

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

Definition at line 5814 of file arrayfuncs.c.

References AllocSizeIsValid, ARR_DATA_PTR, ARR_DIMS, ARR_NDIM, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_contains_nulls(), ArrayCastAndSet(), ArrayCheckBounds(), 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().

5817 {
5818  ArrayType *result;
5819  int *dimv;
5820  int *lbsv;
5821  int ndims;
5822  int nitems;
5823  int deflbs[MAXDIM];
5824  int16 elmlen;
5825  bool elmbyval;
5826  char elmalign;
5827  ArrayMetaState *my_extra;
5828 
5829  /*
5830  * Params checks
5831  */
5832  if (ARR_NDIM(dims) > 1)
5833  ereport(ERROR,
5834  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5835  errmsg("wrong number of array subscripts"),
5836  errdetail("Dimension array must be one dimensional.")));
5837 
5838  if (array_contains_nulls(dims))
5839  ereport(ERROR,
5840  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5841  errmsg("dimension values cannot be null")));
5842 
5843  dimv = (int *) ARR_DATA_PTR(dims);
5844  ndims = (ARR_NDIM(dims) > 0) ? ARR_DIMS(dims)[0] : 0;
5845 
5846  if (ndims < 0) /* we do allow zero-dimension arrays */
5847  ereport(ERROR,
5848  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5849  errmsg("invalid number of dimensions: %d", ndims)));
5850  if (ndims > MAXDIM)
5851  ereport(ERROR,
5852  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5853  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5854  ndims, MAXDIM)));
5855 
5856  if (lbs != NULL)
5857  {
5858  if (ARR_NDIM(lbs) > 1)
5859  ereport(ERROR,
5860  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5861  errmsg("wrong number of array subscripts"),
5862  errdetail("Dimension array must be one dimensional.")));
5863 
5864  if (array_contains_nulls(lbs))
5865  ereport(ERROR,
5866  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5867  errmsg("dimension values cannot be null")));
5868 
5869  if (ndims != ((ARR_NDIM(lbs) > 0) ? ARR_DIMS(lbs)[0] : 0))
5870  ereport(ERROR,
5871  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5872  errmsg("wrong number of array subscripts"),
5873  errdetail("Low bound array has different size than dimensions array.")));
5874 
5875  lbsv = (int *) ARR_DATA_PTR(lbs);
5876  }
5877  else
5878  {
5879  int i;
5880 
5881  for (i = 0; i < MAXDIM; i++)
5882  deflbs[i] = 1;
5883 
5884  lbsv = deflbs;
5885  }
5886 
5887  /* This checks for overflow of the array dimensions */
5888  nitems = ArrayGetNItems(ndims, dimv);
5889  ArrayCheckBounds(ndims, dimv, lbsv);
5890 
5891  /* fast track for empty array */
5892  if (nitems <= 0)
5893  return construct_empty_array(elmtype);
5894 
5895  /*
5896  * We arrange to look up info about element type only once per series of
5897  * calls, assuming the element type doesn't change underneath us.
5898  */
5899  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
5900  if (my_extra == NULL)
5901  {
5902  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
5903  sizeof(ArrayMetaState));
5904  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
5905  my_extra->element_type = InvalidOid;
5906  }
5907 
5908  if (my_extra->element_type != elmtype)
5909  {
5910  /* Get info about element type */
5911  get_typlenbyvalalign(elmtype,
5912  &my_extra->typlen,
5913  &my_extra->typbyval,
5914  &my_extra->typalign);
5915  my_extra->element_type = elmtype;
5916  }
5917 
5918  elmlen = my_extra->typlen;
5919  elmbyval = my_extra->typbyval;
5920  elmalign = my_extra->typalign;
5921 
5922  /* compute required space */
5923  if (!isnull)
5924  {
5925  int i;
5926  char *p;
5927  int nbytes;
5928  int totbytes;
5929 
5930  /* make sure data is not toasted */
5931  if (elmlen == -1)
5933 
5934  nbytes = att_addlength_datum(0, elmlen, value);
5935  nbytes = att_align_nominal(nbytes, elmalign);
5936  Assert(nbytes > 0);
5937 
5938  totbytes = nbytes * nitems;
5939 
5940  /* check for overflow of multiplication or total request */
5941  if (totbytes / nbytes != nitems ||
5942  !AllocSizeIsValid(totbytes))
5943  ereport(ERROR,
5944  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5945  errmsg("array size exceeds the maximum allowed (%d)",
5946  (int) MaxAllocSize)));
5947 
5948  /*
5949  * This addition can't overflow, but it might cause us to go past
5950  * MaxAllocSize. We leave it to palloc to complain in that case.
5951  */
5952  totbytes += ARR_OVERHEAD_NONULLS(ndims);
5953 
5954  result = create_array_envelope(ndims, dimv, lbsv, totbytes,
5955  elmtype, 0);
5956 
5957  p = ARR_DATA_PTR(result);
5958  for (i = 0; i < nitems; i++)
5959  p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, p);
5960  }
5961  else
5962  {
5963  int nbytes;
5964  int dataoffset;
5965 
5966  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
5967  nbytes = dataoffset;
5968 
5969  result = create_array_envelope(ndims, dimv, lbsv, nbytes,
5970  elmtype, dataoffset);
5971 
5972  /* create_array_envelope already zeroed the bitmap, so we're done */
5973  }
5974 
5975  return result;
5976 }
signed short int16
Definition: c.h:428
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
static int ArrayCastAndSet(Datum src, int typlen, bool typbyval, char typalign, char *dest)
Definition: arrayfuncs.c:4582
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2218
#define PointerGetDatum(X)
Definition: postgres.h:600
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
int errcode(int sqlerrcode)
Definition: elog.c:698
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3439
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
bool typbyval
Definition: array.h:233
#define ERROR
Definition: elog.h:46
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
int16 typlen
Definition: array.h:232
#define MAXDIM
Definition: array.h:75
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void ArrayCheckBounds(int ndim, const int *dims, const int *lb)
Definition: arrayutils.c:128
FmgrInfo * flinfo
Definition: fmgr.h:87
#define InvalidOid
Definition: postgres_ext.h:36
static struct @143 value
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
static ArrayType * create_array_envelope(int ndims, int *dimv, int *lbsv, int nbytes, Oid elmtype, int dataoffset)
Definition: arrayfuncs.c:5797
void * fn_extra
Definition: fmgr.h:64
#define ARR_NDIM(a)
Definition: array.h:283
char typalign
Definition: array.h:234
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:164
int errmsg(const char *fmt,...)
Definition: elog.c:909
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
int i
Oid element_type
Definition: array.h:231
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3557

◆ array_fill_with_lower_bounds()

Datum array_fill_with_lower_bounds ( PG_FUNCTION_ARGS  )

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

5722 {
5723  ArrayType *dims;
5724  ArrayType *lbs;
5725  ArrayType *result;
5726  Oid elmtype;
5727  Datum value;
5728  bool isnull;
5729 
5730  if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
5731  ereport(ERROR,
5732  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5733  errmsg("dimension array or low bound array cannot be null")));
5734 
5735  dims = PG_GETARG_ARRAYTYPE_P(1);
5736  lbs = PG_GETARG_ARRAYTYPE_P(2);
5737 
5738  if (!PG_ARGISNULL(0))
5739  {
5740  value = PG_GETARG_DATUM(0);
5741  isnull = false;
5742  }
5743  else
5744  {
5745  value = 0;
5746  isnull = true;
5747  }
5748 
5749  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5750  if (!OidIsValid(elmtype))
5751  elog(ERROR, "could not determine data type of input");
5752 
5753  result = array_fill_internal(dims, lbs, value, isnull, elmtype, fcinfo);
5754  PG_RETURN_ARRAYTYPE_P(result);
5755 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5814
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define ERROR
Definition: elog.h:46
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1800
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:258
uintptr_t Datum
Definition: postgres.h:411
static struct @143 value
#define ereport(elevel,...)
Definition: elog.h:157
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232

◆ array_free_iterator()

void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4514 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4515 {
4516  if (iterator->slice_ndim > 0)
4517  {
4518  pfree(iterator->slice_values);
4519  pfree(iterator->slice_nulls);
4520  }
4521  pfree(iterator);
4522 }
bool * slice_nulls
Definition: arrayfuncs.c:84
void pfree(void *pointer)
Definition: mcxt.c:1169
Datum * slice_values
Definition: arrayfuncs.c:83

◆ array_ge()

Datum array_ge ( PG_FUNCTION_ARGS  )

Definition at line 3757 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3758 {
3759  PG_RETURN_BOOL(array_cmp(fcinfo) >= 0);
3760 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3775
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

◆ 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 1830 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(), array_subscript_fetch(), array_subscript_fetch_old(), ATExecAlterColumnType(), and RelationBuildTupleDesc().

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

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

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

◆ array_get_isnull()

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

Definition at line 4536 of file arrayfuncs.c.

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

4537 {
4538  if (nullbitmap == NULL)
4539  return false; /* assume not null */
4540  if (nullbitmap[offset / 8] & (1 << (offset % 8)))
4541  return false; /* not null */
4542  return true;
4543 }

◆ 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 2040 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 array_subscript_fetch_old_slice(), array_subscript_fetch_slice(), and trim_array().

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

◆ array_gt()

Datum array_gt ( PG_FUNCTION_ARGS  )

Definition at line 3745 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3746 {
3747  PG_RETURN_BOOL(array_cmp(fcinfo) > 0);
3748 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3775
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

◆ 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(), ArrayCheckBounds(), 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  ArrayCheckBounds(ndim, dim, lBound);
376 
377  /* Empty array? */
378  if (nitems == 0)
380 
381  dataPtr = (Datum *) palloc(nitems * sizeof(Datum));
382  nullsPtr = (bool *) palloc(nitems * sizeof(bool));
383  ReadArrayStr(p, string,
384  nitems, ndim, dim,
385  &my_extra->proc, typioparam, typmod,
386  typdelim,
387  typlen, typbyval, typalign,
388  dataPtr, nullsPtr,
389  &hasnulls, &nbytes);
390  if (hasnulls)
391  {
392  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
393  nbytes += dataoffset;
394  }
395  else
396  {
397  dataoffset = 0; /* marker for no null bitmap */
398  nbytes += ARR_OVERHEAD_NONULLS(ndim);
399  }
400  retval = (ArrayType *) palloc0(nbytes);
401  SET_VARSIZE(retval, nbytes);
402  retval->ndim = ndim;
403  retval->dataoffset = dataoffset;
404 
405  /*
406  * This comes from the array's pg_type.typelem (which points to the base
407  * data type's pg_type.oid) and stores system oids in user tables. This
408  * oid must be preserved by binary upgrades.
409  */
410  retval->elemtype = element_type;
411  memcpy(ARR_DIMS(retval), dim, ndim * sizeof(int));
412  memcpy(ARR_LBOUND(retval), lBound, ndim * sizeof(int));
413 
414  CopyArrayEls(retval,
415  dataPtr, nullsPtr, nitems,
416  typlen, typbyval, typalign,
417  true);
418 
419  pfree(dataPtr);
420  pfree(nullsPtr);
421  pfree(string_save);
422 
423  PG_RETURN_ARRAYTYPE_P(retval);
424 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
static bool array_isspace(char ch)
Definition: arrayfuncs.c:435
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
MemoryContext fn_mcxt
Definition: fmgr.h:65
char * pstrdup(const char *in)
Definition: mcxt.c:1299
int32 dataoffset
Definition: array.h:89
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
int errcode(int sqlerrcode)
Definition: elog.c:698
#define printf(...)
Definition: port.h:222
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3439
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
signed int int32
Definition: c.h:429
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:720
#define ARR_LBOUND(a)
Definition: array.h:289
bool typbyval
Definition: array.h:233
void pfree(void *pointer)
Definition: mcxt.c:1169
char typalign
Definition: pg_type.h:176
#define ERROR
Definition: elog.h:46
Oid elemtype
Definition: array.h:90
#define ARR_DIMS(a)
Definition: array.h:287
int16 typlen
Definition: array.h:232
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
char typdelim
Definition: array.h:235
#define MAXDIM
Definition: array.h:75
int errdetail(const char *fmt,...)
Definition: elog.c:1042
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:258
#define ASSGN
Definition: arrayfuncs.c:46
void ArrayCheckBounds(int ndim, const int *dims, const int *lb)
Definition: arrayutils.c:128
void * palloc0(Size size)
Definition: mcxt.c:1093
uintptr_t Datum
Definition: postgres.h:411
#define ereport(elevel,...)
Definition: elog.h:157
Oid typioparam
Definition: array.h:236
static int ArrayCount(const char *str, int *dim, char typdelim)
Definition: arrayfuncs.c:455
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:960
Oid typiofunc
Definition: array.h:237
char typalign
Definition: array.h:234
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
FmgrInfo proc
Definition: array.h:238
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
int i
Oid element_type
Definition: array.h:231
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:342
int ndim
Definition: array.h:88
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:2272

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

4936 {
4937  char *destPtr = ARR_DATA_PTR(destArray);
4938  char *origPtr = ARR_DATA_PTR(origArray);
4939  char *srcPtr = ARR_DATA_PTR(srcArray);
4940  bits8 *destBitmap = ARR_NULLBITMAP(destArray);
4941  bits8 *origBitmap = ARR_NULLBITMAP(origArray);
4942  bits8 *srcBitmap = ARR_NULLBITMAP(srcArray);
4943  int orignitems = ArrayGetNItems(ARR_NDIM(origArray),
4944  ARR_DIMS(origArray));
4945  int dest_offset,
4946  orig_offset,
4947  src_offset,
4948  prod[MAXDIM],
4949  span[MAXDIM],
4950  dist[MAXDIM],
4951  indx[MAXDIM];
4952  int i,
4953  j,
4954  inc;
4955 
4956  dest_offset = ArrayGetOffset(ndim, dim, lb, st);
4957  /* copy items before the slice start */
4958  inc = array_copy(destPtr, dest_offset,
4959  origPtr, 0, origBitmap,
4960  typlen, typbyval, typalign);
4961  destPtr += inc;
4962  origPtr += inc;
4963  if (destBitmap)
4964  array_bitmap_copy(destBitmap, 0, origBitmap, 0, dest_offset);
4965  orig_offset = dest_offset;
4966  mda_get_prod(ndim, dim, prod);
4967  mda_get_range(ndim, span, st, endp);
4968  mda_get_offset_values(ndim, dist, prod, span);
4969  for (i = 0; i < ndim; i++)
4970  indx[i] = 0;
4971  src_offset = 0;
4972  j = ndim - 1;
4973  do
4974  {
4975  /* Copy/advance over elements between here and next part of slice */
4976  if (dist[j])
4977  {
4978  inc = array_copy(destPtr, dist[j],
4979  origPtr, orig_offset, origBitmap,
4980  typlen, typbyval, typalign);
4981  destPtr += inc;
4982  origPtr += inc;
4983  if (destBitmap)
4984  array_bitmap_copy(destBitmap, dest_offset,
4985  origBitmap, orig_offset,
4986  dist[j]);
4987  dest_offset += dist[j];
4988  orig_offset += dist[j];
4989  }
4990  /* Copy new element at this slice position */
4991  inc = array_copy(destPtr, 1,
4992  srcPtr, src_offset, srcBitmap,
4993  typlen, typbyval, typalign);
4994  if (destBitmap)
4995  array_bitmap_copy(destBitmap, dest_offset,
4996  srcBitmap, src_offset,
4997  1);
4998  destPtr += inc;
4999  srcPtr += inc;
5000  dest_offset++;
5001  src_offset++;
5002  /* Advance over old element at this slice position */
5003  origPtr = array_seek(origPtr, orig_offset, origBitmap, 1,
5004  typlen, typbyval, typalign);
5005  orig_offset++;
5006  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
5007 
5008  /* don't miss any data at the end */
5009  array_copy(destPtr, orignitems - orig_offset,
5010  origPtr, orig_offset, origBitmap,
5011  typlen, typbyval, typalign);
5012  if (destBitmap)
5013  array_bitmap_copy(destBitmap, dest_offset,
5014  origBitmap, orig_offset,
5015  orignitems - orig_offset);
5016 }
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:32
void mda_get_prod(int n, const int *range, int *prod)
Definition: arrayutils.c:165
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4721
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
static int array_copy(char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4691
char typalign
Definition: pg_type.h:176
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define MAXDIM
Definition: array.h:75
void mda_get_offset_values(int n, int *dist, const int *prod, const int *span)
Definition: arrayutils.c:181
uint8 bits8
Definition: c.h:448
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:151
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4621
#define ARR_NDIM(a)
Definition: array.h:283
int mda_next_tuple(int n, int *curr, const int *span)
Definition: arrayutils.c:206
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:293

◆ array_isspace()

static bool array_isspace ( char  ch)
static

Definition at line 435 of file arrayfuncs.c.

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

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

◆ array_iterate()

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

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

4432 {
4433  /* Done if we have reached the end of the array */
4434  if (iterator->current_item >= iterator->nitems)
4435  return false;
4436 
4437  if (iterator->slice_ndim == 0)
4438  {
4439  /*
4440  * Scalar case: return one element.
4441  */
4442  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4443  {
4444  *isnull = true;
4445  *value = (Datum) 0;
4446  }
4447  else
4448  {
4449  /* non-NULL, so fetch the individual Datum to return */
4450  char *p = iterator->data_ptr;
4451 
4452  *isnull = false;
4453  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4454 
4455  /* Move our data pointer forward to the next element */
4456  p = att_addlength_pointer(p, iterator->typlen, p);
4457  p = (char *) att_align_nominal(p, iterator->typalign);
4458  iterator->data_ptr = p;
4459  }
4460  }
4461  else
4462  {
4463  /*
4464  * Slice case: build and return an array of the requested size.
4465  */
4466  ArrayType *result;
4467  Datum *values = iterator->slice_values;
4468  bool *nulls = iterator->slice_nulls;
4469  char *p = iterator->data_ptr;
4470  int i;
4471 
4472  for (i = 0; i < iterator->slice_len; i++)
4473  {
4474  if (array_get_isnull(iterator->nullbitmap,
4475  iterator->current_item++))
4476  {
4477  nulls[i] = true;
4478  values[i] = (Datum) 0;
4479  }
4480  else
4481  {
4482  nulls[i] = false;
4483  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4484 
4485  /* Move our data pointer forward to the next element */
4486  p = att_addlength_pointer(p, iterator->typlen, p);
4487  p = (char *) att_align_nominal(p, iterator->typalign);
4488  }
4489  }
4490 
4491  iterator->data_ptr = p;
4492 
4493  result = construct_md_array(values,
4494  nulls,
4495  iterator->slice_ndim,
4496  iterator->slice_dims,
4497  iterator->slice_lbound,
4498  ARR_ELEMTYPE(iterator->arr),
4499  iterator->typlen,
4500  iterator->typbyval,
4501  iterator->typalign);
4502 
4503  *isnull = false;
4504  *value = PointerGetDatum(result);
4505  }
4506 
4507  return true;
4508 }
bits8 * nullbitmap
Definition: arrayfuncs.c:72
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
#define PointerGetDatum(X)
Definition: postgres.h:600
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:411
static struct @143 value
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4536
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#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:3353
#define ARR_ELEMTYPE(a)
Definition: array.h:285
ArrayType * arr
Definition: arrayfuncs.c:71

◆ array_larger()

Datum array_larger ( PG_FUNCTION_ARGS  )

Definition at line 5616 of file arrayfuncs.c.

References array_cmp(), PG_GETARG_DATUM, and PG_RETURN_DATUM.

5617 {
5618  if (array_cmp(fcinfo) > 0)
5620  else
5622 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3775
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353

◆ array_le()

Datum array_le ( PG_FUNCTION_ARGS  )

Definition at line 3751 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3752 {
3753  PG_RETURN_BOOL(array_cmp(fcinfo) <= 0);
3754 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3775
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

◆ array_length()

Datum array_length ( PG_FUNCTION_ARGS  )

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

Referenced by trim_array().

1774 {
1776  int reqdim = PG_GETARG_INT32(1);
1777  int *dimv;
1778  int result;
1779 
1780  /* Sanity check: does it look like an array at all? */
1781  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1782  PG_RETURN_NULL();
1783 
1784  /* Sanity check: was the requested dim valid */
1785  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1786  PG_RETURN_NULL();
1787 
1788  dimv = AARR_DIMS(v);
1789 
1790  result = dimv[reqdim - 1];
1791 
1792  PG_RETURN_INT32(result);
1793 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:267
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define MAXDIM
Definition: array.h:75
#define AARR_DIMS(a)
Definition: array.h:331
#define AARR_NDIM(a)
Definition: array.h:321
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ array_lower()

Datum array_lower ( PG_FUNCTION_ARGS  )

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

1717 {
1719  int reqdim = PG_GETARG_INT32(1);
1720  int *lb;
1721  int result;
1722 
1723  /* Sanity check: does it look like an array at all? */
1724  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1725  PG_RETURN_NULL();
1726 
1727  /* Sanity check: was the requested dim valid */
1728  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1729  PG_RETURN_NULL();
1730 
1731  lb = AARR_LBOUND(v);
1732  result = lb[reqdim - 1];
1733 
1734  PG_RETURN_INT32(result);
1735 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:267
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define MAXDIM
Definition: array.h:75
#define AARR_LBOUND(a)
Definition: array.h:334
#define AARR_NDIM(a)
Definition: array.h:321
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ array_lt()

Datum array_lt ( PG_FUNCTION_ARGS  )

Definition at line 3739 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3740 {
3741  PG_RETURN_BOOL(array_cmp(fcinfo) < 0);
3742 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3775
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

◆ array_map()

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

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

3161 {
3162  AnyArrayType *v = DatumGetAnyArrayP(arrayd);
3163  ArrayType *result;
3164  Datum *values;
3165  bool *nulls;
3166  int *dim;
3167  int ndim;
3168  int nitems;
3169  int i;
3170  int32 nbytes = 0;
3171  int32 dataoffset;
3172  bool hasnulls;
3173  Oid inpType;
3174  int inp_typlen;
3175  bool inp_typbyval;
3176  char inp_typalign;
3177  int typlen;
3178  bool typbyval;
3179  char typalign;
3180  array_iter iter;
3181  ArrayMetaState *inp_extra;
3182  ArrayMetaState *ret_extra;
3183  Datum *transform_source = exprstate->innermost_caseval;
3184  bool *transform_source_isnull = exprstate->innermost_casenull;
3185 
3186  inpType = AARR_ELEMTYPE(v);
3187  ndim = AARR_NDIM(v);
3188  dim = AARR_DIMS(v);
3189  nitems = ArrayGetNItems(ndim, dim);
3190 
3191  /* Check for empty array */
3192  if (nitems <= 0)
3193  {
3194  /* Return empty array */
3195  return PointerGetDatum(construct_empty_array(retType));
3196  }
3197 
3198  /*
3199  * We arrange to look up info about input and return element types only
3200  * once per series of calls, assuming the element type doesn't change
3201  * underneath us.
3202  */
3203  inp_extra = &amstate->inp_extra;
3204  ret_extra = &amstate->ret_extra;
3205 
3206  if (inp_extra->element_type != inpType)
3207  {
3208  get_typlenbyvalalign(inpType,
3209  &inp_extra->typlen,
3210  &inp_extra->typbyval,
3211  &inp_extra->typalign);
3212  inp_extra->element_type = inpType;
3213  }
3214  inp_typlen = inp_extra->typlen;
3215  inp_typbyval = inp_extra->typbyval;
3216  inp_typalign = inp_extra->typalign;
3217 
3218  if (ret_extra->element_type != retType)
3219  {
3220  get_typlenbyvalalign(retType,
3221  &ret_extra->typlen,
3222  &ret_extra->typbyval,
3223  &ret_extra->typalign);
3224  ret_extra->element_type = retType;
3225  }
3226  typlen = ret_extra->typlen;
3227  typbyval = ret_extra->typbyval;
3228  typalign = ret_extra->typalign;
3229 
3230  /* Allocate temporary arrays for new values */
3231  values = (Datum *) palloc(nitems * sizeof(Datum));
3232  nulls = (bool *) palloc(nitems * sizeof(bool));
3233 
3234  /* Loop over source data */
3235  array_iter_setup(&iter, v);
3236  hasnulls = false;
3237 
3238  for (i = 0; i < nitems; i++)
3239  {
3240  /* Get source element, checking for NULL */
3241  *transform_source =
3242  array_iter_next(&iter, transform_source_isnull, i,
3243  inp_typlen, inp_typbyval, inp_typalign);
3244 
3245  /* Apply the given expression to source element */
3246  values[i] = ExecEvalExpr(exprstate, econtext, &nulls[i]);
3247 
3248  if (nulls[i])
3249  hasnulls = true;
3250  else
3251  {
3252  /* Ensure data is not toasted */
3253  if (typlen == -1)
3254  values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
3255  /* Update total result size */
3256  nbytes = att_addlength_datum(nbytes, typlen, values[i]);
3257  nbytes = att_align_nominal(nbytes, typalign);
3258  /* check for overflow of total request */
3259  if (!AllocSizeIsValid(nbytes))
3260  ereport(ERROR,
3261  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3262  errmsg("array size exceeds the maximum allowed (%d)",
3263  (int) MaxAllocSize)));
3264  }
3265  }
3266 
3267  /* Allocate and fill the result array */
3268  if (hasnulls)
3269  {
3270  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3271  nbytes += dataoffset;
3272  }
3273  else
3274  {
3275  dataoffset = 0; /* marker for no null bitmap */
3276  nbytes += ARR_OVERHEAD_NONULLS(ndim);
3277  }
3278  result = (ArrayType *) palloc0(nbytes);
3279  SET_VARSIZE(result, nbytes);
3280  result->ndim = ndim;
3281  result->dataoffset = dataoffset;
3282  result->elemtype = retType;
3283  memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
3284  memcpy(ARR_LBOUND(result), AARR_LBOUND(v), ndim * sizeof(int));
3285 
3286  CopyArrayEls(result,
3287  values, nulls, nitems,
3288  typlen, typbyval, typalign,
3289  false);
3290 
3291  /*
3292  * Note: do not risk trying to pfree the results of the called expression
3293  */
3294  pfree(values);
3295  pfree(nulls);
3296 
3297  return PointerGetDatum(result);
3298 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
#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:2218
#define PointerGetDatum(X)
Definition: postgres.h:600
bool * innermost_casenull
Definition: execnodes.h:112
int32 dataoffset
Definition: array.h:89
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
int errcode(int sqlerrcode)
Definition: elog.c:698
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3439
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
signed int int32
Definition: c.h:429
AnyArrayType * DatumGetAnyArrayP(Datum d)
#define ARR_LBOUND(a)
Definition: array.h:289
bool typbyval
Definition: array.h:233
void pfree(void *pointer)
Definition: mcxt.c:1169
char typalign
Definition: pg_type.h:176
#define ERROR
Definition: elog.h:46
Oid elemtype
Definition: array.h:90
#define ARR_DIMS(a)
Definition: array.h:287
ArrayMetaState inp_extra
Definition: array.h:246
int16 typlen
Definition: array.h:232
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:316
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:1093
uintptr_t Datum
Definition: postgres.h:411
#define AARR_DIMS(a)
Definition: array.h:331
#define AARR_ELEMTYPE(a)
Definition: array.h:328
#define ereport(elevel,...)
Definition: elog.h:157
#define AARR_LBOUND(a)
Definition: array.h:334
#define AARR_NDIM(a)
Definition: array.h:321
ArrayMetaState ret_extra
Definition: array.h:247
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:960
char typalign
Definition: array.h:234
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:164
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
Oid element_type
Definition: array.h:231
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:342
int ndim
Definition: array.h:88

◆ array_ndims()

Datum array_ndims ( PG_FUNCTION_ARGS  )

Definition at line 1662 of file arrayfuncs.c.

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

1663 {
1665 
1666  /* Sanity check: does it look like an array at all? */
1667  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1668  PG_RETURN_NULL();
1669 
1671 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:267
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define MAXDIM
Definition: array.h:75
#define AARR_NDIM(a)
Definition: array.h:321
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ array_ne()

Datum array_ne ( PG_FUNCTION_ARGS  )

Definition at line 3733 of file arrayfuncs.c.

References array_eq(), DatumGetBool, and PG_RETURN_BOOL.

3734 {
3736 }
#define DatumGetBool(X)
Definition: postgres.h:437
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
Datum array_eq(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:3604

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

References array_seek().

Referenced by array_copy(), and array_set_slice().

4671 {
4672  return array_seek(ptr, offset, nullbitmap, nitems,
4673  typlen, typbyval, typalign) - ptr;
4674 }
char typalign
Definition: pg_type.h:176
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4621

◆ array_out()

Datum array_out ( PG_FUNCTION_ARGS  )

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

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

◆ array_recv()

Datum array_recv ( PG_FUNCTION_ARGS  )

Definition at line 1270 of file arrayfuncs.c.

References ARR_DIMS, ARR_LBOUND, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ArrayCheckBounds(), ArrayGetNItems(), buf, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, ArrayMetaState::element_type, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, FirstGenbkiObjectId, fmgr_info_cxt(), FmgrInfo::fn_mcxt, FORMAT_TYPE_ALLOW_INVALID, format_type_be(), format_type_extended(), 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().

1271 {
1273  Oid spec_element_type = PG_GETARG_OID(1); /* type of an array
1274  * element */
1275  int32 typmod = PG_GETARG_INT32(2); /* typmod for array elements */
1276  Oid element_type;
1277  int typlen;
1278  bool typbyval;
1279  char typalign;
1280  Oid typioparam;
1281  int i,
1282  nitems;
1283  Datum *dataPtr;
1284  bool *nullsPtr;
1285  bool hasnulls;
1286  int32 nbytes;
1287  int32 dataoffset;
1288  ArrayType *retval;
1289  int ndim,
1290  flags,
1291  dim[MAXDIM],
1292  lBound[MAXDIM];
1293  ArrayMetaState *my_extra;
1294 
1295  /* Get the array header information */
1296  ndim = pq_getmsgint(buf, 4);
1297  if (ndim < 0) /* we do allow zero-dimension arrays */
1298  ereport(ERROR,
1299  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1300  errmsg("invalid number of dimensions: %d", ndim)));
1301  if (ndim > MAXDIM)
1302  ereport(ERROR,
1303  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1304  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
1305  ndim, MAXDIM)));
1306 
1307  flags = pq_getmsgint(buf, 4);
1308  if (flags != 0 && flags != 1)
1309  ereport(ERROR,
1310  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1311  errmsg("invalid array flags")));
1312 
1313  /* Check element type recorded in the data */
1314  element_type = pq_getmsgint(buf, sizeof(Oid));
1315 
1316  /*
1317  * From a security standpoint, it doesn't matter whether the input's
1318  * element type matches what we expect: the element type's receive
1319  * function has to be robust enough to cope with invalid data. However,
1320  * from a user-friendliness standpoint, it's nicer to complain about type
1321  * mismatches than to throw "improper binary format" errors. But there's
1322  * a problem: only built-in types have OIDs that are stable enough to
1323  * believe that a mismatch is a real issue. So complain only if both OIDs
1324  * are in the built-in range. Otherwise, carry on with the element type
1325  * we "should" be getting.
1326  */
1327  if (element_type != spec_element_type)
1328  {
1329  if (element_type < FirstGenbkiObjectId &&
1330  spec_element_type < FirstGenbkiObjectId)
1331  ereport(ERROR,
1332  (errcode(ERRCODE_DATATYPE_MISMATCH),
1333  errmsg("binary data has array element type %u (%s) instead of expected %u (%s)",
1334  element_type,
1335  format_type_extended(element_type, -1,
1337  spec_element_type,
1338  format_type_extended(spec_element_type, -1,
1340  element_type = spec_element_type;
1341  }
1342 
1343  for (i = 0; i < ndim; i++)
1344  {
1345  dim[i] = pq_getmsgint(buf, 4);
1346  lBound[i] = pq_getmsgint(buf, 4);
1347  }
1348 
1349  /* This checks for overflow of array dimensions */
1350  nitems = ArrayGetNItems(ndim, dim);
1351  ArrayCheckBounds(ndim, dim, lBound);
1352 
1353  /*
1354  * We arrange to look up info about element type, including its receive
1355  * conversion proc, only once per series of calls, assuming the element
1356  * type doesn't change underneath us.
1357  */
1358  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1359  if (my_extra == NULL)
1360  {
1361  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1362  sizeof(ArrayMetaState));
1363  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1364  my_extra->element_type = ~element_type;
1365  }
1366 
1367  if (my_extra->element_type != element_type)
1368  {
1369  /* Get info about element type, including its receive proc */
1370  get_type_io_data(element_type, IOFunc_receive,
1371  &my_extra->typlen, &my_extra->typbyval,
1372  &my_extra->typalign, &my_extra->typdelim,
1373  &my_extra->typioparam, &my_extra->typiofunc);
1374  if (!OidIsValid(my_extra->typiofunc))
1375  ereport(ERROR,
1376  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1377  errmsg("no binary input function available for type %s",
1378  format_type_be(element_type))));
1379  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1380  fcinfo->flinfo->fn_mcxt);
1381  my_extra->element_type = element_type;
1382  }
1383 
1384  if (nitems == 0)
1385  {
1386  /* Return empty array ... but not till we've validated element_type */
1388  }
1389 
1390  typlen = my_extra->typlen;
1391  typbyval = my_extra->typbyval;
1392  typalign = my_extra->typalign;
1393  typioparam = my_extra->typioparam;
1394 
1395  dataPtr = (Datum *) palloc(nitems * sizeof(Datum));
1396  nullsPtr = (bool *) palloc(nitems * sizeof(bool));
1397  ReadArrayBinary(buf, nitems,
1398  &my_extra->proc, typioparam, typmod,
1399  typlen, typbyval, typalign,
1400  dataPtr, nullsPtr,
1401  &hasnulls, &nbytes);
1402  if (hasnulls)
1403  {
1404  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
1405  nbytes += dataoffset;
1406  }
1407  else
1408  {
1409  dataoffset = 0; /* marker for no null bitmap */
1410  nbytes += ARR_OVERHEAD_NONULLS(ndim);
1411  }
1412  retval = (ArrayType *) palloc0(nbytes);
1413  SET_VARSIZE(retval, nbytes);
1414  retval->ndim = ndim;
1415  retval->dataoffset = dataoffset;
1416  retval->elemtype = element_type;
1417  memcpy(ARR_DIMS(retval), dim, ndim * sizeof(int));
1418  memcpy(ARR_LBOUND(retval), lBound, ndim * sizeof(int));
1419 
1420  CopyArrayEls(retval,
1421  dataPtr, nullsPtr, nitems,
1422  typlen, typbyval, typalign,
1423  true);
1424 
1425  pfree(dataPtr);
1426  pfree(nullsPtr);
1427 
1428  PG_RETURN_ARRAYTYPE_P(retval);
1429 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
MemoryContext fn_mcxt
Definition: fmgr.h:65
int32 dataoffset
Definition: array.h:89
StringInfoData * StringInfo
Definition: stringinfo.h:44
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3439
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
signed int int32
Definition: c.h:429
#define ARR_LBOUND(a)
Definition: array.h:289
bool typbyval
Definition: array.h:233
void pfree(void *pointer)
Definition: mcxt.c:1169
char typalign
Definition: pg_type.h:176
#define ERROR
Definition: elog.h:46
Oid elemtype
Definition: array.h:90
#define ARR_DIMS(a)
Definition: array.h:287
int16 typlen
Definition: array.h:232
static char * buf
Definition: pg_test_fsync.c:68
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
char typdelim
Definition: array.h:235
#define MAXDIM
Definition: array.h:75
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:258
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:1453
void ArrayCheckBounds(int ndim, const int *dims, const int *lb)
Definition: arrayutils.c:128
#define FORMAT_TYPE_ALLOW_INVALID
Definition: builtins.h:109
void * palloc0(Size size)
Definition: mcxt.c:1093
uintptr_t Datum
Definition: postgres.h:411
#define ereport(elevel,...)
Definition: elog.h:157
Oid typioparam
Definition: array.h:236
char * format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
Definition: format_type.c:112
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:960
Oid typiofunc
Definition: array.h:237
char typalign
Definition: array.h:234
#define FirstGenbkiObjectId
Definition: transam.h:195
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
FmgrInfo proc
Definition: array.h:238
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
int i
Oid element_type
Definition: array.h:231
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:342
int ndim
Definition: array.h:88
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:2272

◆ array_ref()

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

Definition at line 3103 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3106 {
3107  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3108  arraytyplen, elmlen, elmbyval, elmalign,
3109  isNull);
3110 }
#define PointerGetDatum(X)
Definition: postgres.h:600
Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1830

◆ array_remove()

Datum array_remove ( PG_FUNCTION_ARGS  )

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

6366 {
6367  ArrayType *array;
6368  Datum search = PG_GETARG_DATUM(1);
6369  bool search_isnull = PG_ARGISNULL(1);
6370 
6371  if (PG_ARGISNULL(0))
6372  PG_RETURN_NULL();
6373  array = PG_GETARG_ARRAYTYPE_P(0);
6374 
6375  array = array_replace_internal(array,
6376  search, search_isnull,
6377  (Datum) 0, true,
6378  true, PG_GET_COLLATION(),
6379  fcinfo);
6380  PG_RETURN_ARRAYTYPE_P(array);
6381 }
#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:256
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:258
uintptr_t Datum
Definition: postgres.h:411
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:6107
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ array_replace()

Datum array_replace ( PG_FUNCTION_ARGS  )

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

6388 {
6389  ArrayType *array;
6390  Datum search = PG_GETARG_DATUM(1);
6391  bool search_isnull = PG_ARGISNULL(1);
6392  Datum replace = PG_GETARG_DATUM(2);
6393  bool replace_isnull = PG_ARGISNULL(2);
6394 
6395  if (PG_ARGISNULL(0))
6396  PG_RETURN_NULL();
6397  array = PG_GETARG_ARRAYTYPE_P(0);
6398 
6399  array = array_replace_internal(array,
6400  search, search_isnull,
6401  replace, replace_isnull,
6402  false, PG_GET_COLLATION(),
6403  fcinfo);
6404  PG_RETURN_ARRAYTYPE_P(array);
6405 }
#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:256
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:258
uintptr_t Datum
Definition: postgres.h:411
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:6107
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_RETURN_NULL()
Definition: fmgr.h:345

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

6112 {
6113  LOCAL_FCINFO(locfcinfo, 2);
6114  ArrayType *result;
6115  Oid element_type;
6116  Datum *values;
6117  bool *nulls;
6118  int *dim;
6119  int ndim;
6120  int nitems,
6121  nresult;
6122  int i;
6123  int32 nbytes = 0;
6124  int32 dataoffset;
6125  bool hasnulls;
6126  int typlen;
6127  bool typbyval;
6128  char typalign;
6129  char *arraydataptr;
6130  bits8 *bitmap;
6131  int bitmask;
6132  bool changed = false;
6133  TypeCacheEntry *typentry;
6134 
6135  element_type = ARR_ELEMTYPE(array);
6136  ndim = ARR_NDIM(array);
6137  dim = ARR_DIMS(array);
6138  nitems = ArrayGetNItems(ndim, dim);
6139 
6140  /* Return input array unmodified if it is empty */
6141  if (nitems <= 0)
6142  return array;
6143 
6144  /*
6145  * We can't remove elements from multi-dimensional arrays, since the
6146  * result might not be rectangular.
6147  */
6148  if (remove && ndim > 1)
6149  ereport(ERROR,
6150  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6151  errmsg("removing elements from multidimensional arrays is not supported")));
6152 
6153  /*
6154  * We arrange to look up the equality function only once per series of
6155  * calls, assuming the element type doesn't change underneath us.
6156  */
6157  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
6158  if (typentry == NULL ||
6159  typentry->type_id != element_type)
6160  {
6161  typentry = lookup_type_cache(element_type,
6163  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
6164  ereport(ERROR,
6165  (errcode(ERRCODE_UNDEFINED_FUNCTION),
6166  errmsg("could not identify an equality operator for type %s",
6167  format_type_be(element_type))));
6168  fcinfo->flinfo->fn_extra = (void *) typentry;
6169  }
6170  typlen = typentry->typlen;
6171  typbyval = typentry->typbyval;
6172  typalign = typentry->typalign;
6173 
6174  /*
6175  * Detoast values if they are toasted. The replacement value must be
6176  * detoasted for insertion into the result array, while detoasting the
6177  * search value only once saves cycles.
6178  */
6179  if (typlen == -1)
6180  {
6181  if (!search_isnull)
6182  search = PointerGetDatum(PG_DETOAST_DATUM(search));
6183  if (!replace_isnull)
6184  replace = PointerGetDatum(PG_DETOAST_DATUM(replace));
6185  }
6186 
6187  /* Prepare to apply the comparison operator */
6188  InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
6189  collation, NULL, NULL);
6190 
6191  /* Allocate temporary arrays for new values */
6192  values = (Datum *) palloc(nitems * sizeof(Datum));
6193  nulls = (bool *) palloc(nitems * sizeof(bool));
6194 
6195  /* Loop over source data */
6196  arraydataptr = ARR_DATA_PTR(array);
6197  bitmap = ARR_NULLBITMAP(array);
6198  bitmask = 1;
6199  hasnulls = false;
6200  nresult = 0;
6201 
6202  for (i = 0; i < nitems; i++)
6203  {
6204  Datum elt;
6205  bool isNull;
6206  bool oprresult;
6207  bool skip = false;
6208 
6209  /* Get source element, checking for NULL */
6210  if (bitmap && (*bitmap & bitmask) == 0)
6211  {
6212  isNull = true;
6213  /* If searching for NULL, we have a match */
6214  if (search_isnull)
6215  {
6216  if (remove)
6217  {
6218  skip = true;
6219  changed = true;
6220  }
6221  else if (!replace_isnull)
6222  {
6223  values[nresult] = replace;
6224  isNull = false;
6225  changed = true;
6226  }
6227  }
6228  }
6229  else
6230  {
6231  isNull = false;
6232  elt = fetch_att(arraydataptr, typbyval, typlen);
6233  arraydataptr = att_addlength_datum(arraydataptr, typlen, elt);
6234  arraydataptr = (char *) att_align_nominal(arraydataptr, typalign);
6235 
6236  if (search_isnull)
6237  {
6238  /* no match possible, keep element */
6239  values[nresult] = elt;
6240  }
6241  else
6242  {
6243  /*
6244  * Apply the operator to the element pair; treat NULL as false
6245  */
6246  locfcinfo->args[0].value = elt;
6247  locfcinfo->args[0].isnull = false;
6248  locfcinfo->args[1].value = search;
6249  locfcinfo->args[1].isnull = false;
6250  locfcinfo->isnull = false;
6251  oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
6252  if (locfcinfo->isnull || !oprresult)
6253  {
6254  /* no match, keep element */
6255  values[nresult] = elt;
6256  }
6257  else
6258  {
6259  /* match, so replace or delete */
6260  changed = true;
6261  if (remove)
6262  skip = true;
6263  else
6264  {
6265  values[nresult] = replace;
6266  isNull = replace_isnull;
6267  }
6268  }
6269  }
6270  }
6271 
6272  if (!skip)
6273  {
6274  nulls[nresult] = isNull;
6275  if (isNull)
6276  hasnulls = true;
6277  else
6278  {
6279  /* Update total result size */
6280  nbytes = att_addlength_datum(nbytes, typlen, values[nresult]);
6281  nbytes = att_align_nominal(nbytes, typalign);
6282  /* check for overflow of total request */
6283  if (!AllocSizeIsValid(nbytes))
6284  ereport(ERROR,
6285  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
6286  errmsg("array size exceeds the maximum allowed (%d)",
6287  (int) MaxAllocSize)));
6288  }
6289  nresult++;
6290  }
6291 
6292  /* advance bitmap pointer if any */
6293  if (bitmap)
6294  {
6295  bitmask <<= 1;
6296  if (bitmask == 0x100)
6297  {
6298  bitmap++;
6299  bitmask = 1;
6300  }
6301  }
6302  }
6303 
6304  /*
6305  * If not changed just return the original array
6306  */
6307  if (!changed)
6308  {
6309  pfree(values);
6310  pfree(nulls);
6311  return array;
6312  }
6313 
6314  /* If all elements were removed return an empty array */
6315  if (nresult == 0)
6316  {
6317  pfree(values);
6318  pfree(nulls);
6319  return construct_empty_array(element_type);
6320  }
6321 
6322  /* Allocate and initialize the result array */
6323  if (hasnulls)
6324  {
6325  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nresult);
6326  nbytes += dataoffset;
6327  }
6328  else
6329  {
6330  dataoffset = 0; /* marker for no null bitmap */
6331  nbytes += ARR_OVERHEAD_NONULLS(ndim);
6332  }
6333  result = (ArrayType *) palloc0(nbytes);
6334  SET_VARSIZE(result, nbytes);
6335  result->ndim = ndim;
6336  result->dataoffset = dataoffset;
6337  result->elemtype = element_type;
6338  memcpy(ARR_DIMS(result), ARR_DIMS(array), ndim * sizeof(int));
6339  memcpy(ARR_LBOUND(result), ARR_LBOUND(array), ndim * sizeof(int));
6340 
6341  if (remove)
6342  {
6343  /* Adjust the result length */
6344  ARR_DIMS(result)[0] = nresult;
6345  }
6346 
6347  /* Insert data into result array */
6348  CopyArrayEls(result,
6349  values, nulls, nresult,
6350  typlen, typbyval, typalign,
6351  false);
6352 
6353  pfree(values);
6354  pfree(nulls);
6355 
6356  return result;
6357 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
#define PointerGetDatum(X)
Definition: postgres.h:600
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:141
int32 dataoffset
Definition: array.h:89
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:116
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3439
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:710
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
signed int int32
Definition: c.h:429
#define ARR_LBOUND(a)
Definition: array.h:289
void pfree(void *pointer)
Definition: mcxt.c:1169
char typalign
Definition: pg_type.h:176
#define ERROR
Definition: elog.h:46
Oid elemtype
Definition: array.h:90
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
#define DatumGetBool(X)
Definition: postgres.h:437
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
uint8 bits8
Definition: c.h:448
void * palloc0(Size size)
Definition: mcxt.c:1093
uintptr_t Datum
Definition: postgres.h:411
FmgrInfo * flinfo
Definition: fmgr.h:87
FmgrInfo eq_opr_finfo
Definition: typcache.h:75
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:339
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:157
#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:283
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:960
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#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:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
#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:342
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_NULLBITMAP(a)
Definition: array.h:293
int ndim
Definition: array.h:88

◆ array_seek()

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

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

4623 {
4624  int bitmask;
4625  int i;
4626 
4627  /* easy if fixed-size elements and no NULLs */
4628  if (typlen > 0 && !nullbitmap)
4629  return ptr + nitems * ((Size) att_align_nominal(typlen, typalign));
4630 
4631  /* seems worth having separate loops for NULL and no-NULLs cases */
4632  if (nullbitmap)
4633  {
4634  nullbitmap += offset / 8;
4635  bitmask = 1 << (offset % 8);
4636 
4637  for (i = 0; i < nitems; i++)
4638  {
4639  if (*nullbitmap & bitmask)
4640  {
4641  ptr = att_addlength_pointer(ptr, typlen, ptr);
4642  ptr = (char *) att_align_nominal(ptr, typalign);
4643  }
4644  bitmask <<= 1;
4645  if (bitmask == 0x100)
4646  {
4647  nullbitmap++;
4648  bitmask = 1;
4649  }
4650  }
4651  }
4652  else
4653  {
4654  for (i = 0; i < nitems; i++)
4655  {
4656  ptr = att_addlength_pointer(ptr, typlen, ptr);
4657  ptr = (char *) att_align_nominal(ptr, typalign);
4658  }
4659  }
4660  return ptr;
4661 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
char typalign
Definition: pg_type.h:176
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:176
size_t Size
Definition: c.h:540
int i

◆ array_send()

Datum array_send ( PG_FUNCTION_ARGS  )

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

1559 {
1561  Oid element_type = AARR_ELEMTYPE(v);
1562  int typlen;
1563  bool typbyval;
1564  char typalign;
1565  int nitems,
1566  i;
1567  int ndim,
1568  *dim,
1569  *lb;
1571  array_iter iter;
1572  ArrayMetaState *my_extra;
1573 
1574  /*
1575  * We arrange to look up info about element type, including its send
1576  * conversion proc, only once per series of calls, assuming the element
1577  * type doesn't change underneath us.
1578  */
1579  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1580  if (my_extra == NULL)
1581  {
1582  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1583  sizeof(ArrayMetaState));
1584  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1585  my_extra->element_type = ~element_type;
1586  }
1587 
1588  if (my_extra->element_type != element_type)
1589  {
1590  /* Get info about element type, including its send proc */
1591  get_type_io_data(element_type, IOFunc_send,
1592  &my_extra->typlen, &my_extra->typbyval,
1593  &my_extra->typalign, &my_extra->typdelim,
1594  &my_extra->typioparam, &my_extra->typiofunc);
1595  if (!OidIsValid(my_extra->typiofunc))
1596  ereport(ERROR,
1597  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1598  errmsg("no binary output function available for type %s",
1599  format_type_be(element_type))));
1600  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1601  fcinfo->flinfo->fn_mcxt);
1602  my_extra->element_type = element_type;
1603  }
1604  typlen = my_extra->typlen;
1605  typbyval = my_extra->typbyval;
1606  typalign = my_extra->typalign;
1607 
1608  ndim = AARR_NDIM(v);
1609  dim = AARR_DIMS(v);
1610  lb = AARR_LBOUND(v);
1611  nitems = ArrayGetNItems(ndim, dim);
1612 
1613  pq_begintypsend(&buf);
1614 
1615  /* Send the array header information */
1616  pq_sendint32(&buf, ndim);
1617  pq_sendint32(&buf, AARR_HASNULL(v) ? 1 : 0);
1618  pq_sendint32(&buf, element_type);
1619  for (i = 0; i < ndim; i++)
1620  {
1621  pq_sendint32(&buf, dim[i]);
1622  pq_sendint32(&buf, lb[i]);
1623  }
1624 
1625  /* Send the array elements using the element's own sendproc */
1626  array_iter_setup(&iter, v);
1627 
1628  for (i = 0; i < nitems; i++)
1629  {
1630  Datum itemvalue;
1631  bool isnull;
1632 
1633  /* Get source element, checking for NULL */
1634  itemvalue = array_iter_next(&iter, &isnull, i,
1635  typlen, typbyval, typalign);
1636 
1637  if (isnull)
1638  {
1639  /* -1 length means a NULL */
1640  pq_sendint32(&buf, -1);
1641  }
1642  else
1643  {
1644  bytea *outputbytes;
1645 
1646  outputbytes = SendFunctionCall(&my_extra->proc, itemvalue);
1647  pq_sendint32(&buf, VARSIZE(outputbytes) - VARHDRSZ);
1648  pq_sendbytes(&buf, VARDATA(outputbytes),
1649  VARSIZE(outputbytes) - VARHDRSZ);
1650  pfree(outputbytes);
1651  }
1652  }
1653 
1655 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:267
#define VARDATA(PTR)
Definition: postgres.h:315
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define VARSIZE(PTR)
Definition: postgres.h:316
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:627
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
#define AARR_HASNULL(a)
Definition: array.h:324
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
bool typbyval
Definition: array.h:233
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
void pfree(void *pointer)
Definition: mcxt.c:1169
char typalign
Definition: pg_type.h:176
#define ERROR
Definition: elog.h:46
int16 typlen
Definition: array.h:232
static char * buf
Definition: pg_test_fsync.c:68
char typdelim
Definition: array.h:235
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1634
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
uintptr_t Datum
Definition: postgres.h:411
#define AARR_DIMS(a)
Definition: array.h:331
#define AARR_ELEMTYPE(a)
Definition: array.h:328
#define ereport(elevel,...)
Definition: elog.h:157
#define AARR_LBOUND(a)
Definition: array.h:334
Oid typioparam
Definition: array.h:236
#define AARR_NDIM(a)
Definition: array.h:321
Oid typiofunc
Definition: array.h:237
char typalign
Definition: array.h:234
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
int errmsg(const char *fmt,...)
Definition: elog.c:909
FmgrInfo proc
Definition: array.h:238
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
int i
Oid element_type
Definition: array.h:231
Definition: c.h:621
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:2272

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

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3123 {
3125  nSubscripts, indx,
3126  dataValue, isNull,
3127  arraytyplen,
3128  elmlen, elmbyval, elmalign));
3129 }
#define PointerGetDatum(X)
Definition: postgres.h:600
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:2211
#define DatumGetArrayTypeP(X)
Definition: array.h:254

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

Referenced by array_append(), array_prepend(), array_set(), and array_subscript_assign().

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

◆ 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