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/fmgroids.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 49 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 47 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 55 of file arrayfuncs.c.

Function Documentation

◆ accumArrayResult()

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

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

5126 {
5127  MemoryContext oldcontext;
5128 
5129  if (astate == NULL)
5130  {
5131  /* First time through --- initialize */
5132  astate = initArrayResult(element_type, rcontext, true);
5133  }
5134  else
5135  {
5136  Assert(astate->element_type == element_type);
5137  }
5138 
5139  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5140 
5141  /* enlarge dvalues[]/dnulls[] if needed */
5142  if (astate->nelems >= astate->alen)
5143  {
5144  astate->alen *= 2;
5145  astate->dvalues = (Datum *)
5146  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5147  astate->dnulls = (bool *)
5148  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5149  }
5150 
5151  /*
5152  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5153  * it's varlena. (You might think that detoasting is not needed here
5154  * because construct_md_array can detoast the array elements later.
5155  * However, we must not let construct_md_array modify the ArrayBuildState
5156  * because that would mean array_agg_finalfn damages its input, which is
5157  * verboten. Also, this way frequently saves one copying step.)
5158  */
5159  if (!disnull && !astate->typbyval)
5160  {
5161  if (astate->typlen == -1)
5162  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5163  else
5164  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5165  }
5166 
5167  astate->dvalues[astate->nelems] = dvalue;
5168  astate->dnulls[astate->nelems] = disnull;
5169  astate->nelems++;
5170 
5171  MemoryContextSwitchTo(oldcontext);
5172 
5173  return astate;
5174 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5083
#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 5593 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5597 {
5598  if (astate == NULL)
5599  astate = initArrayResultAny(input_type, rcontext, true);
5600 
5601  if (astate->scalarstate)
5602  (void) accumArrayResult(astate->scalarstate,
5603  dvalue, disnull,
5604  input_type, rcontext);
5605  else
5606  (void) accumArrayResultArr(astate->arraystate,
5607  dvalue, disnull,
5608  input_type, rcontext);
5609 
5610  return astate;
5611 }
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5548
ArrayBuildState * scalarstate
Definition: array.h:222
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5316
ArrayBuildStateArr * arraystate
Definition: array.h:223
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5122

◆ accumArrayResultArr()

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

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

5320 {
5321  ArrayType *arg;
5322  MemoryContext oldcontext;
5323  int *dims,
5324  *lbs,
5325  ndims,
5326  nitems,
5327  ndatabytes;
5328  char *data;
5329  int i;
5330 
5331  /*
5332  * We disallow accumulating null subarrays. Another plausible definition
5333  * is to ignore them, but callers that want that can just skip calling
5334  * this function.
5335  */
5336  if (disnull)
5337  ereport(ERROR,
5338  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5339  errmsg("cannot accumulate null arrays")));
5340 
5341  /* Detoast input array in caller's context */
5342  arg = DatumGetArrayTypeP(dvalue);
5343 
5344  if (astate == NULL)
5345  astate = initArrayResultArr(array_type, InvalidOid, rcontext, true);
5346  else
5347  Assert(astate->array_type == array_type);
5348 
5349  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5350 
5351  /* Collect this input's dimensions */
5352  ndims = ARR_NDIM(arg);
5353  dims = ARR_DIMS(arg);
5354  lbs = ARR_LBOUND(arg);
5355  data = ARR_DATA_PTR(arg);
5356  nitems = ArrayGetNItems(ndims, dims);
5357  ndatabytes = ARR_SIZE(arg) - ARR_DATA_OFFSET(arg);
5358 
5359  if (astate->ndims == 0)
5360  {
5361  /* First input; check/save the dimensionality info */
5362 
5363  /* Should we allow empty inputs and just produce an empty output? */
5364  if (ndims == 0)
5365  ereport(ERROR,
5366  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5367  errmsg("cannot accumulate empty arrays")));
5368  if (ndims + 1 > MAXDIM)
5369  ereport(ERROR,
5370  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5371  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5372  ndims + 1, MAXDIM)));
5373 
5374  /*
5375  * The output array will have n+1 dimensions, with the ones after the
5376  * first matching the input's dimensions.
5377  */
5378  astate->ndims = ndims + 1;
5379  astate->dims[0] = 0;
5380  memcpy(&astate->dims[1], dims, ndims * sizeof(int));
5381  astate->lbs[0] = 1;
5382  memcpy(&astate->lbs[1], lbs, ndims * sizeof(int));
5383 
5384  /* Allocate at least enough data space for this item */
5385  astate->abytes = pg_nextpower2_32(Max(1024, ndatabytes + 1));
5386  astate->data = (char *) palloc(astate->abytes);
5387  }
5388  else
5389  {
5390  /* Second or later input: must match first input's dimensionality */
5391  if (astate->ndims != ndims + 1)
5392  ereport(ERROR,
5393  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5394  errmsg("cannot accumulate arrays of different dimensionality")));
5395  for (i = 0; i < ndims; i++)
5396  {
5397  if (astate->dims[i + 1] != dims[i] || astate->lbs[i + 1] != lbs[i])
5398  ereport(ERROR,
5399  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5400  errmsg("cannot accumulate arrays of different dimensionality")));
5401  }
5402 
5403  /* Enlarge data space if needed */
5404  if (astate->nbytes + ndatabytes > astate->abytes)
5405  {
5406  astate->abytes = Max(astate->abytes * 2,
5407  astate->nbytes + ndatabytes);
5408  astate->data = (char *) repalloc(astate->data, astate->abytes);
5409  }
5410  }
5411 
5412  /*
5413  * Copy the data portion of the sub-array. Note we assume that the
5414  * advertised data length of the sub-array is properly aligned. We do not
5415  * have to worry about detoasting elements since whatever's in the
5416  * sub-array should be OK already.
5417  */
5418  memcpy(astate->data + astate->nbytes, data, ndatabytes);
5419  astate->nbytes += ndatabytes;
5420 
5421  /* Deal with null bitmap if needed */
5422  if (astate->nullbitmap || ARR_HASNULL(arg))
5423  {
5424  int newnitems = astate->nitems + nitems;
5425 
5426  if (astate->nullbitmap == NULL)
5427  {
5428  /*
5429  * First input with nulls; we must retrospectively handle any
5430  * previous inputs by marking all their items non-null.
5431  */
5432  astate->aitems = pg_nextpower2_32(Max(256, newnitems + 1));
5433  astate->nullbitmap = (bits8 *) palloc((astate->aitems + 7) / 8);
5434  array_bitmap_copy(astate->nullbitmap, 0,
5435  NULL, 0,
5436  astate->nitems);
5437  }
5438  else if (newnitems > astate->aitems)
5439  {
5440  astate->aitems = Max(astate->aitems * 2, newnitems);
5441  astate->nullbitmap = (bits8 *)
5442  repalloc(astate->nullbitmap, (astate->aitems + 7) / 8);
5443  }
5444  array_bitmap_copy(astate->nullbitmap, astate->nitems,
5445  ARR_NULLBITMAP(arg), 0,
5446  nitems);
5447  }
5448 
5449  astate->nitems += nitems;
5450  astate->dims[0] += 1;
5451 
5452  MemoryContextSwitchTo(oldcontext);
5453 
5454  /* Release detoasted copy if any */
5455  if ((Pointer) arg != DatumGetPointer(dvalue))
5456  pfree(arg);
5457 
5458  return astate;
5459 }
#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:4756
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:5270
#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 4756 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().

