PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 "utils/array.h"
#include "utils/arrayaccess.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/typcache.h"
Include dependency graph for arrayfuncs.c:

Go to the source code of this file.

Data Structures

struct  ArrayIteratorData
 
struct  generate_subscripts_fctx
 

Macros

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

Typedefs

typedef struct ArrayIteratorData ArrayIteratorData
 
typedef struct
generate_subscripts_fctx 
generate_subscripts_fctx
 

Enumerations

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

Functions

static bool array_isspace (char ch)
 
static int ArrayCount (const char *str, int *dim, char typdelim)
 
static void ReadArrayStr (char *arrayStr, const char *origStr, int nitems, int ndim, int *dim, FmgrInfo *inputproc, Oid typioparam, int32 typmod, char typdelim, int typlen, bool typbyval, char typalign, Datum *values, bool *nulls, bool *hasnulls, int32 *nbytes)
 
static void ReadArrayBinary (StringInfo buf, int nitems, FmgrInfo *receiveproc, Oid typioparam, int32 typmod, int typlen, bool typbyval, char typalign, Datum *values, bool *nulls, bool *hasnulls, int32 *nbytes)
 
static Datum array_get_element_expanded (Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
static Datum array_set_element_expanded (Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
static bool array_get_isnull (const bits8 *nullbitmap, int offset)
 
static void array_set_isnull (bits8 *nullbitmap, int offset, bool isNull)
 
static Datum ArrayCast (char *value, bool byval, int len)
 
static int ArrayCastAndSet (Datum src, int typlen, bool typbyval, char typalign, char *dest)
 
static char * array_seek (char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
 
static int array_nelems_size (char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
 
static int array_copy (char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
 
static int array_slice_size (char *arraydataptr, bits8 *arraynullsptr, int ndim, int *dim, int *lb, int *st, int *endp, int typlen, bool typbyval, char typalign)
 
static void array_extract_slice (ArrayType *newarray, int ndim, int *dim, int *lb, char *arraydataptr, bits8 *arraynullsptr, int *st, int *endp, int typlen, bool typbyval, char typalign)
 
static void array_insert_slice (ArrayType *destArray, ArrayType *origArray, ArrayType *srcArray, int ndim, int *dim, int *lb, int *st, int *endp, int typlen, bool typbyval, char typalign)
 
static int array_cmp (FunctionCallInfo fcinfo)
 
static ArrayTypecreate_array_envelope (int ndims, int *dimv, int *lbv, int nbytes, Oid elmtype, int dataoffset)
 
static ArrayTypearray_fill_internal (ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
 
static ArrayTypearray_replace_internal (ArrayType *array, Datum search, bool search_isnull, Datum replace, bool replace_isnull, bool remove, Oid collation, FunctionCallInfo fcinfo)
 
static int width_bucket_array_float8 (Datum operand, ArrayType *thresholds)
 
static int width_bucket_array_fixed (Datum operand, ArrayType *thresholds, Oid collation, TypeCacheEntry *typentry)
 
static int width_bucket_array_variable (Datum operand, ArrayType *thresholds, Oid collation, TypeCacheEntry *typentry)
 
Datum array_in (PG_FUNCTION_ARGS)
 
void CopyArrayEls (ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
 
Datum array_out (PG_FUNCTION_ARGS)
 
Datum array_recv (PG_FUNCTION_ARGS)
 
Datum array_send (PG_FUNCTION_ARGS)
 
Datum array_ndims (PG_FUNCTION_ARGS)
 
Datum array_dims (PG_FUNCTION_ARGS)
 
Datum array_lower (PG_FUNCTION_ARGS)
 
Datum array_upper (PG_FUNCTION_ARGS)
 
Datum array_length (PG_FUNCTION_ARGS)
 
Datum array_cardinality (PG_FUNCTION_ARGS)
 
Datum array_get_element (Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
Datum array_get_slice (Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_set_element (Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_set_slice (Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, Datum srcArrayDatum, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_ref (ArrayType *array, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
ArrayTypearray_set (ArrayType *array, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_map (FunctionCallInfo fcinfo, 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)
 
static bool array_contain_compare (AnyArrayType *array1, AnyArrayType *array2, Oid collation, bool matchall, void **fn_extra)
 
Datum arrayoverlap (PG_FUNCTION_ARGS)
 
Datum arraycontains (PG_FUNCTION_ARGS)
 
Datum arraycontained (PG_FUNCTION_ARGS)
 
ArrayIterator array_create_iterator (ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
 
bool array_iterate (ArrayIterator iterator, Datum *value, bool *isnull)
 
void array_free_iterator (ArrayIterator iterator)
 
void array_bitmap_copy (bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
 
ArrayBuildStateinitArrayResult (Oid element_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateaccumArrayResult (ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
 
Datum makeArrayResult (ArrayBuildState *astate, MemoryContext rcontext)
 
Datum makeMdArrayResult (ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
 
ArrayBuildStateArrinitArrayResultArr (Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateArraccumArrayResultArr (ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
 
Datum makeArrayResultArr (ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
 
ArrayBuildStateAnyinitArrayResultAny (Oid input_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateAnyaccumArrayResultAny (ArrayBuildStateAny *astate, Datum dvalue, bool disnull, Oid input_type, MemoryContext rcontext)
 
Datum makeArrayResultAny (ArrayBuildStateAny *astate, MemoryContext rcontext, bool release)
 
Datum array_larger (PG_FUNCTION_ARGS)
 
Datum array_smaller (PG_FUNCTION_ARGS)
 
Datum generate_subscripts (PG_FUNCTION_ARGS)
 
Datum generate_subscripts_nodir (PG_FUNCTION_ARGS)
 
Datum array_fill_with_lower_bounds (PG_FUNCTION_ARGS)
 
Datum array_fill (PG_FUNCTION_ARGS)
 
Datum array_unnest (PG_FUNCTION_ARGS)
 
Datum array_remove (PG_FUNCTION_ARGS)
 
Datum array_replace (PG_FUNCTION_ARGS)
 
Datum width_bucket_array (PG_FUNCTION_ARGS)
 

Variables

bool Array_nulls = true
 

Macro Definition Documentation

#define AARR_FREE_IF_COPY (   array,
 
)
Value:
do { \
PG_FREE_IF_COPY(array, n); \
} while (0)
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:216
#define VARATT_IS_EXPANDED_HEADER(PTR)

Definition at line 46 of file arrayfuncs.c.

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

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

Referenced by array_out().

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

Referenced by array_out().

#define ASSGN   "="

Definition at line 44 of file arrayfuncs.c.

Referenced by array_in(), and array_out().

Typedef Documentation

Enumeration Type Documentation

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

Function Documentation

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

Definition at line 4991 of file arrayfuncs.c.

References ArrayBuildState::alen, Assert, datumCopy(), ArrayBuildState::dnulls, ArrayBuildState::dvalues, ArrayBuildState::element_type, initArrayResult(), ArrayBuildState::mcontext, MemoryContextSwitchTo(), ArrayBuildState::nelems, NULL, PG_DETOAST_DATUM_COPY, PointerGetDatum, repalloc(), ArrayBuildState::typbyval, and ArrayBuildState::typlen.

Referenced by accumArrayResultAny(), array_agg_transfn(), array_positions(), array_to_datum_internal(), dblink_get_connections(), get_altertable_subcmdtypes(), optionListToArray(), parse_ident(), regexp_split_to_array(), text_to_array_internal(), transformRelOptions(), and tuple_data_split_internal().

4995 {
4996  MemoryContext oldcontext;
4997 
4998  if (astate == NULL)
4999  {
5000  /* First time through --- initialize */
5001  astate = initArrayResult(element_type, rcontext, true);
5002  }
5003  else
5004  {
5005  Assert(astate->element_type == element_type);
5006  }
5007 
5008  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5009 
5010  /* enlarge dvalues[]/dnulls[] if needed */
5011  if (astate->nelems >= astate->alen)
5012  {
5013  astate->alen *= 2;
5014  astate->dvalues = (Datum *)
5015  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5016  astate->dnulls = (bool *)
5017  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5018  }
5019 
5020  /*
5021  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5022  * it's varlena. (You might think that detoasting is not needed here
5023  * because construct_md_array can detoast the array elements later.
5024  * However, we must not let construct_md_array modify the ArrayBuildState
5025  * because that would mean array_agg_finalfn damages its input, which is
5026  * verboten. Also, this way frequently saves one copying step.)
5027  */
5028  if (!disnull && !astate->typbyval)
5029  {
5030  if (astate->typlen == -1)
5031  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5032  else
5033  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5034  }
5035 
5036  astate->dvalues[astate->nelems] = dvalue;
5037  astate->dnulls[astate->nelems] = disnull;
5038  astate->nelems++;
5039 
5040  MemoryContextSwitchTo(oldcontext);
5041 
5042  return astate;
5043 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:198
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:4951
#define PointerGetDatum(X)
Definition: postgres.h:564
Datum * dvalues
Definition: array.h:171
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:177
Oid element_type
Definition: array.h:175
bool * dnulls
Definition: array.h:172
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1021
MemoryContext mcontext
Definition: array.h:170
int16 typlen
Definition: array.h:176
ArrayBuildStateAny* accumArrayResultAny ( ArrayBuildStateAny astate,
Datum  dvalue,
bool  disnull,
Oid  input_type,
MemoryContext  rcontext 
)

Definition at line 5463 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5467 {
5468  if (astate == NULL)
5469  astate = initArrayResultAny(input_type, rcontext, true);
5470 
5471  if (astate->scalarstate)
5472  (void) accumArrayResult(astate->scalarstate,
5473  dvalue, disnull,
5474  input_type, rcontext);
5475  else
5476  (void) accumArrayResultArr(astate->arraystate,
5477  dvalue, disnull,
5478  input_type, rcontext);
5479 
5480  return astate;
5481 }
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5418
ArrayBuildState * scalarstate
Definition: array.h:210
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5186
ArrayBuildStateArr * arraystate
Definition: array.h:211
#define NULL
Definition: c.h:226
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:4991
ArrayBuildStateArr* accumArrayResultArr ( ArrayBuildStateArr astate,
Datum  dvalue,
bool  disnull,
Oid  array_type,
MemoryContext  rcontext 
)

Definition at line 5186 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, ArrayBuildStateArr::nitems, NULL, ArrayBuildStateArr::nullbitmap, palloc(), pfree(), and repalloc().

Referenced by accumArrayResultAny(), and array_agg_array_transfn().

5190 {
5191  ArrayType *arg;
5192  MemoryContext oldcontext;
5193  int *dims,
5194  *lbs,
5195  ndims,
5196  nitems,
5197  ndatabytes;
5198  char *data;
5199  int i;
5200 
5201  /*
5202  * We disallow accumulating null subarrays. Another plausible definition
5203  * is to ignore them, but callers that want that can just skip calling
5204  * this function.
5205  */
5206  if (disnull)
5207  ereport(ERROR,
5208  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5209  errmsg("cannot accumulate null arrays")));
5210 
5211  /* Detoast input array in caller's context */
5212  arg = DatumGetArrayTypeP(dvalue);
5213 
5214  if (astate == NULL)
5215  astate = initArrayResultArr(array_type, InvalidOid, rcontext, true);
5216  else
5217  Assert(astate->array_type == array_type);
5218 
5219  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5220 
5221  /* Collect this input's dimensions */
5222  ndims = ARR_NDIM(arg);
5223  dims = ARR_DIMS(arg);
5224  lbs = ARR_LBOUND(arg);
5225  data = ARR_DATA_PTR(arg);
5226  nitems = ArrayGetNItems(ndims, dims);
5227  ndatabytes = ARR_SIZE(arg) - ARR_DATA_OFFSET(arg);
5228 
5229  if (astate->ndims == 0)
5230  {
5231  /* First input; check/save the dimensionality info */
5232 
5233  /* Should we allow empty inputs and just produce an empty output? */
5234  if (ndims == 0)
5235  ereport(ERROR,
5236  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5237  errmsg("cannot accumulate empty arrays")));
5238  if (ndims + 1 > MAXDIM)
5239  ereport(ERROR,
5240  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5241  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5242  ndims + 1, MAXDIM)));
5243 
5244  /*
5245  * The output array will have n+1 dimensions, with the ones after the
5246  * first matching the input's dimensions.
5247  */
5248  astate->ndims = ndims + 1;
5249  astate->dims[0] = 0;
5250  memcpy(&astate->dims[1], dims, ndims * sizeof(int));
5251  astate->lbs[0] = 1;
5252  memcpy(&astate->lbs[1], lbs, ndims * sizeof(int));
5253 
5254  /* Allocate at least enough data space for this item */
5255  astate->abytes = 1024;
5256  while (astate->abytes <= ndatabytes)
5257  astate->abytes *= 2;
5258  astate->data = (char *) palloc(astate->abytes);
5259  }
5260  else
5261  {
5262  /* Second or later input: must match first input's dimensionality */
5263  if (astate->ndims != ndims + 1)
5264  ereport(ERROR,
5265  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5266  errmsg("cannot accumulate arrays of different dimensionality")));
5267  for (i = 0; i < ndims; i++)
5268  {
5269  if (astate->dims[i + 1] != dims[i] || astate->lbs[i + 1] != lbs[i])
5270  ereport(ERROR,
5271  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5272  errmsg("cannot accumulate arrays of different dimensionality")));
5273  }
5274 
5275  /* Enlarge data space if needed */
5276  if (astate->nbytes + ndatabytes > astate->abytes)
5277  {
5278  astate->abytes = Max(astate->abytes * 2,
5279  astate->nbytes + ndatabytes);
5280  astate->data = (char *) repalloc(astate->data, astate->abytes);
5281  }
5282  }
5283 
5284  /*
5285  * Copy the data portion of the sub-array. Note we assume that the
5286  * advertised data length of the sub-array is properly aligned. We do not
5287  * have to worry about detoasting elements since whatever's in the
5288  * sub-array should be OK already.
5289  */
5290  memcpy(astate->data + astate->nbytes, data, ndatabytes);
5291  astate->nbytes += ndatabytes;
5292 
5293  /* Deal with null bitmap if needed */
5294  if (astate->nullbitmap || ARR_HASNULL(arg))
5295  {
5296  int newnitems = astate->nitems + nitems;
5297 
5298  if (astate->nullbitmap == NULL)
5299  {
5300  /*
5301  * First input with nulls; we must retrospectively handle any
5302  * previous inputs by marking all their items non-null.
5303  */
5304  astate->aitems = 256;
5305  while (astate->aitems <= newnitems)
5306  astate->aitems *= 2;
5307  astate->nullbitmap = (bits8 *) palloc((astate->aitems + 7) / 8);
5308  array_bitmap_copy(astate->nullbitmap, 0,
5309  NULL, 0,
5310  astate->nitems);
5311  }
5312  else if (newnitems > astate->aitems)
5313  {
5314  astate->aitems = Max(astate->aitems * 2, newnitems);
5315  astate->nullbitmap = (bits8 *)
5316  repalloc(astate->nullbitmap, (astate->aitems + 7) / 8);
5317  }
5318  array_bitmap_copy(astate->nullbitmap, astate->nitems,
5319  ARR_NULLBITMAP(arg), 0,
5320  nitems);
5321  }
5322 
5323  astate->nitems += nitems;
5324  astate->dims[0] += 1;
5325 
5326  MemoryContextSwitchTo(oldcontext);
5327 
5328  /* Release detoasted copy if any */
5329  if ((Pointer) arg != DatumGetPointer(dvalue))
5330  pfree(arg);
5331 
5332  return astate;
5333 }
#define ARR_SIZE(a)
Definition: array.h:270
#define MAXDIM
Definition: c.h:415
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4624
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5139
#define ARR_DATA_OFFSET(a)
Definition: array.h:297
#define ARR_LBOUND(a)
Definition: array.h:277
bits8 * nullbitmap
Definition: array.h:190
void pfree(void *pointer)
Definition: mcxt.c:992
char * Pointer
Definition: c.h:242
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define ARR_HASNULL(a)
Definition: array.h:272
#define ereport(elevel, rest)
Definition: elog.h:122
uint8 bits8
Definition: c.h:272
#define InvalidOid
Definition: postgres_ext.h:36
int lbs[MAXDIM]
Definition: array.h:197
#define Max(x, y)
Definition: c.h:795
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define ARR_NDIM(a)
Definition: array.h:271
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1021
#define DatumGetPointer(X)
Definition: postgres.h:557
int dims[MAXDIM]
Definition: array.h:196
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void * arg
#define ARR_NULLBITMAP(a)
Definition: array.h:281
MemoryContext mcontext
Definition: array.h:188
#define DatumGetArrayTypeP(X)
Definition: array.h:242
void array_bitmap_copy ( bits8 destbitmap,
int  destoffset,
const bits8 srcbitmap,
int  srcoffset,
int  nitems 
)

Definition at line 4624 of file arrayfuncs.c.

References Assert.

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

4627 {
4628  int destbitmask,
4629  destbitval,
4630  srcbitmask,
4631  srcbitval;
4632 
4633  Assert(destbitmap);
4634  if (nitems <= 0)
4635  return; /* don't risk fetch off end of memory */
4636  destbitmap += destoffset / 8;
4637  destbitmask = 1 << (destoffset % 8);
4638  destbitval = *destbitmap;
4639  if (srcbitmap)
4640  {
4641  srcbitmap += srcoffset / 8;
4642  srcbitmask = 1 << (srcoffset % 8);
4643  srcbitval = *srcbitmap;
4644  while (nitems-- > 0)
4645  {
4646  if (srcbitval & srcbitmask)
4647  destbitval |= destbitmask;
4648  else
4649  destbitval &= ~destbitmask;
4650  destbitmask <<= 1;
4651  if (destbitmask == 0x100)
4652  {
4653  *destbitmap++ = destbitval;
4654  destbitmask = 1;
4655  if (nitems > 0)
4656  destbitval = *destbitmap;
4657  }
4658  srcbitmask <<= 1;
4659  if (srcbitmask == 0x100)
4660  {
4661  srcbitmap++;
4662  srcbitmask = 1;
4663  if (nitems > 0)
4664  srcbitval = *srcbitmap;
4665  }
4666  }
4667  if (destbitmask != 1)
4668  *destbitmap = destbitval;
4669  }
4670  else
4671  {
4672  while (nitems-- > 0)
4673  {
4674  destbitval |= destbitmask;
4675  destbitmask <<= 1;
4676  if (destbitmask == 0x100)
4677  {
4678  *destbitmap++ = destbitval;
4679  destbitmask = 1;
4680  if (nitems > 0)
4681  destbitval = *destbitmap;
4682  }
4683  }
4684  if (destbitmask != 1)
4685  *destbitmap = destbitval;
4686  }
4687 }
#define Assert(condition)
Definition: c.h:670
Datum array_cardinality ( PG_FUNCTION_ARGS  )

Definition at line 1776 of file arrayfuncs.c.

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

1777 {
1779 
1781 }
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
#define AARR_DIMS(a)
Definition: array.h:317
#define AARR_NDIM(a)
Definition: array.h:309
static int array_cmp ( FunctionCallInfo  fcinfo)
static

Definition at line 3760 of file arrayfuncs.c.

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

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

3761 {
3762  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY(0);
3763  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY(1);
3764  Oid collation = PG_GET_COLLATION();
3765  int ndims1 = AARR_NDIM(array1);
3766  int ndims2 = AARR_NDIM(array2);
3767  int *dims1 = AARR_DIMS(array1);
3768  int *dims2 = AARR_DIMS(array2);
3769  int nitems1 = ArrayGetNItems(ndims1, dims1);
3770  int nitems2 = ArrayGetNItems(ndims2, dims2);
3771  Oid element_type = AARR_ELEMTYPE(array1);
3772  int result = 0;
3773  TypeCacheEntry *typentry;
3774  int typlen;
3775  bool typbyval;
3776  char typalign;
3777  int min_nitems;
3778  array_iter it1;
3779  array_iter it2;
3780  int i;
3781  FunctionCallInfoData locfcinfo;
3782 
3783  if (element_type != AARR_ELEMTYPE(array2))
3784  ereport(ERROR,
3785  (errcode(ERRCODE_DATATYPE_MISMATCH),
3786  errmsg("cannot compare arrays of different element types")));
3787 
3788  /*
3789  * We arrange to look up the comparison function only once per series of
3790  * calls, assuming the element type doesn't change underneath us. The
3791  * typcache is used so that we have no memory leakage when being used as
3792  * an index support function.
3793  */
3794  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3795  if (typentry == NULL ||
3796  typentry->type_id != element_type)
3797  {
3798  typentry = lookup_type_cache(element_type,
3800  if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
3801  ereport(ERROR,
3802  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3803  errmsg("could not identify a comparison function for type %s",
3804  format_type_be(element_type))));
3805  fcinfo->flinfo->fn_extra = (void *) typentry;
3806  }
3807  typlen = typentry->typlen;
3808  typbyval = typentry->typbyval;
3809  typalign = typentry->typalign;
3810 
3811  /*
3812  * apply the operator to each pair of array elements.
3813  */
3814  InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
3815  collation, NULL, NULL);
3816 
3817  /* Loop over source data */
3818  min_nitems = Min(nitems1, nitems2);
3819  array_iter_setup(&it1, array1);
3820  array_iter_setup(&it2, array2);
3821 
3822  for (i = 0; i < min_nitems; i++)
3823  {
3824  Datum elt1;
3825  Datum elt2;
3826  bool isnull1;
3827  bool isnull2;
3828  int32 cmpresult;
3829 
3830  /* Get elements, checking for NULL */
3831  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
3832  elt2 = array_iter_next(&it2, &isnull2, i, typlen, typbyval, typalign);
3833 
3834  /*
3835  * We consider two NULLs equal; NULL > not-NULL.
3836  */
3837  if (isnull1 && isnull2)
3838  continue;
3839  if (isnull1)
3840  {
3841  /* arg1 is greater than arg2 */
3842  result = 1;
3843  break;
3844  }
3845  if (isnull2)
3846  {
3847  /* arg1 is less than arg2 */
3848  result = -1;
3849  break;
3850  }
3851 
3852  /* Compare the pair of elements */
3853  locfcinfo.arg[0] = elt1;
3854  locfcinfo.arg[1] = elt2;
3855  locfcinfo.argnull[0] = false;
3856  locfcinfo.argnull[1] = false;
3857  locfcinfo.isnull = false;
3858  cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
3859 
3860  if (cmpresult == 0)
3861  continue; /* equal */
3862 
3863  if (cmpresult < 0)
3864  {
3865  /* arg1 is less than arg2 */
3866  result = -1;
3867  break;
3868  }
3869  else
3870  {
3871  /* arg1 is greater than arg2 */
3872  result = 1;
3873  break;
3874  }
3875  }
3876 
3877  /*
3878  * If arrays contain same data (up to end of shorter one), apply
3879  * additional rules to sort by dimensionality. The relative significance
3880  * of the different bits of information is historical; mainly we just care
3881  * that we don't say "equal" for arrays of different dimensionality.
3882  */
3883  if (result == 0)
3884  {
3885  if (nitems1 != nitems2)
3886  result = (nitems1 < nitems2) ? -1 : 1;
3887  else if (ndims1 != ndims2)
3888  result = (ndims1 < ndims2) ? -1 : 1;
3889  else
3890  {
3891  for (i = 0; i < ndims1; i++)
3892  {
3893  if (dims1[i] != dims2[i])
3894  {
3895  result = (dims1[i] < dims2[i]) ? -1 : 1;
3896  break;
3897  }
3898  }
3899  if (result == 0)
3900  {
3901  int *lbound1 = AARR_LBOUND(array1);
3902  int *lbound2 = AARR_LBOUND(array2);
3903 
3904  for (i = 0; i < ndims1; i++)
3905  {
3906  if (lbound1[i] != lbound2[i])
3907  {
3908  result = (lbound1[i] < lbound2[i]) ? -1 : 1;
3909  break;
3910  }
3911  }
3912  }
3913  }
3914  }
3915 
3916  /* Avoid leaking memory when handed toasted input. */
3917  AARR_FREE_IF_COPY(array1, 0);
3918  AARR_FREE_IF_COPY(array2, 1);
3919 
3920  return result;
3921 }
#define DatumGetInt32(X)
Definition: postgres.h:480
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:801
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:35
bool typbyval
Definition: typcache.h:36
#define OidIsValid(objectId)
Definition: c.h:533
#define PG_GET_COLLATION()
Definition: fmgr.h:155
signed int int32
Definition: c.h:253
FmgrInfo cmp_proc_finfo
Definition: typcache.h:68
FmgrInfo * flinfo
Definition: fmgr.h:71
#define ERROR
Definition: elog.h:43
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
#define AARR_DIMS(a)
Definition: array.h:317
#define AARR_ELEMTYPE(a)
Definition: array.h:315
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
Oid fn_oid
Definition: fmgr.h:56
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:226
#define AARR_LBOUND(a)
Definition: array.h:319
#define AARR_NDIM(a)
Definition: array.h:309
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:112
#define AARR_FREE_IF_COPY(array, n)
Definition: arrayfuncs.c:46
void * fn_extra
Definition: fmgr.h:61
char typalign
Definition: typcache.h:37
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:116
static bool array_contain_compare ( AnyArrayType array1,
AnyArrayType array2,
Oid  collation,
bool  matchall,
void **  fn_extra 
)
static

Definition at line 4039 of file arrayfuncs.c.

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

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

4041 {
4042  bool result = matchall;
4043  Oid element_type = AARR_ELEMTYPE(array1);
4044  TypeCacheEntry *typentry;
4045  int nelems1;
4046  Datum *values2;
4047  bool *nulls2;
4048  int nelems2;
4049  int typlen;
4050  bool typbyval;
4051  char typalign;
4052  int i;
4053  int j;
4054  array_iter it1;
4055  FunctionCallInfoData locfcinfo;
4056 
4057  if (element_type != AARR_ELEMTYPE(array2))
4058  ereport(ERROR,
4059  (errcode(ERRCODE_DATATYPE_MISMATCH),
4060  errmsg("cannot compare arrays of different element types")));
4061 
4062  /*
4063  * We arrange to look up the equality function only once per series of
4064  * calls, assuming the element type doesn't change underneath us. The
4065  * typcache is used so that we have no memory leakage when being used as
4066  * an index support function.
4067  */
4068  typentry = (TypeCacheEntry *) *fn_extra;
4069  if (typentry == NULL ||
4070  typentry->type_id != element_type)
4071  {
4072  typentry = lookup_type_cache(element_type,
4074  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
4075  ereport(ERROR,
4076  (errcode(ERRCODE_UNDEFINED_FUNCTION),
4077  errmsg("could not identify an equality operator for type %s",
4078  format_type_be(element_type))));
4079  *fn_extra = (void *) typentry;
4080  }
4081  typlen = typentry->typlen;
4082  typbyval = typentry->typbyval;
4083  typalign = typentry->typalign;
4084 
4085  /*
4086  * Since we probably will need to scan array2 multiple times, it's
4087  * worthwhile to use deconstruct_array on it. We scan array1 the hard way
4088  * however, since we very likely won't need to look at all of it.
4089  */
4090  if (VARATT_IS_EXPANDED_HEADER(array2))
4091  {
4092  /* This should be safe even if input is read-only */
4093  deconstruct_expanded_array(&(array2->xpn));
4094  values2 = array2->xpn.dvalues;
4095  nulls2 = array2->xpn.dnulls;
4096  nelems2 = array2->xpn.nelems;
4097  }
4098  else
4099  deconstruct_array(&(array2->flt),
4100  element_type, typlen, typbyval, typalign,
4101  &values2, &nulls2, &nelems2);
4102 
4103  /*
4104  * Apply the comparison operator to each pair of array elements.
4105  */
4106  InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
4107  collation, NULL, NULL);
4108 
4109  /* Loop over source data */
4110  nelems1 = ArrayGetNItems(AARR_NDIM(array1), AARR_DIMS(array1));
4111  array_iter_setup(&it1, array1);
4112 
4113  for (i = 0; i < nelems1; i++)
4114  {
4115  Datum elt1;
4116  bool isnull1;
4117 
4118  /* Get element, checking for NULL */
4119  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
4120 
4121  /*
4122  * We assume that the comparison operator is strict, so a NULL can't
4123  * match anything. XXX this diverges from the "NULL=NULL" behavior of
4124  * array_eq, should we act like that?
4125  */
4126  if (isnull1)
4127  {
4128  if (matchall)
4129  {
4130  result = false;
4131  break;
4132  }
4133  continue;
4134  }
4135 
4136  for (j = 0; j < nelems2; j++)
4137  {
4138  Datum elt2 = values2[j];
4139  bool isnull2 = nulls2 ? nulls2[j] : false;
4140  bool oprresult;
4141 
4142  if (isnull2)
4143  continue; /* can't match */
4144 
4145  /*
4146  * Apply the operator to the element pair
4147  */
4148  locfcinfo.arg[0] = elt1;
4149  locfcinfo.arg[1] = elt2;
4150  locfcinfo.argnull[0] = false;
4151  locfcinfo.argnull[1] = false;
4152  locfcinfo.isnull = false;
4153  oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
4154  if (oprresult)
4155  break;
4156  }
4157 
4158  if (j < nelems2)
4159  {
4160  /* found a match for elt1 */
4161  if (!matchall)
4162  {
4163  result = true;
4164  break;
4165  }
4166  }
4167  else
4168  {
4169  /* no match for elt1 */
4170  if (matchall)
4171  {
4172  result = false;
4173  break;
4174  }
4175  }
4176  }
4177 
4178  return result;
4179 }
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:115
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
ExpandedArrayHeader xpn
Definition: array.h:161
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
Datum * dvalues
Definition: array.h:130
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:35
bool typbyval
Definition: typcache.h:36
#define OidIsValid(objectId)
Definition: c.h:533
#define ERROR
Definition: elog.h:43
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
#define DatumGetBool(X)
Definition: postgres.h:401
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
#define AARR_DIMS(a)
Definition: array.h:317
#define AARR_ELEMTYPE(a)
Definition: array.h:315
FmgrInfo eq_opr_finfo
Definition: typcache.h:67
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
Oid fn_oid
Definition: fmgr.h:56
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:226
#define AARR_NDIM(a)
Definition: array.h:309
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:112
#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:3475
char typalign
Definition: typcache.h:37
int errmsg(const char *fmt,...)
Definition: elog.c:797
ArrayType flt
Definition: array.h:160
int i
bool array_contains_nulls ( ArrayType array)

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

3543 {
3544  int nelems;
3545  bits8 *bitmap;
3546  int bitmask;
3547 
3548  /* Easy answer if there's no null bitmap */
3549  if (!ARR_HASNULL(array))
3550  return false;
3551 
3552  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3553 
3554  bitmap = ARR_NULLBITMAP(array);
3555 
3556  /* check whole bytes of the bitmap byte-at-a-time */
3557  while (nelems >= 8)
3558  {
3559  if (*bitmap != 0xFF)
3560  return true;
3561  bitmap++;
3562  nelems -= 8;
3563  }
3564 
3565  /* check last partial byte */
3566  bitmask = 1;
3567  while (nelems > 0)
3568  {
3569  if ((*bitmap & bitmask) == 0)
3570  return true;
3571  bitmask <<= 1;
3572  nelems--;
3573  }
3574 
3575  return false;
3576 }
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_HASNULL(a)
Definition: array.h:272
uint8 bits8
Definition: c.h:272
#define ARR_NDIM(a)
Definition: array.h:271
#define ARR_NULLBITMAP(a)
Definition: array.h:281
static int array_copy ( char *  destptr,
int  nitems,
char *  srcptr,
int  offset,
bits8 nullbitmap,
int  typlen,
bool  typbyval,
char  typalign 
)
static

Definition at line 4594 of file arrayfuncs.c.

References array_nelems_size().

Referenced by array_extract_slice(), and array_insert_slice().

4597 {
4598  int numbytes;
4599 
4600  numbytes = array_nelems_size(srcptr, offset, nullbitmap, nitems,
4601  typlen, typbyval, typalign);
4602  memcpy(destptr, srcptr, numbytes);
4603  return numbytes;
4604 }
static int array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4572
ArrayIterator array_create_iterator ( ArrayType arr,
int  slice_ndim,
ArrayMetaState mstate 
)

Definition at line 4255 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, NULL, 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().

4256 {
4257  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4258 
4259  /*
4260  * Sanity-check inputs --- caller should have got this right already
4261  */
4262  Assert(PointerIsValid(arr));
4263  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4264  elog(ERROR, "invalid arguments to array_create_iterator");
4265 
4266  /*
4267  * Remember basic info about the array and its element type
4268  */
4269  iterator->arr = arr;
4270  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4271  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4272 
4273  if (mstate != NULL)
4274  {
4275  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4276 
4277  iterator->typlen = mstate->typlen;
4278  iterator->typbyval = mstate->typbyval;
4279  iterator->typalign = mstate->typalign;
4280  }
4281  else
4283  &iterator->typlen,
4284  &iterator->typbyval,
4285  &iterator->typalign);
4286 
4287  /*
4288  * Remember the slicing parameters.
4289  */
4290  iterator->slice_ndim = slice_ndim;
4291 
4292  if (slice_ndim > 0)
4293  {
4294  /*
4295  * Get pointers into the array's dims and lbound arrays to represent
4296  * the dims/lbound arrays of a slice. These are the same as the
4297  * rightmost N dimensions of the array.
4298  */
4299  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4300  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4301 
4302  /*
4303  * Compute number of elements in a slice.
4304  */
4305  iterator->slice_len = ArrayGetNItems(slice_ndim,
4306  iterator->slice_dims);
4307 
4308  /*
4309  * Create workspace for building sub-arrays.
4310  */
4311  iterator->slice_values = (Datum *)
4312  palloc(iterator->slice_len * sizeof(Datum));
4313  iterator->slice_nulls = (bool *)
4314  palloc(iterator->slice_len * sizeof(bool));
4315  }
4316 
4317  /*
4318  * Initialize our data pointer and linear element number. These will
4319  * advance through the array during array_iterate().
4320  */
4321  iterator->data_ptr = ARR_DATA_PTR(arr);
4322  iterator->current_item = 0;
4323 
4324  return iterator;
4325 }
bits8 * nullbitmap
Definition: arrayfuncs.c:70
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1989
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_LBOUND(a)
Definition: array.h:277
bool typbyval
Definition: array.h:221
bool * slice_nulls
Definition: arrayfuncs.c:82
#define ERROR
Definition: elog.h:43
Datum * slice_values
Definition: arrayfuncs.c:81
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
int16 typlen
Definition: array.h:220
void * palloc0(Size size)
Definition: mcxt.c:920
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define ARR_NDIM(a)
Definition: array.h:271
char typalign
Definition: array.h:222
void * palloc(Size size)
Definition: mcxt.c:891
Oid element_type
Definition: array.h:219
#define elog
Definition: elog.h:219
#define PointerIsValid(pointer)
Definition: c.h:521
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define ARR_NULLBITMAP(a)
Definition: array.h:281
ArrayType * arr
Definition: arrayfuncs.c:69
Datum array_dims ( PG_FUNCTION_ARGS  )

Definition at line 1654 of file arrayfuncs.c.

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

1655 {
1657  char *p;
1658  int i;
1659  int *dimv,
1660  *lb;
1661 
1662  /*
1663  * 33 since we assume 15 digits per number + ':' +'[]'
1664  *
1665  * +1 for trailing null
1666  */
1667  char buf[MAXDIM * 33 + 1];
1668 
1669  /* Sanity check: does it look like an array at all? */
1670  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1671  PG_RETURN_NULL();
1672 
1673  dimv = AARR_DIMS(v);
1674  lb = AARR_LBOUND(v);
1675 
1676  p = buf;
1677  for (i = 0; i < AARR_NDIM(v); i++)
1678  {
1679  sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1);
1680  p += strlen(p);
1681  }
1682 
1684 }
#define MAXDIM
Definition: c.h:415
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
static char * buf
Definition: pg_test_fsync.c:65
#define AARR_DIMS(a)
Definition: array.h:317
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
text * cstring_to_text(const char *s)
Definition: varlena.c:151
#define AARR_LBOUND(a)
Definition: array.h:319
#define AARR_NDIM(a)
Definition: array.h:309
int i
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum array_eq ( PG_FUNCTION_ARGS  )

Definition at line 3589 of file arrayfuncs.c.

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

Referenced by array_ne().

3590 {
3591  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY(0);
3592  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY(1);
3593  Oid collation = PG_GET_COLLATION();
3594  int ndims1 = AARR_NDIM(array1);
3595  int ndims2 = AARR_NDIM(array2);
3596  int *dims1 = AARR_DIMS(array1);
3597  int *dims2 = AARR_DIMS(array2);
3598  int *lbs1 = AARR_LBOUND(array1);
3599  int *lbs2 = AARR_LBOUND(array2);
3600  Oid element_type = AARR_ELEMTYPE(array1);
3601  bool result = true;
3602  int nitems;
3603  TypeCacheEntry *typentry;
3604  int typlen;
3605  bool typbyval;
3606  char typalign;
3607  array_iter it1;
3608  array_iter it2;
3609  int i;
3610  FunctionCallInfoData locfcinfo;
3611 
3612  if (element_type != AARR_ELEMTYPE(array2))
3613  ereport(ERROR,
3614  (errcode(ERRCODE_DATATYPE_MISMATCH),
3615  errmsg("cannot compare arrays of different element types")));
3616 
3617  /* fast path if the arrays do not have the same dimensionality */
3618  if (ndims1 != ndims2 ||
3619  memcmp(dims1, dims2, ndims1 * sizeof(int)) != 0 ||
3620  memcmp(lbs1, lbs2, ndims1 * sizeof(int)) != 0)
3621  result = false;
3622  else
3623  {
3624  /*
3625  * We arrange to look up the equality function only once per series of
3626  * calls, assuming the element type doesn't change underneath us. The
3627  * typcache is used so that we have no memory leakage when being used
3628  * as an index support function.
3629  */
3630  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3631  if (typentry == NULL ||
3632  typentry->type_id != element_type)
3633  {
3634  typentry = lookup_type_cache(element_type,
3636  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
3637  ereport(ERROR,
3638  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3639  errmsg("could not identify an equality operator for type %s",
3640  format_type_be(element_type))));
3641  fcinfo->flinfo->fn_extra = (void *) typentry;
3642  }
3643  typlen = typentry->typlen;
3644  typbyval = typentry->typbyval;
3645  typalign = typentry->typalign;
3646 
3647  /*
3648  * apply the operator to each pair of array elements.
3649  */
3650  InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
3651  collation, NULL, NULL);
3652 
3653  /* Loop over source data */
3654  nitems = ArrayGetNItems(ndims1, dims1);
3655  array_iter_setup(&it1, array1);
3656  array_iter_setup(&it2, array2);
3657 
3658  for (i = 0; i < nitems; i++)
3659  {
3660  Datum elt1;
3661  Datum elt2;
3662  bool isnull1;
3663  bool isnull2;
3664  bool oprresult;
3665 
3666  /* Get elements, checking for NULL */
3667  elt1 = array_iter_next(&it1, &isnull1, i,
3668  typlen, typbyval, typalign);
3669  elt2 = array_iter_next(&it2, &isnull2, i,
3670  typlen, typbyval, typalign);
3671 
3672  /*
3673  * We consider two NULLs equal; NULL and not-NULL are unequal.
3674  */
3675  if (isnull1 && isnull2)
3676  continue;
3677  if (isnull1 || isnull2)
3678  {
3679  result = false;
3680  break;
3681  }
3682 
3683  /*
3684  * Apply the operator to the element pair
3685  */
3686  locfcinfo.arg[0] = elt1;
3687  locfcinfo.arg[1] = elt2;
3688  locfcinfo.argnull[0] = false;
3689  locfcinfo.argnull[1] = false;
3690  locfcinfo.isnull = false;
3691  oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
3692  if (!oprresult)
3693  {
3694  result = false;
3695  break;
3696  }
3697  }
3698  }
3699 
3700  /* Avoid leaking memory when handed toasted input. */
3701  AARR_FREE_IF_COPY(array1, 0);
3702  AARR_FREE_IF_COPY(array2, 1);
3703 
3704  PG_RETURN_BOOL(result);
3705 }
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:115
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:35
bool typbyval
Definition: typcache.h:36
#define OidIsValid(objectId)
Definition: c.h:533
#define PG_GET_COLLATION()
Definition: fmgr.h:155
#define ERROR
Definition: elog.h:43
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
#define DatumGetBool(X)
Definition: postgres.h:401
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
#define ereport(elevel, rest)
Definition: elog.h:122
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
uintptr_t Datum
Definition: postgres.h:374
#define AARR_DIMS(a)
Definition: array.h:317
#define AARR_ELEMTYPE(a)
Definition: array.h:315
FmgrInfo eq_opr_finfo
Definition: typcache.h:67
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
Oid fn_oid
Definition: fmgr.h:56
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:226
#define AARR_LBOUND(a)
Definition: array.h:319
#define AARR_NDIM(a)
Definition: array.h:309
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:112
#define AARR_FREE_IF_COPY(array, n)
Definition: arrayfuncs.c:46
char typalign
Definition: typcache.h:37
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
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 4755 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().

4766 {
4767  char *destdataptr = ARR_DATA_PTR(newarray);
4768  bits8 *destnullsptr = ARR_NULLBITMAP(newarray);
4769  char *srcdataptr;
4770  int src_offset,
4771  dest_offset,
4772  prod[MAXDIM],
4773  span[MAXDIM],
4774  dist[MAXDIM],
4775  indx[MAXDIM];
4776  int i,
4777  j,
4778  inc;
4779 
4780  src_offset = ArrayGetOffset(ndim, dim, lb, st);
4781  srcdataptr = array_seek(arraydataptr, 0, arraynullsptr, src_offset,
4782  typlen, typbyval, typalign);
4783  mda_get_prod(ndim, dim, prod);
4784  mda_get_range(ndim, span, st, endp);
4785  mda_get_offset_values(ndim, dist, prod, span);
4786  for (i = 0; i < ndim; i++)
4787  indx[i] = 0;
4788  dest_offset = 0;
4789  j = ndim - 1;
4790  do
4791  {
4792  if (dist[j])
4793  {
4794  /* skip unwanted elements */
4795  srcdataptr = array_seek(srcdataptr, src_offset, arraynullsptr,
4796  dist[j],
4797  typlen, typbyval, typalign);
4798  src_offset += dist[j];
4799  }
4800  inc = array_copy(destdataptr, 1,
4801  srcdataptr, src_offset, arraynullsptr,
4802  typlen, typbyval, typalign);
4803  if (destnullsptr)
4804  array_bitmap_copy(destnullsptr, dest_offset,
4805  arraynullsptr, src_offset,
4806  1);
4807  destdataptr += inc;
4808  srcdataptr += inc;
4809  src_offset++;
4810  dest_offset++;
4811  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4812 }
#define MAXDIM
Definition: c.h:415
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
void mda_get_prod(int n, const int *range, int *prod)
Definition: arrayutils.c:134
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4624
static int array_copy(char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4594
#define ARR_DATA_PTR(a)
Definition: array.h:303
void mda_get_offset_values(int n, int *dist, const int *prod, const int *span)
Definition: arrayutils.c:150
uint8 bits8
Definition: c.h:272
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:120
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4524
int mda_next_tuple(int n, int *curr, const int *span)
Definition: arrayutils.c:175
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:281
Datum array_fill ( PG_FUNCTION_ARGS  )

Definition at line 5667 of file arrayfuncs.c.

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

5668 {
5669  ArrayType *dims;
5670  ArrayType *result;
5671  Oid elmtype;
5672  Datum value;
5673  bool isnull;
5674 
5675  if (PG_ARGISNULL(1))
5676  ereport(ERROR,
5677  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5678  errmsg("dimension array or low bound array cannot be null")));
5679 
5680  dims = PG_GETARG_ARRAYTYPE_P(1);
5681 
5682  if (!PG_ARGISNULL(0))
5683  {
5684  value = PG_GETARG_DATUM(0);
5685  isnull = false;
5686  }
5687  else
5688  {
5689  value = 0;
5690  isnull = true;
5691  }
5692 
5693  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5694  if (!OidIsValid(elmtype))
5695  elog(ERROR, "could not determine data type of input");
5696 
5697  result = array_fill_internal(dims, NULL, value, isnull, elmtype, fcinfo);
5698  PG_RETURN_ARRAYTYPE_P(result);
5699 }
static struct @76 value
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5719
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2220
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
static ArrayType * array_fill_internal ( ArrayType dims,
ArrayType lbs,
Datum  value,
bool  isnull,
Oid  elmtype,
FunctionCallInfo  fcinfo 
)
static

Definition at line 5719 of file arrayfuncs.c.

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

Referenced by array_fill(), and array_fill_with_lower_bounds().

5722 {
5723  ArrayType *result;
5724  int *dimv;
5725  int *lbsv;
5726  int ndims;
5727  int nitems;
5728  int deflbs[MAXDIM];
5729  int16 elmlen;
5730  bool elmbyval;
5731  char elmalign;
5732  ArrayMetaState *my_extra;
5733 
5734  /*
5735  * Params checks
5736  */
5737  if (ARR_NDIM(dims) > 1)
5738  ereport(ERROR,
5739  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5740  errmsg("wrong number of array subscripts"),
5741  errdetail("Dimension array must be one dimensional.")));
5742 
5743  if (array_contains_nulls(dims))
5744  ereport(ERROR,
5745  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5746  errmsg("dimension values cannot be null")));
5747 
5748  dimv = (int *) ARR_DATA_PTR(dims);
5749  ndims = (ARR_NDIM(dims) > 0) ? ARR_DIMS(dims)[0] : 0;
5750 
5751  if (ndims < 0) /* we do allow zero-dimension arrays */
5752  ereport(ERROR,
5753  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5754  errmsg("invalid number of dimensions: %d", ndims)));
5755  if (ndims > MAXDIM)
5756  ereport(ERROR,
5757  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5758  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5759  ndims, MAXDIM)));
5760 
5761  if (lbs != NULL)
5762  {
5763  if (ARR_NDIM(lbs) > 1)
5764  ereport(ERROR,
5765  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5766  errmsg("wrong number of array subscripts"),
5767  errdetail("Dimension array must be one dimensional.")));
5768 
5769  if (array_contains_nulls(lbs))
5770  ereport(ERROR,
5771  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5772  errmsg("dimension values cannot be null")));
5773 
5774  if (ndims != ((ARR_NDIM(lbs) > 0) ? ARR_DIMS(lbs)[0] : 0))
5775  ereport(ERROR,
5776  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5777  errmsg("wrong number of array subscripts"),
5778  errdetail("Low bound array has different size than dimensions array.")));
5779 
5780  lbsv = (int *) ARR_DATA_PTR(lbs);
5781  }
5782  else
5783  {
5784  int i;
5785 
5786  for (i = 0; i < MAXDIM; i++)
5787  deflbs[i] = 1;
5788 
5789  lbsv = deflbs;
5790  }
5791 
5792  nitems = ArrayGetNItems(ndims, dimv);
5793 
5794  /* fast track for empty array */
5795  if (nitems <= 0)
5796  return construct_empty_array(elmtype);
5797 
5798  /*
5799  * We arrange to look up info about element type only once per series of
5800  * calls, assuming the element type doesn't change underneath us.
5801  */
5802  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
5803  if (my_extra == NULL)
5804  {
5805  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
5806  sizeof(ArrayMetaState));
5807  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
5808  my_extra->element_type = InvalidOid;
5809  }
5810 
5811  if (my_extra->element_type != elmtype)
5812  {
5813  /* Get info about element type */
5814  get_typlenbyvalalign(elmtype,
5815  &my_extra->typlen,
5816  &my_extra->typbyval,
5817  &my_extra->typalign);
5818  my_extra->element_type = elmtype;
5819  }
5820 
5821  elmlen = my_extra->typlen;
5822  elmbyval = my_extra->typbyval;
5823  elmalign = my_extra->typalign;
5824 
5825  /* compute required space */
5826  if (!isnull)
5827  {
5828  int i;
5829  char *p;
5830  int nbytes;
5831  int totbytes;
5832 
5833  /* make sure data is not toasted */
5834  if (elmlen == -1)
5836 
5837  nbytes = att_addlength_datum(0, elmlen, value);
5838  nbytes = att_align_nominal(nbytes, elmalign);
5839  Assert(nbytes > 0);
5840 
5841  totbytes = nbytes * nitems;
5842 
5843  /* check for overflow of multiplication or total request */
5844  if (totbytes / nbytes != nitems ||
5845  !AllocSizeIsValid(totbytes))
5846  ereport(ERROR,
5847  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5848  errmsg("array size exceeds the maximum allowed (%d)",
5849  (int) MaxAllocSize)));
5850 
5851  /*
5852  * This addition can't overflow, but it might cause us to go past
5853  * MaxAllocSize. We leave it to palloc to complain in that case.
5854  */
5855  totbytes += ARR_OVERHEAD_NONULLS(ndims);
5856 
5857  result = create_array_envelope(ndims, dimv, lbsv, totbytes,
5858  elmtype, 0);
5859 
5860  p = ARR_DATA_PTR(result);
5861  for (i = 0; i < nitems; i++)
5862  p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, p);
5863  }
5864  else
5865  {
5866  int nbytes;
5867  int dataoffset;
5868 
5869  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
5870  nbytes = dataoffset;
5871 
5872  result = create_array_envelope(ndims, dimv, lbsv, nbytes,
5873  elmtype, dataoffset);
5874 
5875  /* create_array_envelope already zeroed the bitmap, so we're done */
5876  }
5877 
5878  return result;
5879 }
signed short int16
Definition: c.h:252
static struct @76 value
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
MemoryContext fn_mcxt
Definition: fmgr.h:62
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define MAXDIM
Definition: c.h:415
static ArrayType * create_array_envelope(int ndims, int *dimv, int *lbv, int nbytes, Oid elmtype, int dataoffset)
Definition: arrayfuncs.c:5702
static int ArrayCastAndSet(Datum src, int typlen, bool typbyval, char typalign, char *dest)
Definition: arrayfuncs.c:4485
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1989
#define PointerGetDatum(X)
Definition: postgres.h:564
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3424
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
bool typbyval
Definition: array.h:221
FmgrInfo * flinfo
Definition: fmgr.h:71
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
int16 typlen
Definition: array.h:220
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
void * fn_extra
Definition: fmgr.h:61
#define ARR_NDIM(a)
Definition: array.h:271
char typalign
Definition: array.h:222
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
int i
Oid element_type
Definition: array.h:219
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:196
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3542
Datum array_fill_with_lower_bounds ( PG_FUNCTION_ARGS  )

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

5627 {
5628  ArrayType *dims;
5629  ArrayType *lbs;
5630  ArrayType *result;
5631  Oid elmtype;
5632  Datum value;
5633  bool isnull;
5634 
5635  if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
5636  ereport(ERROR,
5637  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5638  errmsg("dimension array or low bound array cannot be null")));
5639 
5640  dims = PG_GETARG_ARRAYTYPE_P(1);
5641  lbs = PG_GETARG_ARRAYTYPE_P(2);
5642 
5643  if (!PG_ARGISNULL(0))
5644  {
5645  value = PG_GETARG_DATUM(0);
5646  isnull = false;
5647  }
5648  else
5649  {
5650  value = 0;
5651  isnull = true;
5652  }
5653 
5654  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5655  if (!OidIsValid(elmtype))
5656  elog(ERROR, "could not determine data type of input");
5657 
5658  result = array_fill_internal(dims, lbs, value, isnull, elmtype, fcinfo);
5659  PG_RETURN_ARRAYTYPE_P(result);
5660 }
static struct @76 value
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5719
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2220
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4417 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4418 {
4419  if (iterator->slice_ndim > 0)
4420  {
4421  pfree(iterator->slice_values);
4422  pfree(iterator->slice_nulls);
4423  }
4424  pfree(iterator);
4425 }
bool * slice_nulls
Definition: arrayfuncs.c:82
void pfree(void *pointer)
Definition: mcxt.c:992
Datum * slice_values
Definition: arrayfuncs.c:81
Datum array_ge ( PG_FUNCTION_ARGS  )

Definition at line 3742 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3743 {
3744  PG_RETURN_BOOL(array_cmp(fcinfo) >= 0);
3745 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3760
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
Datum array_get_element ( Datum  arraydatum,
int  nSubscripts,
int *  indx,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign,
bool isNull 
)

Definition at line 1806 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, NULL, and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by array_ref(), and ExecEvalArrayRef().

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

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

Definition at line 4439 of file arrayfuncs.c.

References NULL.

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

4440 {
4441  if (nullbitmap == NULL)
4442  return false; /* assume not null */
4443  if (nullbitmap[offset / 8] & (1 << (offset % 8)))
4444  return false; /* not null */
4445  return true;
4446 }
#define NULL
Definition: c.h:226
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 2015 of file arrayfuncs.c.

References ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_extract_slice(), array_slice_size(), ArrayGetNItems(), construct_empty_array(), ArrayType::dataoffset, DatumGetArrayTypeP, DatumGetPointer, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, InvalidOid, MAXDIM, mda_get_range(), ArrayType::ndim, NULL, palloc0(), PointerGetDatum, and SET_VARSIZE.

Referenced by ExecEvalArrayRef().

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

Definition at line 3730 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3731 {
3732  PG_RETURN_BOOL(array_cmp(fcinfo) > 0);
3733 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3760
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
Datum array_in ( PG_FUNCTION_ARGS  )

Definition at line 171 of file arrayfuncs.c.

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

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

4839 {
4840  char *destPtr = ARR_DATA_PTR(destArray);
4841  char *origPtr = ARR_DATA_PTR(origArray);
4842  char *srcPtr = ARR_DATA_PTR(srcArray);
4843  bits8 *destBitmap = ARR_NULLBITMAP(destArray);
4844  bits8 *origBitmap = ARR_NULLBITMAP(origArray);
4845  bits8 *srcBitmap = ARR_NULLBITMAP(srcArray);
4846  int orignitems = ArrayGetNItems(ARR_NDIM(origArray),
4847  ARR_DIMS(origArray));
4848  int dest_offset,
4849  orig_offset,
4850  src_offset,
4851  prod[MAXDIM],
4852  span[MAXDIM],
4853  dist[MAXDIM],
4854  indx[MAXDIM];
4855  int i,
4856  j,
4857  inc;
4858 
4859  dest_offset = ArrayGetOffset(ndim, dim, lb, st);
4860  /* copy items before the slice start */
4861  inc = array_copy(destPtr, dest_offset,
4862  origPtr, 0, origBitmap,
4863  typlen, typbyval, typalign);
4864  destPtr += inc;
4865  origPtr += inc;
4866  if (destBitmap)
4867  array_bitmap_copy(destBitmap, 0, origBitmap, 0, dest_offset);
4868  orig_offset = dest_offset;
4869  mda_get_prod(ndim, dim, prod);
4870  mda_get_range(ndim, span, st, endp);
4871  mda_get_offset_values(ndim, dist, prod, span);
4872  for (i = 0; i < ndim; i++)
4873  indx[i] = 0;
4874  src_offset = 0;
4875  j = ndim - 1;
4876  do
4877  {
4878  /* Copy/advance over elements between here and next part of slice */
4879  if (dist[j])
4880  {
4881  inc = array_copy(destPtr, dist[j],
4882  origPtr, orig_offset, origBitmap,
4883  typlen, typbyval, typalign);
4884  destPtr += inc;
4885  origPtr += inc;
4886  if (destBitmap)
4887  array_bitmap_copy(destBitmap, dest_offset,
4888  origBitmap, orig_offset,
4889  dist[j]);
4890  dest_offset += dist[j];
4891  orig_offset += dist[j];
4892  }
4893  /* Copy new element at this slice position */
4894  inc = array_copy(destPtr, 1,
4895  srcPtr, src_offset, srcBitmap,
4896  typlen, typbyval, typalign);
4897  if (destBitmap)
4898  array_bitmap_copy(destBitmap, dest_offset,
4899  srcBitmap, src_offset,
4900  1);
4901  destPtr += inc;
4902  srcPtr += inc;
4903  dest_offset++;
4904  src_offset++;
4905  /* Advance over old element at this slice position */
4906  origPtr = array_seek(origPtr, orig_offset, origBitmap, 1,
4907  typlen, typbyval, typalign);
4908  orig_offset++;
4909  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4910 
4911  /* don't miss any data at the end */
4912  array_copy(destPtr, orignitems - orig_offset,
4913  origPtr, orig_offset, origBitmap,
4914  typlen, typbyval, typalign);
4915  if (destBitmap)
4916  array_bitmap_copy(destBitmap, dest_offset,
4917  origBitmap, orig_offset,
4918  orignitems - orig_offset);
4919 }
#define MAXDIM
Definition: c.h:415
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
void mda_get_prod(int n, const int *range, int *prod)
Definition: arrayutils.c:134
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4624
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
static int array_copy(char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4594
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
void mda_get_offset_values(int n, int *dist, const int *prod, const int *span)
Definition: arrayutils.c:150
uint8 bits8
Definition: c.h:272
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:120
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4524
#define ARR_NDIM(a)
Definition: array.h:271
int mda_next_tuple(int n, int *curr, const int *span)
Definition: arrayutils.c:175
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:281
static bool array_isspace ( char  ch)
static

Definition at line 431 of file arrayfuncs.c.

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

432 {
433  if (ch == ' ' ||
434  ch == '\t' ||
435  ch == '\n' ||
436  ch == '\r' ||
437  ch == '\v' ||
438  ch == '\f')
439  return true;
440  return false;
441 }
bool array_iterate ( ArrayIterator  iterator,
Datum value,
bool isnull 
)

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

4335 {
4336  /* Done if we have reached the end of the array */
4337  if (iterator->current_item >= iterator->nitems)
4338  return false;
4339 
4340  if (iterator->slice_ndim == 0)
4341  {
4342  /*
4343  * Scalar case: return one element.
4344  */
4345  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4346  {
4347  *isnull = true;
4348  *value = (Datum) 0;
4349  }
4350  else
4351  {
4352  /* non-NULL, so fetch the individual Datum to return */
4353  char *p = iterator->data_ptr;
4354 
4355  *isnull = false;
4356  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4357 
4358  /* Move our data pointer forward to the next element */
4359  p = att_addlength_pointer(p, iterator->typlen, p);
4360  p = (char *) att_align_nominal(p, iterator->typalign);
4361  iterator->data_ptr = p;
4362  }
4363  }
4364  else
4365  {
4366  /*
4367  * Slice case: build and return an array of the requested size.
4368  */
4369  ArrayType *result;
4370  Datum *values = iterator->slice_values;
4371  bool *nulls = iterator->slice_nulls;
4372  char *p = iterator->data_ptr;
4373  int i;
4374 
4375  for (i = 0; i < iterator->slice_len; i++)
4376  {
4377  if (array_get_isnull(iterator->nullbitmap,
4378  iterator->current_item++))
4379  {
4380  nulls[i] = true;
4381  values[i] = (Datum) 0;
4382  }
4383  else
4384  {
4385  nulls[i] = false;
4386  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4387 
4388  /* Move our data pointer forward to the next element */
4389  p = att_addlength_pointer(p, iterator->typlen, p);
4390  p = (char *) att_align_nominal(p, iterator->typalign);
4391  }
4392  }
4393 
4394  iterator->data_ptr = p;
4395 
4396  result = construct_md_array(values,
4397  nulls,
4398  iterator->slice_ndim,
4399  iterator->slice_dims,
4400  iterator->slice_lbound,
4401  ARR_ELEMTYPE(iterator->arr),
4402  iterator->typlen,
4403  iterator->typbyval,
4404  iterator->typalign);
4405 
4406  *isnull = false;
4407  *value = PointerGetDatum(result);
4408  }
4409 
4410  return true;
4411 }
bits8 * nullbitmap
Definition: arrayfuncs.c:70
static struct @76 value
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define PointerGetDatum(X)
Definition: postgres.h:564
bool * slice_nulls
Definition: arrayfuncs.c:82
Datum * slice_values
Definition: arrayfuncs.c:81
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
uintptr_t Datum
Definition: postgres.h:374
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4439
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
int i
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3340
#define ARR_ELEMTYPE(a)
Definition: array.h:273
ArrayType * arr
Definition: arrayfuncs.c:69
Datum array_larger ( PG_FUNCTION_ARGS  )

Definition at line 5521 of file arrayfuncs.c.

References array_cmp(), PG_GETARG_DATUM, and PG_RETURN_DATUM.

5522 {
5523  if (array_cmp(fcinfo) > 0)
5525  else
5527 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3760
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
Datum array_le ( PG_FUNCTION_ARGS  )

Definition at line 3736 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3737 {
3738  PG_RETURN_BOOL(array_cmp(fcinfo) <= 0);
3739 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3760
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
Datum array_length ( PG_FUNCTION_ARGS  )

Definition at line 1749 of file arrayfuncs.c.

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

1750 {
1752  int reqdim = PG_GETARG_INT32(1);
1753  int *dimv;
1754  int result;
1755 
1756  /* Sanity check: does it look like an array at all? */
1757  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1758  PG_RETURN_NULL();
1759 
1760  /* Sanity check: was the requested dim valid */
1761  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1762  PG_RETURN_NULL();
1763 
1764  dimv = AARR_DIMS(v);
1765 
1766  result = dimv[reqdim - 1];
1767 
1768  PG_RETURN_INT32(result);
1769 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define MAXDIM
Definition: c.h:415
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
#define AARR_DIMS(a)
Definition: array.h:317
#define AARR_NDIM(a)
Definition: array.h:309
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum array_lower ( PG_FUNCTION_ARGS  )

Definition at line 1692 of file arrayfuncs.c.

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

1693 {
1695  int reqdim = PG_GETARG_INT32(1);
1696  int *lb;
1697  int result;
1698 
1699  /* Sanity check: does it look like an array at all? */
1700  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1701  PG_RETURN_NULL();
1702 
1703  /* Sanity check: was the requested dim valid */
1704  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1705  PG_RETURN_NULL();
1706 
1707  lb = AARR_LBOUND(v);
1708  result = lb[reqdim - 1];
1709 
1710  PG_RETURN_INT32(result);
1711 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define MAXDIM
Definition: c.h:415
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
#define AARR_LBOUND(a)
Definition: array.h:319
#define AARR_NDIM(a)
Definition: array.h:309
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum array_lt ( PG_FUNCTION_ARGS  )

Definition at line 3724 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3725 {
3726  PG_RETURN_BOOL(array_cmp(fcinfo) < 0);
3727 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3760
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
Datum array_map ( FunctionCallInfo  fcinfo,
Oid  retType,
ArrayMapState amstate 
)

Definition at line 3120 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_LBOUND, AARR_NDIM, AllocSizeIsValid, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, 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, ArrayMetaState::element_type, ArrayType::elemtype, elog, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoData::flinfo, FmgrInfo::fn_strict, FunctionCallInvoke, get_typlenbyvalalign(), i, ArrayMapState::inp_extra, FunctionCallInfoData::isnull, MaxAllocSize, FunctionCallInfoData::nargs, ArrayType::ndim, palloc(), palloc0(), pfree(), PG_ARGISNULL, PG_DETOAST_DATUM, PG_GETARG_ANY_ARRAY, PG_RETURN_ARRAYTYPE_P, PointerGetDatum, ArrayMapState::ret_extra, SET_VARSIZE, ArrayMetaState::typalign, ArrayMetaState::typbyval, ArrayMetaState::typlen, and values.

Referenced by ExecEvalArrayCoerceExpr().

3121 {
3122  AnyArrayType *v;
3123  ArrayType *result;
3124  Datum *values;
3125  bool *nulls;
3126  int *dim;
3127  int ndim;
3128  int nitems;
3129  int i;
3130  int32 nbytes = 0;
3131  int32 dataoffset;
3132  bool hasnulls;
3133  Oid inpType;
3134  int inp_typlen;
3135  bool inp_typbyval;
3136  char inp_typalign;
3137  int typlen;
3138  bool typbyval;
3139  char typalign;
3140  array_iter iter;
3141  ArrayMetaState *inp_extra;
3142  ArrayMetaState *ret_extra;
3143 
3144  /* Get input array */
3145  if (fcinfo->nargs < 1)
3146  elog(ERROR, "invalid nargs: %d", fcinfo->nargs);
3147  if (PG_ARGISNULL(0))
3148  elog(ERROR, "null input array");
3149  v = PG_GETARG_ANY_ARRAY(0);
3150 
3151  inpType = AARR_ELEMTYPE(v);
3152  ndim = AARR_NDIM(v);
3153  dim = AARR_DIMS(v);
3154  nitems = ArrayGetNItems(ndim, dim);
3155 
3156  /* Check for empty array */
3157  if (nitems <= 0)
3158  {
3159  /* Return empty array */
3161  }
3162 
3163  /*
3164  * We arrange to look up info about input and return element types only
3165  * once per series of calls, assuming the element type doesn't change
3166  * underneath us.
3167  */
3168  inp_extra = &amstate->inp_extra;
3169  ret_extra = &amstate->ret_extra;
3170 
3171  if (inp_extra->element_type != inpType)
3172  {
3173  get_typlenbyvalalign(inpType,
3174  &inp_extra->typlen,
3175  &inp_extra->typbyval,
3176  &inp_extra->typalign);
3177  inp_extra->element_type = inpType;
3178  }
3179  inp_typlen = inp_extra->typlen;
3180  inp_typbyval = inp_extra->typbyval;
3181  inp_typalign = inp_extra->typalign;
3182 
3183  if (ret_extra->element_type != retType)
3184  {
3185  get_typlenbyvalalign(retType,
3186  &ret_extra->typlen,
3187  &ret_extra->typbyval,
3188  &ret_extra->typalign);
3189  ret_extra->element_type = retType;
3190  }
3191  typlen = ret_extra->typlen;
3192  typbyval = ret_extra->typbyval;
3193  typalign = ret_extra->typalign;
3194 
3195  /* Allocate temporary arrays for new values */
3196  values = (Datum *) palloc(nitems * sizeof(Datum));
3197  nulls = (bool *) palloc(nitems * sizeof(bool));
3198 
3199  /* Loop over source data */
3200  array_iter_setup(&iter, v);
3201  hasnulls = false;
3202 
3203  for (i = 0; i < nitems; i++)
3204  {
3205  bool callit = true;
3206 
3207  /* Get source element, checking for NULL */
3208  fcinfo->arg[0] = array_iter_next(&iter, &fcinfo->argnull[0], i,
3209  inp_typlen, inp_typbyval, inp_typalign);
3210 
3211  /*
3212  * Apply the given function to source elt and extra args.
3213  */
3214  if (fcinfo->flinfo->fn_strict)
3215  {
3216  int j;
3217 
3218  for (j = 0; j < fcinfo->nargs; j++)
3219  {
3220  if (fcinfo->argnull[j])
3221  {
3222  callit = false;
3223  break;
3224  }
3225  }
3226  }
3227 
3228  if (callit)
3229  {
3230  fcinfo->isnull = false;
3231  values[i] = FunctionCallInvoke(fcinfo);
3232  }
3233  else
3234  fcinfo->isnull = true;
3235 
3236  nulls[i] = fcinfo->isnull;
3237  if (fcinfo->isnull)
3238  hasnulls = true;
3239  else
3240  {
3241  /* Ensure data is not toasted */
3242  if (typlen == -1)
3243  values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
3244  /* Update total result size */
3245  nbytes = att_addlength_datum(nbytes, typlen, values[i]);
3246  nbytes = att_align_nominal(nbytes, typalign);
3247  /* check for overflow of total request */
3248  if (!AllocSizeIsValid(nbytes))
3249  ereport(ERROR,
3250  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3251  errmsg("array size exceeds the maximum allowed (%d)",
3252  (int) MaxAllocSize)));
3253  }
3254  }
3255 
3256  /* Allocate and initialize the result array */
3257  if (hasnulls)
3258  {
3259  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3260  nbytes += dataoffset;
3261  }
3262  else
3263  {
3264  dataoffset = 0; /* marker for no null bitmap */
3265  nbytes += ARR_OVERHEAD_NONULLS(ndim);
3266  }
3267  result = (ArrayType *) palloc0(nbytes);
3268  SET_VARSIZE(result, nbytes);
3269  result->ndim = ndim;
3270  result->dataoffset = dataoffset;
3271  result->elemtype = retType;
3272  memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
3273  memcpy(ARR_LBOUND(result), AARR_LBOUND(v), ndim * sizeof(int));
3274 
3275  /*
3276  * Note: do not risk trying to pfree the results of the called function
3277  */
3278  CopyArrayEls(result,
3279  values, nulls, nitems,
3280  typlen, typbyval, typalign,
3281  false);
3282 
3283  pfree(values);
3284  pfree(nulls);
3285 
3286  PG_RETURN_ARRAYTYPE_P(result);
3287 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1989
#define PointerGetDatum(X)
Definition: postgres.h:564
int32 dataoffset
Definition: array.h:80
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3424
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
signed int int32
Definition: c.h:253
#define ARR_LBOUND(a)
Definition: array.h:277
bool typbyval
Definition: array.h:221
FmgrInfo * flinfo
Definition: fmgr.h:71
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
bool fn_strict
Definition: fmgr.h:58
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
Oid elemtype
Definition: array.h:81
#define ARR_DIMS(a)
Definition: array.h:275
ArrayMetaState inp_extra
Definition: array.h:234
int16 typlen
Definition: array.h:220
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define ereport(elevel, rest)
Definition: elog.h:122
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void * palloc0(Size size)
Definition: mcxt.c:920
uintptr_t Datum
Definition: postgres.h:374
#define AARR_DIMS(a)
Definition: array.h:317
#define AARR_ELEMTYPE(a)
Definition: array.h:315
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define AARR_LBOUND(a)
Definition: array.h:319
#define AARR_NDIM(a)
Definition: array.h:309
ArrayMetaState ret_extra
Definition: array.h:235
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:956
char typalign
Definition: array.h:222
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
Oid element_type
Definition: array.h:219
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:196
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
#define elog
Definition: elog.h:219
int ndim
Definition: array.h:79
Datum array_ndims ( PG_FUNCTION_ARGS  )

Definition at line 1638 of file arrayfuncs.c.

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

1639 {
1641 
1642  /* Sanity check: does it look like an array at all? */
1643  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1644  PG_RETURN_NULL();
1645 
1647 }
#define MAXDIM
Definition: c.h:415
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
#define AARR_NDIM(a)
Definition: array.h:309
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum array_ne ( PG_FUNCTION_ARGS  )

Definition at line 3718 of file arrayfuncs.c.

References array_eq(), DatumGetBool, and PG_RETURN_BOOL.

3719 {
3721 }
#define DatumGetBool(X)
Definition: postgres.h:401
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
Datum array_eq(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:3589
static int array_nelems_size ( char *  ptr,
int  offset,
bits8 nullbitmap,
int  nitems,
int  typlen,
bool  typbyval,
char  typalign 
)
static

Definition at line 4572 of file arrayfuncs.c.

References array_seek().

Referenced by array_copy(), and array_set_slice().

4574 {
4575  return array_seek(ptr, offset, nullbitmap, nitems,
4576  typlen, typbyval, typalign) - ptr;
4577 }
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4524
Datum array_out ( PG_FUNCTION_ARGS  )

Definition at line 1011 of file arrayfuncs.c.

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

Referenced by anyarray_out().

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

Definition at line 1254 of file arrayfuncs.c.

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

Referenced by int2vectorrecv(), and oidvectorrecv().

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

Definition at line 3063 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

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

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

6239 {
6240  ArrayType *array;
6241  Datum search = PG_GETARG_DATUM(1);
6242  bool search_isnull = PG_ARGISNULL(1);
6243 
6244  if (PG_ARGISNULL(0))
6245  PG_RETURN_NULL();
6246  array = PG_GETARG_ARRAYTYPE_P(0);
6247 
6248  array = array_replace_internal(array,
6249  search, search_isnull,
6250  (Datum) 0, true,
6251  true, PG_GET_COLLATION(),
6252  fcinfo);
6253  PG_RETURN_ARRAYTYPE_P(array);
6254 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_GET_COLLATION()
Definition: fmgr.h:155
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
uintptr_t Datum
Definition: postgres.h:374
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:5980
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum array_replace ( PG_FUNCTION_ARGS  )

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

6261 {
6262  ArrayType *array;
6263  Datum search = PG_GETARG_DATUM(1);
6264  bool search_isnull = PG_ARGISNULL(1);
6265  Datum replace = PG_GETARG_DATUM(2);
6266  bool replace_isnull = PG_ARGISNULL(2);
6267 
6268  if (PG_ARGISNULL(0))
6269  PG_RETURN_NULL();
6270  array = PG_GETARG_ARRAYTYPE_P(0);
6271 
6272  array = array_replace_internal(array,
6273  search, search_isnull,
6274  replace, replace_isnull,
6275  false, PG_GET_COLLATION(),
6276  fcinfo);
6277  PG_RETURN_ARRAYTYPE_P(array);
6278 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_GET_COLLATION()
Definition: fmgr.h:155
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
uintptr_t Datum
Definition: postgres.h:374
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:5980
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define PG_RETURN_NULL()
Definition: fmgr.h:289
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 5980 of file arrayfuncs.c.

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

Referenced by array_remove(), and array_replace().

5985 {
5986  ArrayType *result;
5987  Oid element_type;
5988  Datum *values;
5989  bool *nulls;
5990  int *dim;
5991  int ndim;
5992  int nitems,
5993  nresult;
5994  int i;
5995  int32 nbytes = 0;
5996  int32 dataoffset;
5997  bool hasnulls;
5998  int typlen;
5999  bool typbyval;
6000  char typalign;
6001  char *arraydataptr;
6002  bits8 *bitmap;
6003  int bitmask;
6004  bool changed = false;
6005  TypeCacheEntry *typentry;
6006  FunctionCallInfoData locfcinfo;
6007 
6008  element_type = ARR_ELEMTYPE(array);
6009  ndim = ARR_NDIM(array);
6010  dim = ARR_DIMS(array);
6011  nitems = ArrayGetNItems(ndim, dim);
6012 
6013  /* Return input array unmodified if it is empty */
6014  if (nitems <= 0)
6015  return array;
6016 
6017  /*
6018  * We can't remove elements from multi-dimensional arrays, since the
6019  * result might not be rectangular.
6020  */
6021  if (remove && ndim > 1)
6022  ereport(ERROR,
6023  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6024  errmsg("removing elements from multidimensional arrays is not supported")));
6025 
6026  /*
6027  * We arrange to look up the equality function only once per series of
6028  * calls, assuming the element type doesn't change underneath us.
6029  */
6030  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
6031  if (typentry == NULL ||
6032  typentry->type_id != element_type)
6033  {
6034  typentry = lookup_type_cache(element_type,
6036  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
6037  ereport(ERROR,
6038  (errcode(ERRCODE_UNDEFINED_FUNCTION),
6039  errmsg("could not identify an equality operator for type %s",
6040  format_type_be(element_type))));
6041  fcinfo->flinfo->fn_extra = (void *) typentry;
6042  }
6043  typlen = typentry->typlen;
6044  typbyval = typentry->typbyval;
6045  typalign = typentry->typalign;
6046 
6047  /*
6048  * Detoast values if they are toasted. The replacement value must be
6049  * detoasted for insertion into the result array, while detoasting the
6050  * search value only once saves cycles.
6051  */
6052  if (typlen == -1)
6053  {
6054  if (!search_isnull)
6055  search = PointerGetDatum(PG_DETOAST_DATUM(search));
6056  if (!replace_isnull)
6057  replace = PointerGetDatum(PG_DETOAST_DATUM(replace));
6058  }
6059 
6060  /* Prepare to apply the comparison operator */
6061  InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
6062  collation, NULL, NULL);
6063 
6064  /* Allocate temporary arrays for new values */
6065  values = (Datum *) palloc(nitems * sizeof(Datum));
6066  nulls = (bool *) palloc(nitems * sizeof(bool));
6067 
6068  /* Loop over source data */
6069  arraydataptr = ARR_DATA_PTR(array);
6070  bitmap = ARR_NULLBITMAP(array);
6071  bitmask = 1;
6072  hasnulls = false;
6073  nresult = 0;
6074 
6075  for (i = 0; i < nitems; i++)
6076  {
6077  Datum elt;
6078  bool isNull;
6079  bool oprresult;
6080  bool skip = false;
6081 
6082  /* Get source element, checking for NULL */
6083  if (bitmap && (*bitmap & bitmask) == 0)
6084  {
6085  isNull = true;
6086  /* If searching for NULL, we have a match */
6087  if (search_isnull)
6088  {
6089  if (remove)
6090  {
6091  skip = true;
6092  changed = true;
6093  }
6094  else if (!replace_isnull)
6095  {
6096  values[nresult] = replace;
6097  isNull = false;
6098  changed = true;
6099  }
6100  }
6101  }
6102  else
6103  {
6104  isNull = false;
6105  elt = fetch_att(arraydataptr, typbyval, typlen);
6106  arraydataptr = att_addlength_datum(arraydataptr, typlen, elt);
6107  arraydataptr = (char *) att_align_nominal(arraydataptr, typalign);
6108 
6109  if (search_isnull)
6110  {
6111  /* no match possible, keep element */
6112  values[nresult] = elt;
6113  }
6114  else
6115  {
6116  /*
6117  * Apply the operator to the element pair
6118  */
6119  locfcinfo.arg[0] = elt;
6120  locfcinfo.arg[1] = search;
6121  locfcinfo.argnull[0] = false;
6122  locfcinfo.argnull[1] = false;
6123  locfcinfo.isnull = false;
6124  oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
6125  if (!oprresult)
6126  {
6127  /* no match, keep element */
6128  values[nresult] = elt;
6129  }
6130  else
6131  {
6132  /* match, so replace or delete */
6133  changed = true;
6134  if (remove)
6135  skip = true;
6136  else
6137  {
6138  values[nresult] = replace;
6139  isNull = replace_isnull;
6140  }
6141  }
6142  }
6143  }
6144 
6145  if (!skip)
6146  {
6147  nulls[nresult] = isNull;
6148  if (isNull)
6149  hasnulls = true;
6150  else
6151  {
6152  /* Update total result size */
6153  nbytes = att_addlength_datum(nbytes, typlen, values[nresult]);
6154  nbytes = att_align_nominal(nbytes, typalign);
6155  /* check for overflow of total request */
6156  if (!AllocSizeIsValid(nbytes))
6157  ereport(ERROR,
6158  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
6159  errmsg("array size exceeds the maximum allowed (%d)",
6160  (int) MaxAllocSize)));
6161  }
6162  nresult++;
6163  }
6164 
6165  /* advance bitmap pointer if any */
6166  if (bitmap)
6167  {
6168  bitmask <<= 1;
6169  if (bitmask == 0x100)
6170  {
6171  bitmap++;
6172  bitmask = 1;
6173  }
6174  }
6175  }
6176 
6177  /*
6178  * If not changed just return the original array
6179  */
6180  if (!changed)
6181  {
6182  pfree(values);
6183  pfree(nulls);
6184  return array;
6185  }
6186 
6187  /* If all elements were removed return an empty array */
6188  if (nresult == 0)
6189  {
6190  pfree(values);
6191  pfree(nulls);
6192  return construct_empty_array(element_type);
6193  }
6194 
6195  /* Allocate and initialize the result array */
6196  if (hasnulls)
6197  {
6198  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nresult);
6199  nbytes += dataoffset;
6200  }
6201  else
6202  {
6203  dataoffset = 0; /* marker for no null bitmap */
6204  nbytes += ARR_OVERHEAD_NONULLS(ndim);
6205  }
6206  result = (ArrayType *) palloc0(nbytes);
6207  SET_VARSIZE(result, nbytes);
6208  result->ndim = ndim;
6209  result->dataoffset = dataoffset;
6210  result->elemtype = element_type;
6211  memcpy(ARR_DIMS(result), ARR_DIMS(array), ndim * sizeof(int));
6212  memcpy(ARR_LBOUND(result), ARR_LBOUND(array), ndim * sizeof(int));
6213 
6214  if (remove)
6215  {
6216  /* Adjust the result length */
6217  ARR_DIMS(result)[0] = nresult;
6218  }
6219 
6220  /* Insert data into result array */
6221  CopyArrayEls(result,
6222  values, nulls, nresult,
6223  typlen, typbyval, typalign,
6224  false);
6225 
6226  pfree(values);
6227  pfree(nulls);
6228 
6229  return result;
6230 }
static void skip(struct vars *v)
Definition: regc_lex.c:1109
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define PointerGetDatum(X)
Definition: postgres.h:564
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:115
int32 dataoffset
Definition: array.h:80
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3424
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:35
bool typbyval
Definition: typcache.h:36
#define OidIsValid(objectId)
Definition: c.h:533
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
signed int int32
Definition: c.h:253
#define ARR_LBOUND(a)
Definition: array.h:277
FmgrInfo * flinfo
Definition: fmgr.h:71
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:81
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
#define DatumGetBool(X)
Definition: postgres.h:401
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
#define ereport(elevel, rest)
Definition: elog.h:122
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
uint8 bits8
Definition: c.h:272
void * palloc0(Size size)
Definition: mcxt.c:920
uintptr_t Datum
Definition: postgres.h:374
FmgrInfo eq_opr_finfo
Definition: typcache.h:67
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
Oid fn_oid
Definition: fmgr.h:56
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:226
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:112
void * fn_extra
Definition: fmgr.h:61
#define ARR_NDIM(a)
Definition: array.h:271
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:956
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
char typalign
Definition: typcache.h:37
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
int i
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:196
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define ARR_NULLBITMAP(a)
Definition: array.h:281
int ndim
Definition: array.h:79
static char * array_seek ( char *  ptr,
int  offset,
bits8 nullbitmap,
int  nitems,
int  typlen,
bool  typbyval,
char  typalign 
)
static

Definition at line 4524 of file arrayfuncs.c.

References att_addlength_pointer, att_align_nominal, and i.

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

4526 {
4527  int bitmask;
4528  int i;
4529 
4530  /* easy if fixed-size elements and no NULLs */
4531  if (typlen > 0 && !nullbitmap)
4532  return ptr + nitems * ((Size) att_align_nominal(typlen, typalign));
4533 
4534  /* seems worth having separate loops for NULL and no-NULLs cases */
4535  if (nullbitmap)
4536  {
4537  nullbitmap += offset / 8;
4538  bitmask = 1 << (offset % 8);
4539 
4540  for (i = 0; i < nitems; i++)
4541  {
4542  if (*nullbitmap & bitmask)
4543  {
4544  ptr = att_addlength_pointer(ptr, typlen, ptr);
4545  ptr = (char *) att_align_nominal(ptr, typalign);
4546  }
4547  bitmask <<= 1;
4548  if (bitmask == 0x100)
4549  {
4550  nullbitmap++;
4551  bitmask = 1;
4552  }
4553  }
4554  }
4555  else
4556  {
4557  for (i = 0; i < nitems; i++)
4558  {
4559  ptr = att_addlength_pointer(ptr, typlen, ptr);
4560  ptr = (char *) att_align_nominal(ptr, typalign);
4561  }
4562  }
4563  return ptr;
4564 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
size_t Size
Definition: c.h:352
int i
Datum array_send ( PG_FUNCTION_ARGS  )

Definition at line 1534 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(), NULL, OidIsValid, pfree(), PG_GETARG_ANY_ARRAY, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendbytes(), pq_sendint(), ArrayMetaState::proc, SendFunctionCall(), ArrayMetaState::typalign, ArrayMetaState::typbyval, ArrayMetaState::typdelim, ArrayMetaState::typiofunc, ArrayMetaState::typioparam, ArrayMetaState::typlen, VARDATA, VARHDRSZ, and VARSIZE.

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

1535 {
1537  Oid element_type = AARR_ELEMTYPE(v);
1538  int typlen;
1539  bool typbyval;
1540  char typalign;
1541  int nitems,
1542  i;
1543  int ndim,
1544  *dim,
1545  *lb;
1547  array_iter iter;
1548  ArrayMetaState *my_extra;
1549 
1550  /*
1551  * We arrange to look up info about element type, including its send
1552  * conversion proc, only once per series of calls, assuming the element
1553  * type doesn't change underneath us.
1554  */
1555  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1556  if (my_extra == NULL)
1557  {
1558  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1559  sizeof(ArrayMetaState));
1560  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
1561  my_extra->element_type = ~element_type;
1562  }
1563 
1564  if (my_extra->element_type != element_type)
1565  {
1566  /* Get info about element type, including its send proc */
1567  get_type_io_data(element_type, IOFunc_send,
1568  &my_extra->typlen, &my_extra->typbyval,
1569  &my_extra->typalign, &my_extra->typdelim,
1570  &my_extra->typioparam, &my_extra->typiofunc);
1571  if (!OidIsValid(my_extra->typiofunc))
1572  ereport(ERROR,
1573  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1574  errmsg("no binary output function available for type %s",
1575  format_type_be(element_type))));
1576  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc,
1577  fcinfo->flinfo->fn_mcxt);
1578  my_extra->element_type = element_type;
1579  }
1580  typlen = my_extra->typlen;
1581  typbyval = my_extra->typbyval;
1582  typalign = my_extra->typalign;
1583 
1584  ndim = AARR_NDIM(v);
1585  dim = AARR_DIMS(v);
1586  lb = AARR_LBOUND(v);
1587  nitems = ArrayGetNItems(ndim, dim);
1588 
1589  pq_begintypsend(&buf);
1590 
1591  /* Send the array header information */
1592  pq_sendint(&buf, ndim, 4);
1593  pq_sendint(&buf, AARR_HASNULL(v) ? 1 : 0, 4);
1594  pq_sendint(&buf, element_type, sizeof(Oid));
1595  for (i = 0; i < ndim; i++)
1596  {
1597  pq_sendint(&buf, dim[i], 4);
1598  pq_sendint(&buf, lb[i], 4);
1599  }
1600 
1601  /* Send the array elements using the element's own sendproc */
1602  array_iter_setup(&iter, v);
1603 
1604  for (i = 0; i < nitems; i++)
1605  {
1606  Datum itemvalue;
1607  bool isnull;
1608 
1609  /* Get source element, checking for NULL */
1610  itemvalue = array_iter_next(&iter, &isnull, i,
1611  typlen, typbyval, typalign);
1612 
1613  if (isnull)
1614  {
1615  /* -1 length means a NULL */
1616  pq_sendint(&buf, -1, 4);
1617  }
1618  else
1619  {
1620  bytea *outputbytes;
1621 
1622  outputbytes = SendFunctionCall(&my_extra->proc, itemvalue);
1623  pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
1624  pq_sendbytes(&buf, VARDATA(outputbytes),
1625  VARSIZE(outputbytes) - VARHDRSZ);
1626  pfree(outputbytes);
1627  }
1628  }
1629 
1631 }
#define VARDATA(PTR)
Definition: postgres.h:305
MemoryContext fn_mcxt
Definition: fmgr.h:62
#define VARSIZE(PTR)
Definition: postgres.h:306
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:359
#define VARHDRSZ
Definition: c.h:440
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define AARR_HASNULL(a)
Definition: array.h:311
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:313
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:379
bool typbyval
Definition: array.h:221
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
int16 typlen
Definition: array.h:220
static char * buf
Definition: pg_test_fsync.c:65
char typdelim
Definition: array.h:223
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1987
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:169
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
#define AARR_DIMS(a)
Definition: array.h:317
#define AARR_ELEMTYPE(a)
Definition: array.h:315
#define NULL
Definition: c.h:226
#define AARR_LBOUND(a)
Definition: array.h:319
Oid typioparam
Definition: array.h:224
#define AARR_NDIM(a)
Definition: array.h:309
Oid typiofunc
Definition: array.h:225
char typalign
Definition: array.h:222
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:115
int errmsg(const char *fmt,...)
Definition: elog.c:797
void pq_sendint(StringInfo buf, int i, int b)
Definition: pqformat.c:236
FmgrInfo proc
Definition: array.h:226
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
int i
Oid element_type
Definition: array.h:219
Definition: c.h:434
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:2043
ArrayType* array_set ( ArrayType array,
int  nSubscripts,
int *  indx,
Datum  dataValue,
bool  isNull,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 3080 of file arrayfuncs.c.

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3083 {
3085  nSubscripts, indx,
3086  dataValue, isNull,
3087  arraytyplen,
3088  elmlen, elmbyval, elmalign));
3089 }
#define PointerGetDatum(X)
Definition: postgres.h:564
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:2186
#define DatumGetArrayTypeP(X)
Definition: array.h:242
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 2186 of file arrayfuncs.c.

References ARR_DATA_OFFSET, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ARR_SIZE, array_bitmap_copy(), array_get_isnull(), array_seek(), array_set_element_expanded(), array_set_isnull(), ArrayCastAndSet(), ArrayGetNItems(), ArrayGetOffset(), att_addlength_datum, att_addlength_pointer, att_align_nominal, construct_md_array(), ArrayType::dataoffset, DatumGetArrayTypeP, DatumGetPointer, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, MAXDIM, MemSet, ArrayType::ndim, palloc(), palloc0(), PG_DETOAST_DATUM, PointerGetDatum, SET_VARSIZE, and VARATT_IS_EXTERNAL_EXPANDED.

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

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

Definition at line 2468 of file arrayfuncs.c.

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

Referenced by array_set_element().

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