4759 {
4760  int destbitmask,
4761  destbitval,
4762  srcbitmask,
4763  srcbitval;
4764 
4765  Assert(destbitmap);
4766  if (nitems <= 0)
4767  return; /* don't risk fetch off end of memory */
4768  destbitmap += destoffset / 8;
4769  destbitmask = 1 << (destoffset % 8);
4770  destbitval = *destbitmap;
4771  if (srcbitmap)
4772  {
4773  srcbitmap += srcoffset / 8;
4774  srcbitmask = 1 << (srcoffset % 8);
4775  srcbitval = *srcbitmap;
4776  while (nitems-- > 0)
4777  {
4778  if (srcbitval & srcbitmask)
4779  destbitval |= destbitmask;
4780  else
4781  destbitval &= ~destbitmask;
4782  destbitmask <<= 1;
4783  if (destbitmask == 0x100)
4784  {
4785  *destbitmap++ = destbitval;
4786  destbitmask = 1;
4787  if (nitems > 0)
4788  destbitval = *destbitmap;
4789  }
4790  srcbitmask <<= 1;
4791  if (srcbitmask == 0x100)
4792  {
4793  srcbitmap++;
4794  srcbitmask = 1;
4795  if (nitems > 0)
4796  srcbitval = *srcbitmap;
4797  }
4798  }
4799  if (destbitmask != 1)
4800  *destbitmap = destbitval;
4801  }
4802  else
4803  {
4804  while (nitems-- > 0)
4805  {
4806  destbitval |= destbitmask;
4807  destbitmask <<= 1;
4808  if (destbitmask == 0x100)
4809  {
4810  *destbitmap++ = destbitval;
4811  destbitmask = 1;
4812  if (nitems > 0)
4813  destbitval = *destbitmap;
4814  }
4815  }
4816  if (destbitmask != 1)
4817  *destbitmap = destbitval;
4818  }
4819 }
#define Assert(condition)
Definition: c.h:804

◆ array_cardinality()

Datum array_cardinality ( PG_FUNCTION_ARGS  )

Definition at line 1801 of file arrayfuncs.c.

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

1802 {
1804 
1806 }
#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 3776 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().

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

4173 {
4174  LOCAL_FCINFO(locfcinfo, 2);
4175  bool result = matchall;
4176  Oid element_type = AARR_ELEMTYPE(array1);
4177  TypeCacheEntry *typentry;
4178  int nelems1;
4179  Datum *values2;
4180  bool *nulls2;
4181  int nelems2;
4182  int typlen;
4183  bool typbyval;
4184  char typalign;
4185  int i;
4186  int j;
4187  array_iter it1;
4188 
4189  if (element_type != AARR_ELEMTYPE(array2))
4190  ereport(ERROR,
4191  (errcode(ERRCODE_DATATYPE_MISMATCH),
4192  errmsg("cannot compare arrays of different element types")));
4193 
4194  /*
4195  * We arrange to look up the equality function only once per series of
4196  * calls, assuming the element type doesn't change underneath us. The
4197  * typcache is used so that we have no memory leakage when being used as
4198  * an index support function.
4199  */
4200  typentry = (TypeCacheEntry *) *fn_extra;
4201  if (typentry == NULL ||
4202  typentry->type_id != element_type)
4203  {
4204  typentry = lookup_type_cache(element_type,
4206  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
4207  ereport(ERROR,
4208  (errcode(ERRCODE_UNDEFINED_FUNCTION),
4209  errmsg("could not identify an equality operator for type %s",
4210  format_type_be(element_type))));
4211  *fn_extra = (void *) typentry;
4212  }
4213  typlen = typentry->typlen;
4214  typbyval = typentry->typbyval;
4215  typalign = typentry->typalign;
4216 
4217  /*
4218  * Since we probably will need to scan array2 multiple times, it's
4219  * worthwhile to use deconstruct_array on it. We scan array1 the hard way
4220  * however, since we very likely won't need to look at all of it.
4221  */
4222  if (VARATT_IS_EXPANDED_HEADER(array2))
4223  {
4224  /* This should be safe even if input is read-only */
4225  deconstruct_expanded_array(&(array2->xpn));
4226  values2 = array2->xpn.dvalues;
4227  nulls2 = array2->xpn.dnulls;
4228  nelems2 = array2->xpn.nelems;
4229  }
4230  else
4231  deconstruct_array((ArrayType *) array2,
4232  element_type, typlen, typbyval, typalign,
4233  &values2, &nulls2, &nelems2);
4234 
4235  /*
4236  * Apply the comparison operator to each pair of array elements.
4237  */
4238  InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
4239  collation, NULL, NULL);
4240 
4241  /* Loop over source data */
4242  nelems1 = ArrayGetNItems(AARR_NDIM(array1), AARR_DIMS(array1));
4243  array_iter_setup(&it1, array1);
4244 
4245  for (i = 0; i < nelems1; i++)
4246  {
4247  Datum elt1;
4248  bool isnull1;
4249 
4250  /* Get element, checking for NULL */
4251  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
4252 
4253  /*
4254  * We assume that the comparison operator is strict, so a NULL can't
4255  * match anything. XXX this diverges from the "NULL=NULL" behavior of
4256  * array_eq, should we act like that?
4257  */
4258  if (isnull1)
4259  {
4260  if (matchall)
4261  {
4262  result = false;
4263  break;
4264  }
4265  continue;
4266  }
4267 
4268  for (j = 0; j < nelems2; j++)
4269  {
4270  Datum elt2 = values2[j];
4271  bool isnull2 = nulls2 ? nulls2[j] : false;
4272  bool oprresult;
4273 
4274  if (isnull2)
4275  continue; /* can't match */
4276 
4277  /*
4278  * Apply the operator to the element pair; treat NULL as false
4279  */
4280  locfcinfo->args[0].value = elt1;
4281  locfcinfo->args[0].isnull = false;
4282  locfcinfo->args[1].value = elt2;
4283  locfcinfo->args[1].isnull = false;
4284  locfcinfo->isnull = false;
4285  oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
4286  if (!locfcinfo->isnull && oprresult)
4287  break;
4288  }
4289 
4290  if (j < nelems2)
4291  {
4292  /* found a match for elt1 */
4293  if (!matchall)
4294  {
4295  result = true;
4296  break;
4297  }
4298  }
4299  else
4300  {
4301  /* no match for elt1 */
4302  if (matchall)
4303  {
4304  result = false;
4305  break;
4306  }
4307  }
4308  }
4309 
4310  return result;
4311 }
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:3491
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 3558 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().

3559 {
3560  int nelems;
3561  bits8 *bitmap;
3562  int bitmask;
3563 
3564  /* Easy answer if there's no null bitmap */
3565  if (!ARR_HASNULL(array))
3566  return false;
3567 
3568  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3569 
3570  bitmap = ARR_NULLBITMAP(array);
3571 
3572  /* check whole bytes of the bitmap byte-at-a-time */
3573  while (nelems >= 8)
3574  {
3575  if (*bitmap != 0xFF)
3576  return true;
3577  bitmap++;
3578  nelems -= 8;
3579  }
3580 
3581  /* check last partial byte */
3582  bitmask = 1;
3583  while (nelems > 0)
3584  {
3585  if ((*bitmap & bitmask) == 0)
3586  return true;
3587  bitmask <<= 1;
3588  nelems--;
3589  }
3590 
3591  return false;
3592 }
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 4726 of file arrayfuncs.c.

References array_nelems_size().

Referenced by array_extract_slice(), and array_insert_slice().

4729 {
4730  int numbytes;
4731 
4732  numbytes = array_nelems_size(srcptr, offset, nullbitmap, nitems,
4733  typlen, typbyval, typalign);
4734  memcpy(destptr, srcptr, numbytes);
4735  return numbytes;
4736 }
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:4704

◆ array_create_iterator()

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

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

4388 {
4389  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4390 
4391  /*
4392  * Sanity-check inputs --- caller should have got this right already
4393  */
4394  Assert(PointerIsValid(arr));
4395  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4396  elog(ERROR, "invalid arguments to array_create_iterator");
4397 
4398  /*
4399  * Remember basic info about the array and its element type
4400  */
4401  iterator->arr = arr;
4402  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4403  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4404 
4405  if (mstate != NULL)
4406  {
4407  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4408 
4409  iterator->typlen = mstate->typlen;
4410  iterator->typbyval = mstate->typbyval;
4411  iterator->typalign = mstate->typalign;
4412  }
4413  else
4415  &iterator->typlen,
4416  &iterator->typbyval,
4417  &iterator->typalign);
4418 
4419  /*
4420  * Remember the slicing parameters.
4421  */
4422  iterator->slice_ndim = slice_ndim;
4423 
4424  if (slice_ndim > 0)
4425  {
4426  /*
4427  * Get pointers into the array's dims and lbound arrays to represent
4428  * the dims/lbound arrays of a slice. These are the same as the
4429  * rightmost N dimensions of the array.
4430  */
4431  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4432  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4433 
4434  /*
4435  * Compute number of elements in a slice.
4436  */
4437  iterator->slice_len = ArrayGetNItems(slice_ndim,
4438  iterator->slice_dims);
4439 
4440  /*
4441  * Create workspace for building sub-arrays.
4442  */
4443  iterator->slice_values = (Datum *)
4444  palloc(iterator->slice_len * sizeof(Datum));
4445  iterator->slice_nulls = (bool *)
4446  palloc(iterator->slice_len * sizeof(bool));
4447  }
4448 
4449  /*
4450  * Initialize our data pointer and linear element number. These will
4451  * advance through the array during array_iterate().
4452  */
4453  iterator->data_ptr = ARR_DATA_PTR(arr);
4454  iterator->current_item = 0;
4455 
4456  return iterator;
4457 }
bits8 * nullbitmap
Definition: arrayfuncs.c:73
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:85
#define ERROR
Definition: elog.h:46
Datum * slice_values
Definition: arrayfuncs.c:84
#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:72

◆ array_dims()

Datum array_dims ( PG_FUNCTION_ARGS  )

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

1680 {
1682  char *p;
1683  int i;
1684  int *dimv,
1685  *lb;
1686 
1687  /*
1688  * 33 since we assume 15 digits per number + ':' +'[]'
1689  *
1690  * +1 for trailing null
1691  */
1692  char buf[MAXDIM * 33 + 1];
1693 
1694  /* Sanity check: does it look like an array at all? */
1695  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1696  PG_RETURN_NULL();
1697 
1698  dimv = AARR_DIMS(v);
1699  lb = AARR_LBOUND(v);
1700 
1701  p = buf;
1702  for (i = 0; i < AARR_NDIM(v); i++)
1703  {
1704  sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1);
1705  p += strlen(p);
1706  }
1707 
1709 }
#define PG_GETARG_ANY_ARRAY_P(n)
Definition: array.h:267
#define sprintf
Definition: port.h:219
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:189
#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 3605 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().

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

4898 {
4899  char *destdataptr = ARR_DATA_PTR(newarray);
4900  bits8 *destnullsptr = ARR_NULLBITMAP(newarray);
4901  char *srcdataptr;
4902  int src_offset,
4903  dest_offset,
4904  prod[MAXDIM],
4905  span[MAXDIM],
4906  dist[MAXDIM],
4907  indx[MAXDIM];
4908  int i,
4909  j,
4910  inc;
4911 
4912  src_offset = ArrayGetOffset(ndim, dim, lb, st);
4913  srcdataptr = array_seek(arraydataptr, 0, arraynullsptr, src_offset,
4914  typlen, typbyval, typalign);
4915  mda_get_prod(ndim, dim, prod);
4916  mda_get_range(ndim, span, st, endp);
4917  mda_get_offset_values(ndim, dist, prod, span);
4918  for (i = 0; i < ndim; i++)
4919  indx[i] = 0;
4920  dest_offset = 0;
4921  j = ndim - 1;
4922  do
4923  {
4924  if (dist[j])
4925  {
4926  /* skip unwanted elements */
4927  srcdataptr = array_seek(srcdataptr, src_offset, arraynullsptr,
4928  dist[j],
4929  typlen, typbyval, typalign);
4930  src_offset += dist[j];
4931  }
4932  inc = array_copy(destdataptr, 1,
4933  srcdataptr, src_offset, arraynullsptr,
4934  typlen, typbyval, typalign);
4935  if (destnullsptr)
4936  array_bitmap_copy(destnullsptr, dest_offset,
4937  arraynullsptr, src_offset,
4938  1);
4939  destdataptr += inc;
4940  srcdataptr += inc;
4941  src_offset++;
4942  dest_offset++;
4943  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4944 }
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:4756
static int array_copy(char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4726
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:4656
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 5797 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.

5798 {
5799  ArrayType *dims;
5800  ArrayType *result;
5801  Oid elmtype;
5802  Datum value;
5803  bool isnull;
5804 
5805  if (PG_ARGISNULL(1))
5806  ereport(ERROR,
5807  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5808  errmsg("dimension array or low bound array cannot be null")));
5809 
5810  dims = PG_GETARG_ARRAYTYPE_P(1);
5811 
5812  if (!PG_ARGISNULL(0))
5813  {
5814  value = PG_GETARG_DATUM(0);
5815  isnull = false;
5816  }
5817  else
5818  {
5819  value = 0;
5820  isnull = true;
5821  }
5822 
5823  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5824  if (!OidIsValid(elmtype))
5825  elog(ERROR, "could not determine data type of input");
5826 
5827  result = array_fill_internal(dims, NULL, value, isnull, elmtype, fcinfo);
5828  PG_RETURN_ARRAYTYPE_P(result);
5829 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5849
#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 5849 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().

5852 {
5853  ArrayType *result;
5854  int *dimv;
5855  int *lbsv;
5856  int ndims;
5857  int nitems;
5858  int deflbs[MAXDIM];
5859  int16 elmlen;
5860  bool elmbyval;
5861  char elmalign;
5862  ArrayMetaState *my_extra;
5863 
5864  /*
5865  * Params checks
5866  */
5867  if (ARR_NDIM(dims) > 1)
5868  ereport(ERROR,
5869  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5870  errmsg("wrong number of array subscripts"),
5871  errdetail("Dimension array must be one dimensional.")));
5872 
5873  if (array_contains_nulls(dims))
5874  ereport(ERROR,
5875  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5876  errmsg("dimension values cannot be null")));
5877 
5878  dimv = (int *) ARR_DATA_PTR(dims);
5879  ndims = (ARR_NDIM(dims) > 0) ? ARR_DIMS(dims)[0] : 0;
5880 
5881  if (ndims < 0) /* we do allow zero-dimension arrays */
5882  ereport(ERROR,
5883  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5884  errmsg("invalid number of dimensions: %d", ndims)));
5885  if (ndims > MAXDIM)
5886  ereport(ERROR,
5887  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5888  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5889  ndims, MAXDIM)));
5890 
5891  if (lbs != NULL)
5892  {
5893  if (ARR_NDIM(lbs) > 1)
5894  ereport(ERROR,
5895  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5896  errmsg("wrong number of array subscripts"),
5897  errdetail("Dimension array must be one dimensional.")));
5898 
5899  if (array_contains_nulls(lbs))
5900  ereport(ERROR,
5901  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5902  errmsg("dimension values cannot be null")));
5903 
5904  if (ndims != ((ARR_NDIM(lbs) > 0) ? ARR_DIMS(lbs)[0] : 0))
5905  ereport(ERROR,
5906  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5907  errmsg("wrong number of array subscripts"),
5908  errdetail("Low bound array has different size than dimensions array.")));
5909 
5910  lbsv = (int *) ARR_DATA_PTR(lbs);
5911  }
5912  else
5913  {
5914  int i;
5915 
5916  for (i = 0; i < MAXDIM; i++)
5917  deflbs[i] = 1;
5918 
5919  lbsv = deflbs;
5920  }
5921 
5922  /* This checks for overflow of the array dimensions */
5923  nitems = ArrayGetNItems(ndims, dimv);
5924  ArrayCheckBounds(ndims, dimv, lbsv);
5925 
5926  /* fast track for empty array */
5927  if (nitems <= 0)
5928  return construct_empty_array(elmtype);
5929 
5930  /*
5931  * We arrange to look up info about element type only once per series of
5932  * calls, assuming the element type doesn't change underneath us.
5933  */
5934  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
5935  if (my_extra == NULL)
5936  {
5937  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
5938  sizeof(ArrayMetaState));
5939  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
5940  my_extra->element_type = InvalidOid;
5941  }
5942 
5943  if (my_extra->element_type != elmtype)
5944  {
5945  /* Get info about element type */
5946  get_typlenbyvalalign(elmtype,
5947  &my_extra->typlen,
5948  &my_extra->typbyval,
5949  &my_extra->typalign);
5950  my_extra->element_type = elmtype;
5951  }
5952 
5953  elmlen = my_extra->typlen;
5954  elmbyval = my_extra->typbyval;
5955  elmalign = my_extra->typalign;
5956 
5957  /* compute required space */
5958  if (!isnull)
5959  {
5960  int i;
5961  char *p;
5962  int nbytes;
5963  int totbytes;
5964 
5965  /* make sure data is not toasted */
5966  if (elmlen == -1)
5968 
5969  nbytes = att_addlength_datum(0, elmlen, value);
5970  nbytes = att_align_nominal(nbytes, elmalign);
5971  Assert(nbytes > 0);
5972 
5973  totbytes = nbytes * nitems;
5974 
5975  /* check for overflow of multiplication or total request */
5976  if (totbytes / nbytes != nitems ||
5977  !AllocSizeIsValid(totbytes))
5978  ereport(ERROR,
5979  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5980  errmsg("array size exceeds the maximum allowed (%d)",
5981  (int) MaxAllocSize)));
5982 
5983  /*
5984  * This addition can't overflow, but it might cause us to go past
5985  * MaxAllocSize. We leave it to palloc to complain in that case.
5986  */
5987  totbytes += ARR_OVERHEAD_NONULLS(ndims);
5988 
5989  result = create_array_envelope(ndims, dimv, lbsv, totbytes,
5990  elmtype, 0);
5991 
5992  p = ARR_DATA_PTR(result);
5993  for (i = 0; i < nitems; i++)
5994  p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, p);
5995  }
5996  else
5997  {
5998  int nbytes;
5999  int dataoffset;
6000 
6001  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
6002  nbytes = dataoffset;
6003 
6004  result = create_array_envelope(ndims, dimv, lbsv, nbytes,
6005  elmtype, dataoffset);
6006 
6007  /* create_array_envelope already zeroed the bitmap, so we're done */
6008  }
6009 
6010  return result;
6011 }
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:4617
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:3440
#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:5832
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:3558

◆ array_fill_with_lower_bounds()

Datum array_fill_with_lower_bounds ( PG_FUNCTION_ARGS  )

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

5757 {
5758  ArrayType *dims;
5759  ArrayType *lbs;
5760  ArrayType *result;
5761  Oid elmtype;
5762  Datum value;
5763  bool isnull;
5764 
5765  if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
5766  ereport(ERROR,
5767  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5768  errmsg("dimension array or low bound array cannot be null")));
5769 
5770  dims = PG_GETARG_ARRAYTYPE_P(1);
5771  lbs = PG_GETARG_ARRAYTYPE_P(2);
5772 
5773  if (!PG_ARGISNULL(0))
5774  {
5775  value = PG_GETARG_DATUM(0);
5776  isnull = false;
5777  }
5778  else
5779  {
5780  value = 0;
5781  isnull = true;
5782  }
5783 
5784  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5785  if (!OidIsValid(elmtype))
5786  elog(ERROR, "could not determine data type of input");
5787 
5788  result = array_fill_internal(dims, lbs, value, isnull, elmtype, fcinfo);
5789  PG_RETURN_ARRAYTYPE_P(result);
5790 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5849
#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 4549 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4550 {
4551  if (iterator->slice_ndim > 0)
4552  {
4553  pfree(iterator->slice_values);
4554  pfree(iterator->slice_nulls);
4555  }
4556  pfree(iterator);
4557 }
bool * slice_nulls
Definition: arrayfuncs.c:85
void pfree(void *pointer)
Definition: mcxt.c:1169
Datum * slice_values
Definition: arrayfuncs.c:84

◆ array_ge()

Datum array_ge ( PG_FUNCTION_ARGS  )

Definition at line 3758 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3759 {
3760  PG_RETURN_BOOL(array_cmp(fcinfo) >= 0);
3761 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3776
#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 1831 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().

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

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

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

4572 {
4573  if (nullbitmap == NULL)
4574  return false; /* assume not null */
4575  if (nullbitmap[offset / 8] & (1 << (offset % 8)))
4576  return false; /* not null */
4577  return true;
4578 }

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

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

References array_cmp(), and PG_RETURN_BOOL.

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

◆ array_in()

Datum array_in ( PG_FUNCTION_ARGS  )

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

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

4971 {
4972  char *destPtr = ARR_DATA_PTR(destArray);
4973  char *origPtr = ARR_DATA_PTR(origArray);
4974  char *srcPtr = ARR_DATA_PTR(srcArray);
4975  bits8 *destBitmap = ARR_NULLBITMAP(destArray);
4976  bits8 *origBitmap = ARR_NULLBITMAP(origArray);
4977  bits8 *srcBitmap = ARR_NULLBITMAP(srcArray);
4978  int orignitems = ArrayGetNItems(ARR_NDIM(origArray),
4979  ARR_DIMS(origArray));
4980  int dest_offset,
4981  orig_offset,
4982  src_offset,
4983  prod[MAXDIM],
4984  span[MAXDIM],
4985  dist[MAXDIM],
4986  indx[MAXDIM];
4987  int i,
4988  j,
4989  inc;
4990 
4991  dest_offset = ArrayGetOffset(ndim, dim, lb, st);
4992  /* copy items before the slice start */
4993  inc = array_copy(destPtr, dest_offset,
4994  origPtr, 0, origBitmap,
4995  typlen, typbyval, typalign);
4996  destPtr += inc;
4997  origPtr += inc;
4998  if (destBitmap)
4999  array_bitmap_copy(destBitmap, 0, origBitmap, 0, dest_offset);
5000  orig_offset = dest_offset;
5001  mda_get_prod(ndim, dim, prod);
5002  mda_get_range(ndim, span, st, endp);
5003  mda_get_offset_values(ndim, dist, prod, span);
5004  for (i = 0; i < ndim; i++)
5005  indx[i] = 0;
5006  src_offset = 0;
5007  j = ndim - 1;
5008  do
5009  {
5010  /* Copy/advance over elements between here and next part of slice */
5011  if (dist[j])
5012  {
5013  inc = array_copy(destPtr, dist[j],
5014  origPtr, orig_offset, origBitmap,
5015  typlen, typbyval, typalign);
5016  destPtr += inc;
5017  origPtr += inc;
5018  if (destBitmap)
5019  array_bitmap_copy(destBitmap, dest_offset,
5020  origBitmap, orig_offset,
5021  dist[j]);
5022  dest_offset += dist[j];
5023  orig_offset += dist[j];
5024  }
5025  /* Copy new element at this slice position */
5026  inc = array_copy(destPtr, 1,
5027  srcPtr, src_offset, srcBitmap,
5028  typlen, typbyval, typalign);
5029  if (destBitmap)
5030  array_bitmap_copy(destBitmap, dest_offset,
5031  srcBitmap, src_offset,
5032  1);
5033  destPtr += inc;
5034  srcPtr += inc;
5035  dest_offset++;
5036  src_offset++;
5037  /* Advance over old element at this slice position */
5038  origPtr = array_seek(origPtr, orig_offset, origBitmap, 1,
5039  typlen, typbyval, typalign);
5040  orig_offset++;
5041  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
5042 
5043  /* don't miss any data at the end */
5044  array_copy(destPtr, orignitems - orig_offset,
5045  origPtr, orig_offset, origBitmap,
5046  typlen, typbyval, typalign);
5047  if (destBitmap)
5048  array_bitmap_copy(destBitmap, dest_offset,
5049  origBitmap, orig_offset,
5050  orignitems - orig_offset);
5051 }
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:4756
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:4726
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:4656
#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 436 of file arrayfuncs.c.

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

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

◆ array_iterate()

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

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

4467 {
4468  /* Done if we have reached the end of the array */
4469  if (iterator->current_item >= iterator->nitems)
4470  return false;
4471 
4472  if (iterator->slice_ndim == 0)
4473  {
4474  /*
4475  * Scalar case: return one element.
4476  */
4477  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4478  {
4479  *isnull = true;
4480  *value = (Datum) 0;
4481  }
4482  else
4483  {
4484  /* non-NULL, so fetch the individual Datum to return */
4485  char *p = iterator->data_ptr;
4486 
4487  *isnull = false;
4488  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4489 
4490  /* Move our data pointer forward to the next element */
4491  p = att_addlength_pointer(p, iterator->typlen, p);
4492  p = (char *) att_align_nominal(p, iterator->typalign);
4493  iterator->data_ptr = p;
4494  }
4495  }
4496  else
4497  {
4498  /*
4499  * Slice case: build and return an array of the requested size.
4500  */
4501  ArrayType *result;
4502  Datum *values = iterator->slice_values;
4503  bool *nulls = iterator->slice_nulls;
4504  char *p = iterator->data_ptr;
4505  int i;
4506 
4507  for (i = 0; i < iterator->slice_len; i++)
4508  {
4509  if (array_get_isnull(iterator->nullbitmap,
4510  iterator->current_item++))
4511  {
4512  nulls[i] = true;
4513  values[i] = (Datum) 0;
4514  }
4515  else
4516  {
4517  nulls[i] = false;
4518  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4519 
4520  /* Move our data pointer forward to the next element */
4521  p = att_addlength_pointer(p, iterator->typlen, p);
4522  p = (char *) att_align_nominal(p, iterator->typalign);
4523  }
4524  }
4525 
4526  iterator->data_ptr = p;
4527 
4528  result = construct_md_array(values,
4529  nulls,
4530  iterator->slice_ndim,
4531  iterator->slice_dims,
4532  iterator->slice_lbound,
4533  ARR_ELEMTYPE(iterator->arr),
4534  iterator->typlen,
4535  iterator->typbyval,
4536  iterator->typalign);
4537 
4538  *isnull = false;
4539  *value = PointerGetDatum(result);
4540  }
4541 
4542  return true;
4543 }
bits8 * nullbitmap
Definition: arrayfuncs.c:73
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
#define PointerGetDatum(X)
Definition: postgres.h:600
bool * slice_nulls
Definition: arrayfuncs.c:85
Datum * slice_values
Definition: arrayfuncs.c:84
#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:4571
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#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:3354
#define ARR_ELEMTYPE(a)
Definition: array.h:285
ArrayType * arr
Definition: arrayfuncs.c:72

◆ array_larger()

Datum array_larger ( PG_FUNCTION_ARGS  )

Definition at line 5651 of file arrayfuncs.c.

References array_cmp(), PG_GETARG_DATUM, and PG_RETURN_DATUM.

5652 {
5653  if (array_cmp(fcinfo) > 0)
5655  else
5657 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3776
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353

◆ array_le()

Datum array_le ( PG_FUNCTION_ARGS  )

Definition at line 3752 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

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

◆ array_length()

Datum array_length ( PG_FUNCTION_ARGS  )

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

1775 {
1777  int reqdim = PG_GETARG_INT32(1);
1778  int *dimv;
1779  int result;
1780 
1781  /* Sanity check: does it look like an array at all? */
1782  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1783  PG_RETURN_NULL();
1784 
1785  /* Sanity check: was the requested dim valid */
1786  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1787  PG_RETURN_NULL();
1788 
1789  dimv = AARR_DIMS(v);
1790 
1791  result = dimv[reqdim - 1];
1792 
1793  PG_RETURN_INT32(result);
1794 }
#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 1717 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.

1718 {
1720  int reqdim = PG_GETARG_INT32(1);
1721  int *lb;
1722  int result;
1723 
1724  /* Sanity check: does it look like an array at all? */
1725  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1726  PG_RETURN_NULL();
1727 
1728  /* Sanity check: was the requested dim valid */
1729  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1730  PG_RETURN_NULL();
1731 
1732  lb = AARR_LBOUND(v);
1733  result = lb[reqdim - 1];
1734 
1735  PG_RETURN_INT32(result);
1736 }
#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 3740 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3741 {
3742  PG_RETURN_BOOL(array_cmp(fcinfo) < 0);
3743 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3776
#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 3159 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().

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

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

1664 {
1666 
1667  /* Sanity check: does it look like an array at all? */
1668  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1669  PG_RETURN_NULL();
1670 
1672 }
#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 3734 of file arrayfuncs.c.

References array_eq(), DatumGetBool, and PG_RETURN_BOOL.

3735 {
3737 }
#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:3605

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

References array_seek().

Referenced by array_copy(), and array_set_slice().

4706 {
4707  return array_seek(ptr, offset, nullbitmap, nitems,
4708  typlen, typbyval, typalign) - ptr;
4709 }
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:4656

◆ array_out()

Datum array_out ( PG_FUNCTION_ARGS  )

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

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

1272 {
1274  Oid spec_element_type = PG_GETARG_OID(1); /* type of an array
1275  * element */
1276  int32 typmod = PG_GETARG_INT32(2); /* typmod for array elements */
1277  Oid element_type;
1278  int typlen;
1279  bool typbyval;
1280  char typalign;
1281  Oid typioparam;
1282  int i,
1283  nitems;
1284  Datum *dataPtr;
1285  bool *nullsPtr;
1286  bool hasnulls;
1287  int32 nbytes;
1288  int32 dataoffset;
1289  ArrayType *retval;
1290  int ndim,
1291  flags,
1292  dim[MAXDIM],
1293  lBound[MAXDIM];
1294  ArrayMetaState *my_extra;
1295 
1296  /* Get the array header information */
1297  ndim = pq_getmsgint(buf, 4);
1298  if (ndim < 0) /* we do allow zero-dimension arrays */
1299  ereport(ERROR,
1300  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1301  errmsg("invalid number of dimensions: %d", ndim)));
1302  if (ndim > MAXDIM)
1303  ereport(ERROR,
1304  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1305  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
1306  ndim, MAXDIM)));
1307 
1308  flags = pq_getmsgint(buf, 4);
1309  if (flags != 0 && flags != 1)
1310  ereport(ERROR,
1311  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1312  errmsg("invalid array flags")));
1313 
1314  /* Check element type recorded in the data */
1315  element_type = pq_getmsgint(buf, sizeof(Oid));
1316 
1317  /*
1318  * From a security standpoint, it doesn't matter whether the input's
1319  * element type matches what we expect: the element type's receive
1320  * function has to be robust enough to cope with invalid data. However,
1321  * from a user-friendliness standpoint, it's nicer to complain about type
1322  * mismatches than to throw "improper binary format" errors. But there's
1323  * a problem: only built-in types have OIDs that are stable enough to
1324  * believe that a mismatch is a real issue. So complain only if both OIDs
1325  * are in the built-in range. Otherwise, carry on with the element type
1326  * we "should" be getting.
1327  */
1328  if (element_type != spec_element_type)
1329  {
1330  if (element_type < FirstGenbkiObjectId &&
1331  spec_element_type < FirstGenbkiObjectId)
1332  ereport(ERROR,
1333  (errcode(ERRCODE_DATATYPE_MISMATCH),
1334  errmsg("binary data has array element type %u (%s) instead of expected %u (%s)",
1335  element_type,
1336  format_type_extended(element_type, -1,
1338  spec_element_type,
1339  format_type_extended(spec_element_type, -1,
1341  element_type = spec_element_type;
1342  }
1343 
1344  for (i = 0; i < ndim; i++)
1345  {
1346  dim[i] = pq_getmsgint(buf, 4);
1347  lBound[i] = pq_getmsgint(buf, 4);
1348  }
1349 
1350  /* This checks for overflow of array dimensions */
1351  nitems = ArrayGetNItems(ndim, dim);
1352  ArrayCheckBounds(ndim, dim, lBound);
1353 
1354  /*
1355  * We arrange to look up info about element type, including its receive
1356  * conversion proc, only once per series of calls, assuming the element
1357  * type doesn't change underneath us.
1358  */
1359  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1360  if (my_extra == NULL)
1361  {
1362  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1363  sizeof(ArrayMetaState));
1364  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1365  my_extra->element_type = ~element_type;
1366  }
1367 
1368  if (my_extra->element_type != element_type)
1369  {
1370  /* Get info about element type, including its receive proc */
1371  get_type_io_data(element_type, IOFunc_receive,
1372  &my_extra->typlen, &my_extra->typbyval,
1373  &my_extra->typalign, &my_extra->typdelim,
1374  &my_extra->typioparam, &my_extra->typiofunc);
1375  if (!OidIsValid(my_extra->typiofunc))
1376  ereport(ERROR,
1377  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1378  errmsg("no binary input function available for type %s",
1379  format_type_be(element_type))));
1380  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1381  fcinfo->flinfo->fn_mcxt);
1382  my_extra->element_type = element_type;
1383  }
1384 
1385  if (nitems == 0)
1386  {
1387  /* Return empty array ... but not till we've validated element_type */
1389  }
1390 
1391  typlen = my_extra->typlen;
1392  typbyval = my_extra->typbyval;
1393  typalign = my_extra->typalign;
1394  typioparam = my_extra->typioparam;
1395 
1396  dataPtr = (Datum *) palloc(nitems * sizeof(Datum));
1397  nullsPtr = (bool *) palloc(nitems * sizeof(bool));
1398  ReadArrayBinary(buf, nitems,
1399  &my_extra->proc, typioparam, typmod,
1400  typlen, typbyval, typalign,
1401  dataPtr, nullsPtr,
1402  &hasnulls, &nbytes);
1403  if (hasnulls)
1404  {
1405  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
1406  nbytes += dataoffset;
1407  }
1408  else
1409  {
1410  dataoffset = 0; /* marker for no null bitmap */
1411  nbytes += ARR_OVERHEAD_NONULLS(ndim);
1412  }
1413  retval = (ArrayType *) palloc0(nbytes);
1414  SET_VARSIZE(retval, nbytes);
1415  retval->ndim = ndim;
1416  retval->dataoffset = dataoffset;
1417  retval->elemtype = element_type;
1418  memcpy(ARR_DIMS(retval), dim, ndim * sizeof(int));
1419  memcpy(ARR_LBOUND(retval), lBound, ndim * sizeof(int));
1420 
1421  CopyArrayEls(retval,
1422  dataPtr, nullsPtr, nitems,
1423  typlen, typbyval, typalign,
1424  true);
1425 
1426  pfree(dataPtr);
1427  pfree(nullsPtr);
1428 
1429  PG_RETURN_ARRAYTYPE_P(retval);
1430 }
#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:3440
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:1454
void ArrayCheckBounds(int ndim, const int *dims, const int *lb)
Definition: arrayutils.c:128
#define FORMAT_TYPE_ALLOW_INVALID
Definition: builtins.h:113
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:961
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 3104 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3107 {
3108  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3109  arraytyplen, elmlen, elmbyval, elmalign,
3110  isNull);
3111 }
#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:1831

◆ array_remove()

Datum array_remove ( PG_FUNCTION_ARGS  )

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

6401 {
6402  ArrayType *array;
6403  Datum search = PG_GETARG_DATUM(1);
6404  bool search_isnull = PG_ARGISNULL(1);
6405 
6406  if (PG_ARGISNULL(0))
6407  PG_RETURN_NULL();
6408  array = PG_GETARG_ARRAYTYPE_P(0);
6409 
6410  array = array_replace_internal(array,
6411  search, search_isnull,
6412  (Datum) 0, true,
6413  true, PG_GET_COLLATION(),
6414  fcinfo);
6415  PG_RETURN_ARRAYTYPE_P(array);
6416 }
#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:6142
#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 6422 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.

6423 {
6424  ArrayType *array;
6425  Datum search = PG_GETARG_DATUM(1);
6426  bool search_isnull = PG_ARGISNULL(1);
6427  Datum replace = PG_GETARG_DATUM(2);
6428  bool replace_isnull = PG_ARGISNULL(2);
6429 
6430  if (PG_ARGISNULL(0))
6431  PG_RETURN_NULL();
6432  array = PG_GETARG_ARRAYTYPE_P(0);
6433 
6434  array = array_replace_internal(array,
6435  search, search_isnull,
6436  replace, replace_isnull,
6437  false, PG_GET_COLLATION(),
6438  fcinfo);
6439  PG_RETURN_ARRAYTYPE_P(array);
6440 }
#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:6142
#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 6142 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().

6147 {
6148  LOCAL_FCINFO(locfcinfo, 2);
6149  ArrayType *result;
6150  Oid element_type;
6151  Datum *values;
6152  bool *nulls;
6153  int *dim;
6154  int ndim;
6155  int nitems,
6156  nresult;
6157  int i;
6158  int32 nbytes = 0;
6159  int32 dataoffset;
6160  bool hasnulls;
6161  int typlen;
6162  bool typbyval;
6163  char typalign;
6164  char *arraydataptr;
6165  bits8 *bitmap;
6166  int bitmask;
6167  bool changed = false;
6168  TypeCacheEntry *typentry;
6169 
6170  element_type = ARR_ELEMTYPE(array);
6171  ndim = ARR_NDIM(array);
6172  dim = ARR_DIMS(array);
6173  nitems = ArrayGetNItems(ndim, dim);
6174 
6175  /* Return input array unmodified if it is empty */
6176  if (nitems <= 0)
6177  return array;
6178 
6179  /*
6180  * We can't remove elements from multi-dimensional arrays, since the
6181  * result might not be rectangular.
6182  */
6183  if (remove && ndim > 1)
6184  ereport(ERROR,
6185  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6186  errmsg("removing elements from multidimensional arrays is not supported")));
6187 
6188  /*
6189  * We arrange to look up the equality function only once per series of
6190  * calls, assuming the element type doesn't change underneath us.
6191  */
6192  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
6193  if (typentry == NULL ||
6194  typentry->type_id != element_type)
6195  {
6196  typentry = lookup_type_cache(element_type,
6198  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
6199  ereport(ERROR,
6200  (errcode(ERRCODE_UNDEFINED_FUNCTION),
6201  errmsg("could not identify an equality operator for type %s",
6202  format_type_be(element_type))));
6203  fcinfo->flinfo->fn_extra = (void *) typentry;
6204  }
6205  typlen = typentry->typlen;
6206  typbyval = typentry->typbyval;
6207  typalign = typentry->typalign;
6208 
6209  /*
6210  * Detoast values if they are toasted. The replacement value must be
6211  * detoasted for insertion into the result array, while detoasting the
6212  * search value only once saves cycles.
6213  */
6214  if (typlen == -1)
6215  {
6216  if (!search_isnull)
6217  search = PointerGetDatum(PG_DETOAST_DATUM(search));
6218  if (!replace_isnull)
6219  replace = PointerGetDatum(PG_DETOAST_DATUM(replace));
6220  }
6221 
6222  /* Prepare to apply the comparison operator */
6223  InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
6224  collation, NULL, NULL);
6225 
6226  /* Allocate temporary arrays for new values */
6227  values = (Datum *) palloc(nitems * sizeof(Datum));
6228  nulls = (bool *) palloc(nitems * sizeof(bool));
6229 
6230  /* Loop over source data */
6231  arraydataptr = ARR_DATA_PTR(array);
6232  bitmap = ARR_NULLBITMAP(array);
6233  bitmask = 1;
6234  hasnulls = false;
6235  nresult = 0;
6236 
6237  for (i = 0; i < nitems; i++)
6238  {
6239  Datum elt;
6240  bool isNull;
6241  bool oprresult;
6242  bool skip = false;
6243 
6244  /* Get source element, checking for NULL */
6245  if (bitmap && (*bitmap & bitmask) == 0)
6246  {
6247  isNull = true;
6248  /* If searching for NULL, we have a match */
6249  if (search_isnull)
6250  {
6251  if (remove)
6252  {
6253  skip = true;
6254  changed = true;
6255  }
6256  else if (!replace_isnull)
6257  {
6258  values[nresult] = replace;
6259  isNull = false;
6260  changed = true;
6261  }
6262  }
6263  }
6264  else
6265  {
6266  isNull = false;
6267  elt = fetch_att(arraydataptr, typbyval, typlen);
6268  arraydataptr = att_addlength_datum(arraydataptr, typlen, elt);
6269  arraydataptr = (char *) att_align_nominal(arraydataptr, typalign);
6270 
6271  if (search_isnull)
6272  {
6273  /* no match possible, keep element */
6274  values[nresult] = elt;
6275  }
6276  else
6277  {
6278  /*
6279  * Apply the operator to the element pair; treat NULL as false
6280  */
6281  locfcinfo->args[0].value = elt;
6282  locfcinfo->args[0].isnull = false;
6283  locfcinfo->args[1].value = search;
6284  locfcinfo->args[1].isnull = false;
6285  locfcinfo->isnull = false;
6286  oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
6287  if (locfcinfo->isnull || !oprresult)
6288  {
6289  /* no match, keep element */
6290  values[nresult] = elt;
6291  }
6292  else
6293  {
6294  /* match, so replace or delete */
6295  changed = true;
6296  if (remove)
6297  skip = true;
6298  else
6299  {
6300  values[nresult] = replace;
6301  isNull = replace_isnull;
6302  }
6303  }
6304  }
6305  }
6306 
6307  if (!skip)
6308  {
6309  nulls[nresult] = isNull;
6310  if (isNull)
6311  hasnulls = true;
6312  else
6313  {
6314  /* Update total result size */
6315  nbytes = att_addlength_datum(nbytes, typlen, values[nresult]);
6316  nbytes = att_align_nominal(nbytes, typalign);
6317  /* check for overflow of total request */
6318  if (!AllocSizeIsValid(nbytes))
6319  ereport(ERROR,
6320  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
6321  errmsg("array size exceeds the maximum allowed (%d)",
6322  (int) MaxAllocSize)));
6323  }
6324  nresult++;
6325  }
6326 
6327  /* advance bitmap pointer if any */
6328  if (bitmap)
6329  {
6330  bitmask <<= 1;
6331  if (bitmask == 0x100)
6332  {
6333  bitmap++;
6334  bitmask = 1;
6335  }
6336  }
6337  }
6338 
6339  /*
6340  * If not changed just return the original array
6341  */
6342  if (!changed)
6343  {
6344  pfree(values);
6345  pfree(nulls);
6346  return array;
6347  }
6348 
6349  /* If all elements were removed return an empty array */
6350  if (nresult == 0)
6351  {
6352  pfree(values);
6353  pfree(nulls);
6354  return construct_empty_array(element_type);
6355  }
6356 
6357  /* Allocate and initialize the result array */
6358  if (hasnulls)
6359  {
6360  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nresult);
6361  nbytes += dataoffset;
6362  }
6363  else
6364  {
6365  dataoffset = 0; /* marker for no null bitmap */
6366  nbytes += ARR_OVERHEAD_NONULLS(ndim);
6367  }
6368  result = (ArrayType *) palloc0(nbytes);
6369  SET_VARSIZE(result, nbytes);
6370  result->ndim = ndim;
6371  result->dataoffset = dataoffset;
6372  result->elemtype = element_type;
6373  memcpy(ARR_DIMS(result), ARR_DIMS(array), ndim * sizeof(int));
6374  memcpy(ARR_LBOUND(result), ARR_LBOUND(array), ndim * sizeof(int));
6375 
6376  if (remove)
6377  {
6378  /* Adjust the result length */
6379  ARR_DIMS(result)[0] = nresult;
6380  }
6381 
6382  /* Insert data into result array */
6383  CopyArrayEls(result,
6384  values, nulls, nresult,
6385  typlen, typbyval, typalign,
6386  false);
6387 
6388  pfree(values);
6389  pfree(nulls);
6390 
6391  return result;
6392 }
#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:3440
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:961
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#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 4656 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().

4658 {
4659  int bitmask;
4660  int i;
4661 
4662  /* easy if fixed-size elements and no NULLs */
4663  if (typlen > 0 && !nullbitmap)
4664  return ptr + nitems * ((Size) att_align_nominal(typlen, typalign));
4665 
4666  /* seems worth having separate loops for NULL and no-NULLs cases */
4667  if (nullbitmap)
4668  {
4669  nullbitmap += offset / 8;
4670  bitmask = 1 << (offset % 8);
4671 
4672  for (i = 0; i < nitems; i++)
4673  {
4674  if (*nullbitmap & bitmask)
4675  {
4676  ptr = att_addlength_pointer(ptr, typlen, ptr);
4677  ptr = (char *) att_align_nominal(ptr, typalign);
4678  }
4679  bitmask <<= 1;
4680  if (bitmask == 0x100)
4681  {
4682  nullbitmap++;
4683  bitmask = 1;
4684  }
4685  }
4686  }
4687  else
4688  {
4689  for (i = 0; i < nitems; i++)
4690  {
4691  ptr = att_addlength_pointer(ptr, typlen, ptr);
4692  ptr = (char *) att_align_nominal(ptr, typalign);
4693  }
4694  }
4695  return ptr;
4696 }
#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 1559 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().

1560 {
1562  Oid element_type = AARR_ELEMTYPE(v);
1563  int typlen;
1564  bool typbyval;
1565  char typalign;
1566  int nitems,
1567  i;
1568  int ndim,
1569  *dim,
1570  *lb;
1572  array_iter iter;
1573  ArrayMetaState *my_extra;
1574 
1575  /*
1576  * We arrange to look up info about element type, including its send
1577  * conversion proc, only once per series of calls, assuming the element
1578  * type doesn't change underneath us.
1579  */
1580  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1581  if (my_extra == NULL)
1582  {
1583  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1584  sizeof(ArrayMetaState));
1585  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1586  my_extra->element_type = ~element_type;
1587  }
1588 
1589  if (my_extra->element_type != element_type)
1590  {
1591  /* Get info about element type, including its send proc */
1592  get_type_io_data(element_type, IOFunc_send,
1593  &my_extra->typlen, &my_extra->typbyval,
1594  &my_extra->typalign, &my_extra->typdelim,
1595  &my_extra->typioparam, &my_extra->typiofunc);
1596  if (!OidIsValid(my_extra->typiofunc))
1597  ereport(ERROR,
1598  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1599  errmsg("no binary output function available for type %s",
1600  format_type_be(element_type))));
1601  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1602  fcinfo->flinfo->fn_mcxt);
1603  my_extra->element_type = element_type;
1604  }
1605  typlen = my_extra->typlen;
1606  typbyval = my_extra->typbyval;
1607  typalign = my_extra->typalign;
1608 
1609  ndim = AARR_NDIM(v);
1610  dim = AARR_DIMS(v);
1611  lb = AARR_LBOUND(v);
1612  nitems = ArrayGetNItems(ndim, dim);
1613 
1614  pq_begintypsend(&buf);
1615 
1616  /* Send the array header information */
1617  pq_sendint32(&buf, ndim);
1618  pq_sendint32(&buf, AARR_HASNULL(v) ? 1 : 0);
1619  pq_sendint32(&buf, element_type);
1620  for (i = 0; i < ndim; i++)
1621  {
1622  pq_sendint32(&buf, dim[i]);
1623  pq_sendint32(&buf, lb[i]);
1624  }
1625 
1626  /* Send the array elements using the element's own sendproc */
1627  array_iter_setup(&iter, v);
1628 
1629  for (i = 0; i < nitems; i++)
1630  {
1631  Datum itemvalue;
1632  bool isnull;
1633 
1634  /* Get source element, checking for NULL */
1635  itemvalue = array_iter_next(&iter, &isnull, i,
1636  typlen, typbyval, typalign);
1637 
1638  if (isnull)
1639  {
1640  /* -1 length means a NULL */
1641  pq_sendint32(&buf, -1);
1642  }
1643  else
1644  {
1645  bytea *outputbytes;
1646 
1647  outputbytes = SendFunctionCall(&my_extra->proc, itemvalue);
1648  pq_sendint32(&buf, VARSIZE(outputbytes) - VARHDRSZ);
1649  pq_sendbytes(&buf, VARDATA(outputbytes),
1650  VARSIZE(outputbytes) - VARHDRSZ);
1651  pfree(outputbytes);
1652  }
1653  }
1654 
1656 }
#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 3121 of file arrayfuncs.c.

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3124 {
3126  nSubscripts, indx,
3127  dataValue, isNull,
3128  arraytyplen,
3129  elmlen, elmbyval, elmalign));
3130 }
#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:2212
#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 2212 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().

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