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, 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, 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 4964 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(), regexp_split_to_array(), text_to_array_internal(), and transformRelOptions().

4968 {
4969  MemoryContext oldcontext;
4970 
4971  if (astate == NULL)
4972  {
4973  /* First time through --- initialize */
4974  astate = initArrayResult(element_type, rcontext, true);
4975  }
4976  else
4977  {
4978  Assert(astate->element_type == element_type);
4979  }
4980 
4981  oldcontext = MemoryContextSwitchTo(astate->mcontext);
4982 
4983  /* enlarge dvalues[]/dnulls[] if needed */
4984  if (astate->nelems >= astate->alen)
4985  {
4986  astate->alen *= 2;
4987  astate->dvalues = (Datum *)
4988  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
4989  astate->dnulls = (bool *)
4990  repalloc(astate->dnulls, astate->alen * sizeof(bool));
4991  }
4992 
4993  /*
4994  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
4995  * it's varlena. (You might think that detoasting is not needed here
4996  * because construct_md_array can detoast the array elements later.
4997  * However, we must not let construct_md_array modify the ArrayBuildState
4998  * because that would mean array_agg_finalfn damages its input, which is
4999  * verboten. Also, this way frequently saves one copying step.)
5000  */
5001  if (!disnull && !astate->typbyval)
5002  {
5003  if (astate->typlen == -1)
5004  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5005  else
5006  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5007  }
5008 
5009  astate->dvalues[astate->nelems] = dvalue;
5010  astate->dnulls[astate->nelems] = disnull;
5011  astate->nelems++;
5012 
5013  MemoryContextSwitchTo(oldcontext);
5014 
5015  return astate;
5016 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:198
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:4922
#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:215
#define Assert(condition)
Definition: c.h:656
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1022
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 5438 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5442 {
5443  if (astate == NULL)
5444  astate = initArrayResultAny(input_type, rcontext, true);
5445 
5446  if (astate->scalarstate)
5447  (void) accumArrayResult(astate->scalarstate,
5448  dvalue, disnull,
5449  input_type, rcontext);
5450  else
5451  (void) accumArrayResultArr(astate->arraystate,
5452  dvalue, disnull,
5453  input_type, rcontext);
5454 
5455  return astate;
5456 }
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5393
ArrayBuildState * scalarstate
Definition: array.h:210
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5161
ArrayBuildStateArr * arraystate
Definition: array.h:211
#define NULL
Definition: c.h:215
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:4964
ArrayBuildStateArr* accumArrayResultArr ( ArrayBuildStateArr astate,
Datum  dvalue,
bool  disnull,
Oid  array_type,
MemoryContext  rcontext 
)

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

5165 {
5166  ArrayType *arg;
5167  MemoryContext oldcontext;
5168  int *dims,
5169  *lbs,
5170  ndims,
5171  nitems,
5172  ndatabytes;
5173  char *data;
5174  int i;
5175 
5176  /*
5177  * We disallow accumulating null subarrays. Another plausible definition
5178  * is to ignore them, but callers that want that can just skip calling
5179  * this function.
5180  */
5181  if (disnull)
5182  ereport(ERROR,
5183  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5184  errmsg("cannot accumulate null arrays")));
5185 
5186  /* Detoast input array in caller's context */
5187  arg = DatumGetArrayTypeP(dvalue);
5188 
5189  if (astate == NULL)
5190  astate = initArrayResultArr(array_type, InvalidOid, rcontext, true);
5191  else
5192  Assert(astate->array_type == array_type);
5193 
5194  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5195 
5196  /* Collect this input's dimensions */
5197  ndims = ARR_NDIM(arg);
5198  dims = ARR_DIMS(arg);
5199  lbs = ARR_LBOUND(arg);
5200  data = ARR_DATA_PTR(arg);
5201  nitems = ArrayGetNItems(ndims, dims);
5202  ndatabytes = ARR_SIZE(arg) - ARR_DATA_OFFSET(arg);
5203 
5204  if (astate->ndims == 0)
5205  {
5206  /* First input; check/save the dimensionality info */
5207 
5208  /* Should we allow empty inputs and just produce an empty output? */
5209  if (ndims == 0)
5210  ereport(ERROR,
5211  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5212  errmsg("cannot accumulate empty arrays")));
5213  if (ndims + 1 > MAXDIM)
5214  ereport(ERROR,
5215  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5216  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5217  ndims + 1, MAXDIM)));
5218 
5219  /*
5220  * The output array will have n+1 dimensions, with the ones after the
5221  * first matching the input's dimensions.
5222  */
5223  astate->ndims = ndims + 1;
5224  astate->dims[0] = 0;
5225  memcpy(&astate->dims[1], dims, ndims * sizeof(int));
5226  astate->lbs[0] = 1;
5227  memcpy(&astate->lbs[1], lbs, ndims * sizeof(int));
5228 
5229  /* Allocate at least enough data space for this item */
5230  astate->abytes = 1024;
5231  while (astate->abytes <= ndatabytes)
5232  astate->abytes *= 2;
5233  astate->data = (char *) palloc(astate->abytes);
5234  }
5235  else
5236  {
5237  /* Second or later input: must match first input's dimensionality */
5238  if (astate->ndims != ndims + 1)
5239  ereport(ERROR,
5240  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5241  errmsg("cannot accumulate arrays of different dimensionality")));
5242  for (i = 0; i < ndims; i++)
5243  {
5244  if (astate->dims[i + 1] != dims[i] || astate->lbs[i + 1] != lbs[i])
5245  ereport(ERROR,
5246  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5247  errmsg("cannot accumulate arrays of different dimensionality")));
5248  }
5249 
5250  /* Enlarge data space if needed */
5251  if (astate->nbytes + ndatabytes > astate->abytes)
5252  {
5253  astate->abytes = Max(astate->abytes * 2,
5254  astate->nbytes + ndatabytes);
5255  astate->data = (char *) repalloc(astate->data, astate->abytes);
5256  }
5257  }
5258 
5259  /*
5260  * Copy the data portion of the sub-array. Note we assume that the
5261  * advertised data length of the sub-array is properly aligned. We do not
5262  * have to worry about detoasting elements since whatever's in the
5263  * sub-array should be OK already.
5264  */
5265  memcpy(astate->data + astate->nbytes, data, ndatabytes);
5266  astate->nbytes += ndatabytes;
5267 
5268  /* Deal with null bitmap if needed */
5269  if (astate->nullbitmap || ARR_HASNULL(arg))
5270  {
5271  int newnitems = astate->nitems + nitems;
5272 
5273  if (astate->nullbitmap == NULL)
5274  {
5275  /*
5276  * First input with nulls; we must retrospectively handle any
5277  * previous inputs by marking all their items non-null.
5278  */
5279  astate->aitems = 256;
5280  while (astate->aitems <= newnitems)
5281  astate->aitems *= 2;
5282  astate->nullbitmap = (bits8 *) palloc((astate->aitems + 7) / 8);
5283  array_bitmap_copy(astate->nullbitmap, 0,
5284  NULL, 0,
5285  astate->nitems);
5286  }
5287  else if (newnitems > astate->aitems)
5288  {
5289  astate->aitems = Max(astate->aitems * 2, newnitems);
5290  astate->nullbitmap = (bits8 *)
5291  repalloc(astate->nullbitmap, (astate->aitems + 7) / 8);
5292  }
5293  array_bitmap_copy(astate->nullbitmap, astate->nitems,
5294  ARR_NULLBITMAP(arg), 0,
5295  nitems);
5296  }
5297 
5298  astate->nitems += nitems;
5299  astate->dims[0] += 1;
5300 
5301  MemoryContextSwitchTo(oldcontext);
5302 
5303  /* Release detoasted copy if any */
5304  if ((Pointer) arg != DatumGetPointer(dvalue))
5305  pfree(arg);
5306 
5307  return astate;
5308 }
#define ARR_SIZE(a)
Definition: array.h:270
#define MAXDIM
Definition: c.h:404
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4595
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:569
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5112
#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:993
char * Pointer
Definition: c.h:231
#define ERROR
Definition: elog.h:41
#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:132
uint8 bits8
Definition: c.h:261
#define InvalidOid
Definition: postgres_ext.h:36
int lbs[MAXDIM]
Definition: array.h:197
#define Max(x, y)
Definition: c.h:781
#define NULL
Definition: c.h:215
#define Assert(condition)
Definition: c.h:656
#define ARR_NDIM(a)
Definition: array.h:271
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1022
#define DatumGetPointer(X)
Definition: postgres.h:557
int dims[MAXDIM]
Definition: array.h:196
void * palloc(Size size)
Definition: mcxt.c:892
int errmsg(const char *fmt,...)
Definition: elog.c:791
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 4595 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().

4598 {
4599  int destbitmask,
4600  destbitval,
4601  srcbitmask,
4602  srcbitval;
4603 
4604  Assert(destbitmap);
4605  if (nitems <= 0)
4606  return; /* don't risk fetch off end of memory */
4607  destbitmap += destoffset / 8;
4608  destbitmask = 1 << (destoffset % 8);
4609  destbitval = *destbitmap;
4610  if (srcbitmap)
4611  {
4612  srcbitmap += srcoffset / 8;
4613  srcbitmask = 1 << (srcoffset % 8);
4614  srcbitval = *srcbitmap;
4615  while (nitems-- > 0)
4616  {
4617  if (srcbitval & srcbitmask)
4618  destbitval |= destbitmask;
4619  else
4620  destbitval &= ~destbitmask;
4621  destbitmask <<= 1;
4622  if (destbitmask == 0x100)
4623  {
4624  *destbitmap++ = destbitval;
4625  destbitmask = 1;
4626  if (nitems > 0)
4627  destbitval = *destbitmap;
4628  }
4629  srcbitmask <<= 1;
4630  if (srcbitmask == 0x100)
4631  {
4632  srcbitmap++;
4633  srcbitmask = 1;
4634  if (nitems > 0)
4635  srcbitval = *srcbitmap;
4636  }
4637  }
4638  if (destbitmask != 1)
4639  *destbitmap = destbitval;
4640  }
4641  else
4642  {
4643  while (nitems-- > 0)
4644  {
4645  destbitval |= destbitmask;
4646  destbitmask <<= 1;
4647  if (destbitmask == 0x100)
4648  {
4649  *destbitmap++ = destbitval;
4650  destbitmask = 1;
4651  if (nitems > 0)
4652  destbitval = *destbitmap;
4653  }
4654  }
4655  if (destbitmask != 1)
4656  *destbitmap = destbitval;
4657  }
4658 }
#define Assert(condition)
Definition: c.h:656
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 3731 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().

3732 {
3733  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY(0);
3734  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY(1);
3735  Oid collation = PG_GET_COLLATION();
3736  int ndims1 = AARR_NDIM(array1);
3737  int ndims2 = AARR_NDIM(array2);
3738  int *dims1 = AARR_DIMS(array1);
3739  int *dims2 = AARR_DIMS(array2);
3740  int nitems1 = ArrayGetNItems(ndims1, dims1);
3741  int nitems2 = ArrayGetNItems(ndims2, dims2);
3742  Oid element_type = AARR_ELEMTYPE(array1);
3743  int result = 0;
3744  TypeCacheEntry *typentry;
3745  int typlen;
3746  bool typbyval;
3747  char typalign;
3748  int min_nitems;
3749  array_iter it1;
3750  array_iter it2;
3751  int i;
3752  FunctionCallInfoData locfcinfo;
3753 
3754  if (element_type != AARR_ELEMTYPE(array2))
3755  ereport(ERROR,
3756  (errcode(ERRCODE_DATATYPE_MISMATCH),
3757  errmsg("cannot compare arrays of different element types")));
3758 
3759  /*
3760  * We arrange to look up the comparison function only once per series of
3761  * calls, assuming the element type doesn't change underneath us. The
3762  * typcache is used so that we have no memory leakage when being used as
3763  * an index support function.
3764  */
3765  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3766  if (typentry == NULL ||
3767  typentry->type_id != element_type)
3768  {
3769  typentry = lookup_type_cache(element_type,
3771  if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
3772  ereport(ERROR,
3773  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3774  errmsg("could not identify a comparison function for type %s",
3775  format_type_be(element_type))));
3776  fcinfo->flinfo->fn_extra = (void *) typentry;
3777  }
3778  typlen = typentry->typlen;
3779  typbyval = typentry->typbyval;
3780  typalign = typentry->typalign;
3781 
3782  /*
3783  * apply the operator to each pair of array elements.
3784  */
3785  InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
3786  collation, NULL, NULL);
3787 
3788  /* Loop over source data */
3789  min_nitems = Min(nitems1, nitems2);
3790  array_iter_setup(&it1, array1);
3791  array_iter_setup(&it2, array2);
3792 
3793  for (i = 0; i < min_nitems; i++)
3794  {
3795  Datum elt1;
3796  Datum elt2;
3797  bool isnull1;
3798  bool isnull2;
3799  int32 cmpresult;
3800 
3801  /* Get elements, checking for NULL */
3802  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
3803  elt2 = array_iter_next(&it2, &isnull2, i, typlen, typbyval, typalign);
3804 
3805  /*
3806  * We consider two NULLs equal; NULL > not-NULL.
3807  */
3808  if (isnull1 && isnull2)
3809  continue;
3810  if (isnull1)
3811  {
3812  /* arg1 is greater than arg2 */
3813  result = 1;
3814  break;
3815  }
3816  if (isnull2)
3817  {
3818  /* arg1 is less than arg2 */
3819  result = -1;
3820  break;
3821  }
3822 
3823  /* Compare the pair of elements */
3824  locfcinfo.arg[0] = elt1;
3825  locfcinfo.arg[1] = elt2;
3826  locfcinfo.argnull[0] = false;
3827  locfcinfo.argnull[1] = false;
3828  locfcinfo.isnull = false;
3829  cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
3830 
3831  if (cmpresult == 0)
3832  continue; /* equal */
3833 
3834  if (cmpresult < 0)
3835  {
3836  /* arg1 is less than arg2 */
3837  result = -1;
3838  break;
3839  }
3840  else
3841  {
3842  /* arg1 is greater than arg2 */
3843  result = 1;
3844  break;
3845  }
3846  }
3847 
3848  /*
3849  * If arrays contain same data (up to end of shorter one), apply
3850  * additional rules to sort by dimensionality. The relative significance
3851  * of the different bits of information is historical; mainly we just care
3852  * that we don't say "equal" for arrays of different dimensionality.
3853  */
3854  if (result == 0)
3855  {
3856  if (nitems1 != nitems2)
3857  result = (nitems1 < nitems2) ? -1 : 1;
3858  else if (ndims1 != ndims2)
3859  result = (ndims1 < ndims2) ? -1 : 1;
3860  else
3861  {
3862  for (i = 0; i < ndims1; i++)
3863  {
3864  if (dims1[i] != dims2[i])
3865  {
3866  result = (dims1[i] < dims2[i]) ? -1 : 1;
3867  break;
3868  }
3869  }
3870  if (result == 0)
3871  {
3872  int *lbound1 = AARR_LBOUND(array1);
3873  int *lbound2 = AARR_LBOUND(array2);
3874 
3875  for (i = 0; i < ndims1; i++)
3876  {
3877  if (lbound1[i] != lbound2[i])
3878  {
3879  result = (lbound1[i] < lbound2[i]) ? -1 : 1;
3880  break;
3881  }
3882  }
3883  }
3884  }
3885  }
3886 
3887  /* Avoid leaking memory when handed toasted input. */
3888  AARR_FREE_IF_COPY(array1, 0);
3889  AARR_FREE_IF_COPY(array2, 1);
3890 
3891  return result;
3892 }
#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:787
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:569
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:519
#define PG_GET_COLLATION()
Definition: fmgr.h:155
signed int int32
Definition: c.h:242
FmgrInfo cmp_proc_finfo
Definition: typcache.h:68
FmgrInfo * flinfo
Definition: fmgr.h:71
#define ERROR
Definition: elog.h:41
#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:132
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:182
Oid fn_oid
Definition: fmgr.h:56
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:215
#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:791
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 4010 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().

4012 {
4013  bool result = matchall;
4014  Oid element_type = AARR_ELEMTYPE(array1);
4015  TypeCacheEntry *typentry;
4016  int nelems1;
4017  Datum *values2;
4018  bool *nulls2;
4019  int nelems2;
4020  int typlen;
4021  bool typbyval;
4022  char typalign;
4023  int i;
4024  int j;
4025  array_iter it1;
4026  FunctionCallInfoData locfcinfo;
4027 
4028  if (element_type != AARR_ELEMTYPE(array2))
4029  ereport(ERROR,
4030  (errcode(ERRCODE_DATATYPE_MISMATCH),
4031  errmsg("cannot compare arrays of different element types")));
4032 
4033  /*
4034  * We arrange to look up the equality function only once per series of
4035  * calls, assuming the element type doesn't change underneath us. The
4036  * typcache is used so that we have no memory leakage when being used as
4037  * an index support function.
4038  */
4039  typentry = (TypeCacheEntry *) *fn_extra;
4040  if (typentry == NULL ||
4041  typentry->type_id != element_type)
4042  {
4043  typentry = lookup_type_cache(element_type,
4045  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
4046  ereport(ERROR,
4047  (errcode(ERRCODE_UNDEFINED_FUNCTION),
4048  errmsg("could not identify an equality operator for type %s",
4049  format_type_be(element_type))));
4050  *fn_extra = (void *) typentry;
4051  }
4052  typlen = typentry->typlen;
4053  typbyval = typentry->typbyval;
4054  typalign = typentry->typalign;
4055 
4056  /*
4057  * Since we probably will need to scan array2 multiple times, it's
4058  * worthwhile to use deconstruct_array on it. We scan array1 the hard way
4059  * however, since we very likely won't need to look at all of it.
4060  */
4061  if (VARATT_IS_EXPANDED_HEADER(array2))
4062  {
4063  /* This should be safe even if input is read-only */
4064  deconstruct_expanded_array(&(array2->xpn));
4065  values2 = array2->xpn.dvalues;
4066  nulls2 = array2->xpn.dnulls;
4067  nelems2 = array2->xpn.nelems;
4068  }
4069  else
4070  deconstruct_array(&(array2->flt),
4071  element_type, typlen, typbyval, typalign,
4072  &values2, &nulls2, &nelems2);
4073 
4074  /*
4075  * Apply the comparison operator to each pair of array elements.
4076  */
4077  InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
4078  collation, NULL, NULL);
4079 
4080  /* Loop over source data */
4081  nelems1 = ArrayGetNItems(AARR_NDIM(array1), AARR_DIMS(array1));
4082  array_iter_setup(&it1, array1);
4083 
4084  for (i = 0; i < nelems1; i++)
4085  {
4086  Datum elt1;
4087  bool isnull1;
4088 
4089  /* Get element, checking for NULL */
4090  elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
4091 
4092  /*
4093  * We assume that the comparison operator is strict, so a NULL can't
4094  * match anything. XXX this diverges from the "NULL=NULL" behavior of
4095  * array_eq, should we act like that?
4096  */
4097  if (isnull1)
4098  {
4099  if (matchall)
4100  {
4101  result = false;
4102  break;
4103  }
4104  continue;
4105  }
4106 
4107  for (j = 0; j < nelems2; j++)
4108  {
4109  Datum elt2 = values2[j];
4110  bool isnull2 = nulls2 ? nulls2[j] : false;
4111  bool oprresult;
4112 
4113  if (isnull2)
4114  continue; /* can't match */
4115 
4116  /*
4117  * Apply the operator to the element pair
4118  */
4119  locfcinfo.arg[0] = elt1;
4120  locfcinfo.arg[1] = elt2;
4121  locfcinfo.argnull[0] = false;
4122  locfcinfo.argnull[1] = false;
4123  locfcinfo.isnull = false;
4124  oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
4125  if (oprresult)
4126  break;
4127  }
4128 
4129  if (j < nelems2)
4130  {
4131  /* found a match for elt1 */
4132  if (!matchall)
4133  {
4134  result = true;
4135  break;
4136  }
4137  }
4138  else
4139  {
4140  /* no match for elt1 */
4141  if (matchall)
4142  {
4143  result = false;
4144  break;
4145  }
4146  }
4147  }
4148 
4149  return result;
4150 }
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:569
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:519
#define ERROR
Definition: elog.h:41
#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:132
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:182
Oid fn_oid
Definition: fmgr.h:56
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:215
#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:3446
char typalign
Definition: typcache.h:37
int errmsg(const char *fmt,...)
Definition: elog.c:791
ArrayType flt
Definition: array.h:160
int i
bool array_contains_nulls ( ArrayType array)

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

3514 {
3515  int nelems;
3516  bits8 *bitmap;
3517  int bitmask;
3518 
3519  /* Easy answer if there's no null bitmap */
3520  if (!ARR_HASNULL(array))
3521  return false;
3522 
3523  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3524 
3525  bitmap = ARR_NULLBITMAP(array);
3526 
3527  /* check whole bytes of the bitmap byte-at-a-time */
3528  while (nelems >= 8)
3529  {
3530  if (*bitmap != 0xFF)
3531  return true;
3532  bitmap++;
3533  nelems -= 8;
3534  }
3535 
3536  /* check last partial byte */
3537  bitmask = 1;
3538  while (nelems > 0)
3539  {
3540  if ((*bitmap & bitmask) == 0)
3541  return true;
3542  bitmask <<= 1;
3543  nelems--;
3544  }
3545 
3546  return false;
3547 }
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:261
#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 4565 of file arrayfuncs.c.

References array_nelems_size().

Referenced by array_extract_slice(), and array_insert_slice().

4568 {
4569  int numbytes;
4570 
4571  numbytes = array_nelems_size(srcptr, offset, nullbitmap, nitems,
4572  typlen, typbyval, typalign);
4573  memcpy(destptr, srcptr, numbytes);
4574  return numbytes;
4575 }
static int array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4543
ArrayIterator array_create_iterator ( ArrayType arr,
int  slice_ndim,
ArrayMetaState mstate 
)

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

4227 {
4228  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4229 
4230  /*
4231  * Sanity-check inputs --- caller should have got this right already
4232  */
4233  Assert(PointerIsValid(arr));
4234  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4235  elog(ERROR, "invalid arguments to array_create_iterator");
4236 
4237  /*
4238  * Remember basic info about the array and its element type
4239  */
4240  iterator->arr = arr;
4241  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4242  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4243 
4244  if (mstate != NULL)
4245  {
4246  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4247 
4248  iterator->typlen = mstate->typlen;
4249  iterator->typbyval = mstate->typbyval;
4250  iterator->typalign = mstate->typalign;
4251  }
4252  else
4254  &iterator->typlen,
4255  &iterator->typbyval,
4256  &iterator->typalign);
4257 
4258  /*
4259  * Remember the slicing parameters.
4260  */
4261  iterator->slice_ndim = slice_ndim;
4262 
4263  if (slice_ndim > 0)
4264  {
4265  /*
4266  * Get pointers into the array's dims and lbound arrays to represent
4267  * the dims/lbound arrays of a slice. These are the same as the
4268  * rightmost N dimensions of the array.
4269  */
4270  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4271  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4272 
4273  /*
4274  * Compute number of elements in a slice.
4275  */
4276  iterator->slice_len = ArrayGetNItems(slice_ndim,
4277  iterator->slice_dims);
4278 
4279  /*
4280  * Create workspace for building sub-arrays.
4281  */
4282  iterator->slice_values = (Datum *)
4283  palloc(iterator->slice_len * sizeof(Datum));
4284  iterator->slice_nulls = (bool *)
4285  palloc(iterator->slice_len * sizeof(bool));
4286  }
4287 
4288  /*
4289  * Initialize our data pointer and linear element number. These will
4290  * advance through the array during array_iterate().
4291  */
4292  iterator->data_ptr = ARR_DATA_PTR(arr);
4293  iterator->current_item = 0;
4294 
4295  return iterator;
4296 }
bits8 * nullbitmap
Definition: arrayfuncs.c:70
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1924
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:41
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:921
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:215
#define Assert(condition)
Definition: c.h:656
#define ARR_NDIM(a)
Definition: array.h:271
char typalign
Definition: array.h:222
void * palloc(Size size)
Definition: mcxt.c:892
Oid element_type
Definition: array.h:219
#define elog
Definition: elog.h:228
#define PointerIsValid(pointer)
Definition: c.h:510
#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:404
#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:140
#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 3560 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().

3561 {
3562  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY(0);
3563  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY(1);
3564  Oid collation = PG_GET_COLLATION();
3565  int ndims1 = AARR_NDIM(array1);
3566  int ndims2 = AARR_NDIM(array2);
3567  int *dims1 = AARR_DIMS(array1);
3568  int *dims2 = AARR_DIMS(array2);
3569  int *lbs1 = AARR_LBOUND(array1);
3570  int *lbs2 = AARR_LBOUND(array2);
3571  Oid element_type = AARR_ELEMTYPE(array1);
3572  bool result = true;
3573  int nitems;
3574  TypeCacheEntry *typentry;
3575  int typlen;
3576  bool typbyval;
3577  char typalign;
3578  array_iter it1;
3579  array_iter it2;
3580  int i;
3581  FunctionCallInfoData locfcinfo;
3582 
3583  if (element_type != AARR_ELEMTYPE(array2))
3584  ereport(ERROR,
3585  (errcode(ERRCODE_DATATYPE_MISMATCH),
3586  errmsg("cannot compare arrays of different element types")));
3587 
3588  /* fast path if the arrays do not have the same dimensionality */
3589  if (ndims1 != ndims2 ||
3590  memcmp(dims1, dims2, ndims1 * sizeof(int)) != 0 ||
3591  memcmp(lbs1, lbs2, ndims1 * sizeof(int)) != 0)
3592  result = false;
3593  else
3594  {
3595  /*
3596  * We arrange to look up the equality function only once per series of
3597  * calls, assuming the element type doesn't change underneath us. The
3598  * typcache is used so that we have no memory leakage when being used
3599  * as an index support function.
3600  */
3601  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3602  if (typentry == NULL ||
3603  typentry->type_id != element_type)
3604  {
3605  typentry = lookup_type_cache(element_type,
3607  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
3608  ereport(ERROR,
3609  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3610  errmsg("could not identify an equality operator for type %s",
3611  format_type_be(element_type))));
3612  fcinfo->flinfo->fn_extra = (void *) typentry;
3613  }
3614  typlen = typentry->typlen;
3615  typbyval = typentry->typbyval;
3616  typalign = typentry->typalign;
3617 
3618  /*
3619  * apply the operator to each pair of array elements.
3620  */
3621  InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
3622  collation, NULL, NULL);
3623 
3624  /* Loop over source data */
3625  nitems = ArrayGetNItems(ndims1, dims1);
3626  array_iter_setup(&it1, array1);
3627  array_iter_setup(&it2, array2);
3628 
3629  for (i = 0; i < nitems; i++)
3630  {
3631  Datum elt1;
3632  Datum elt2;
3633  bool isnull1;
3634  bool isnull2;
3635  bool oprresult;
3636 
3637  /* Get elements, checking for NULL */
3638  elt1 = array_iter_next(&it1, &isnull1, i,
3639  typlen, typbyval, typalign);
3640  elt2 = array_iter_next(&it2, &isnull2, i,
3641  typlen, typbyval, typalign);
3642 
3643  /*
3644  * We consider two NULLs equal; NULL and not-NULL are unequal.
3645  */
3646  if (isnull1 && isnull2)
3647  continue;
3648  if (isnull1 || isnull2)
3649  {
3650  result = false;
3651  break;
3652  }
3653 
3654  /*
3655  * Apply the operator to the element pair
3656  */
3657  locfcinfo.arg[0] = elt1;
3658  locfcinfo.arg[1] = elt2;
3659  locfcinfo.argnull[0] = false;
3660  locfcinfo.argnull[1] = false;
3661  locfcinfo.isnull = false;
3662  oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
3663  if (!oprresult)
3664  {
3665  result = false;
3666  break;
3667  }
3668  }
3669  }
3670 
3671  /* Avoid leaking memory when handed toasted input. */
3672  AARR_FREE_IF_COPY(array1, 0);
3673  AARR_FREE_IF_COPY(array2, 1);
3674 
3675  PG_RETURN_BOOL(result);
3676 }
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:569
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:519
#define PG_GET_COLLATION()
Definition: fmgr.h:155
#define ERROR
Definition: elog.h:41
#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:132
#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:182
Oid fn_oid
Definition: fmgr.h:56
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:215
#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:791
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 4726 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().

4737 {
4738  char *destdataptr = ARR_DATA_PTR(newarray);
4739  bits8 *destnullsptr = ARR_NULLBITMAP(newarray);
4740  char *srcdataptr;
4741  int src_offset,
4742  dest_offset,
4743  prod[MAXDIM],
4744  span[MAXDIM],
4745  dist[MAXDIM],
4746  indx[MAXDIM];
4747  int i,
4748  j,
4749  inc;
4750 
4751  src_offset = ArrayGetOffset(ndim, dim, lb, st);
4752  srcdataptr = array_seek(arraydataptr, 0, arraynullsptr, src_offset,
4753  typlen, typbyval, typalign);
4754  mda_get_prod(ndim, dim, prod);
4755  mda_get_range(ndim, span, st, endp);
4756  mda_get_offset_values(ndim, dist, prod, span);
4757  for (i = 0; i < ndim; i++)
4758  indx[i] = 0;
4759  dest_offset = 0;
4760  j = ndim - 1;
4761  do
4762  {
4763  if (dist[j])
4764  {
4765  /* skip unwanted elements */
4766  srcdataptr = array_seek(srcdataptr, src_offset, arraynullsptr,
4767  dist[j],
4768  typlen, typbyval, typalign);
4769  src_offset += dist[j];
4770  }
4771  inc = array_copy(destdataptr, 1,
4772  srcdataptr, src_offset, arraynullsptr,
4773  typlen, typbyval, typalign);
4774  if (destnullsptr)
4775  array_bitmap_copy(destnullsptr, dest_offset,
4776  arraynullsptr, src_offset,
4777  1);
4778  destdataptr += inc;
4779  srcdataptr += inc;
4780  src_offset++;
4781  dest_offset++;
4782  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4783 }
#define MAXDIM
Definition: c.h:404
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:4595
static int array_copy(char *destptr, int nitems, char *srcptr, int offset, bits8 *nullbitmap, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4565
#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:261
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:4495
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 5642 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.

5643 {
5644  ArrayType *dims;
5645  ArrayType *result;
5646  Oid elmtype;
5647  Datum value;
5648  bool isnull;
5649 
5650  if (PG_ARGISNULL(1))
5651  ereport(ERROR,
5652  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5653  errmsg("dimension array or low bound array cannot be null")));
5654 
5655  dims = PG_GETARG_ARRAYTYPE_P(1);
5656 
5657  if (!PG_ARGISNULL(0))
5658  {
5659  value = PG_GETARG_DATUM(0);
5660  isnull = false;
5661  }
5662  else
5663  {
5664  value = 0;
5665  isnull = true;
5666  }
5667 
5668  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5669  if (!OidIsValid(elmtype))
5670  elog(ERROR, "could not determine data type of input");
5671 
5672  result = array_fill_internal(dims, NULL, value, isnull, elmtype, fcinfo);
5673  PG_RETURN_ARRAYTYPE_P(result);
5674 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5694
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
int errcode(int sqlerrcode)
Definition: elog.c:569
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:519
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:41
static struct @72 value
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2313
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define ereport(elevel, rest)
Definition: elog.h:132
uintptr_t Datum
Definition: postgres.h:374
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:215
int errmsg(const char *fmt,...)
Definition: elog.c:791
#define elog
Definition: elog.h:228
static ArrayType * array_fill_internal ( ArrayType dims,
ArrayType lbs,
Datum  value,
bool  isnull,
Oid  elmtype,
FunctionCallInfo  fcinfo 
)
static

Definition at line 5694 of file arrayfuncs.c.

References AllocSizeIsValid, ARR_DATA_PTR, ARR_DIMS, ARR_LBOUND, 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().

5697 {
5698  ArrayType *result;
5699  int *dimv;
5700  int *lbsv;
5701  int ndims;
5702  int nitems;
5703  int deflbs[MAXDIM];
5704  int16 elmlen;
5705  bool elmbyval;
5706  char elmalign;
5707  ArrayMetaState *my_extra;
5708 
5709  /*
5710  * Params checks
5711  */
5712  if (ARR_NDIM(dims) != 1)
5713  ereport(ERROR,
5714  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5715  errmsg("wrong number of array subscripts"),
5716  errdetail("Dimension array must be one dimensional.")));
5717 
5718  if (ARR_LBOUND(dims)[0] != 1)
5719  ereport(ERROR,
5720  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5721  errmsg("wrong range of array subscripts"),
5722  errdetail("Lower bound of dimension array must be one.")));
5723 
5724  if (array_contains_nulls(dims))
5725  ereport(ERROR,
5726  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5727  errmsg("dimension values cannot be null")));
5728 
5729  dimv = (int *) ARR_DATA_PTR(dims);
5730  ndims = ARR_DIMS(dims)[0];
5731 
5732  if (ndims < 0) /* we do allow zero-dimension arrays */
5733  ereport(ERROR,
5734  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5735  errmsg("invalid number of dimensions: %d", ndims)));
5736  if (ndims > MAXDIM)
5737  ereport(ERROR,
5738  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5739  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5740  ndims, MAXDIM)));
5741 
5742  if (lbs != NULL)
5743  {
5744  if (ARR_NDIM(lbs) != 1)
5745  ereport(ERROR,
5746  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5747  errmsg("wrong number of array subscripts"),
5748  errdetail("Dimension array must be one dimensional.")));
5749 
5750  if (ARR_LBOUND(lbs)[0] != 1)
5751  ereport(ERROR,
5752  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5753  errmsg("wrong range of array subscripts"),
5754  errdetail("Lower bound of dimension array must be one.")));
5755 
5756  if (array_contains_nulls(lbs))
5757  ereport(ERROR,
5758  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5759  errmsg("dimension values cannot be null")));
5760 
5761  if (ARR_DIMS(lbs)[0] != ndims)
5762  ereport(ERROR,
5763  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5764  errmsg("wrong number of array subscripts"),
5765  errdetail("Low bound array has different size than dimensions array.")));
5766 
5767  lbsv = (int *) ARR_DATA_PTR(lbs);
5768  }
5769  else
5770  {
5771  int i;
5772 
5773  for (i = 0; i < MAXDIM; i++)
5774  deflbs[i] = 1;
5775 
5776  lbsv = deflbs;
5777  }
5778 
5779  /* fast track for empty array */
5780  if (ndims == 0)
5781  return construct_empty_array(elmtype);
5782 
5783  nitems = ArrayGetNItems(ndims, dimv);
5784 
5785  /*
5786  * We arrange to look up info about element type only once per series of
5787  * calls, assuming the element type doesn't change underneath us.
5788  */
5789  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
5790  if (my_extra == NULL)
5791  {
5792  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
5793  sizeof(ArrayMetaState));
5794  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
5795  my_extra->element_type = InvalidOid;
5796  }
5797 
5798  if (my_extra->element_type != elmtype)
5799  {
5800  /* Get info about element type */
5801  get_typlenbyvalalign(elmtype,
5802  &my_extra->typlen,
5803  &my_extra->typbyval,
5804  &my_extra->typalign);
5805  my_extra->element_type = elmtype;
5806  }
5807 
5808  elmlen = my_extra->typlen;
5809  elmbyval = my_extra->typbyval;
5810  elmalign = my_extra->typalign;
5811 
5812  /* compute required space */
5813  if (!isnull)
5814  {
5815  int i;
5816  char *p;
5817  int nbytes;
5818  int totbytes;
5819 
5820  /* make sure data is not toasted */
5821  if (elmlen == -1)
5823 
5824  nbytes = att_addlength_datum(0, elmlen, value);
5825  nbytes = att_align_nominal(nbytes, elmalign);
5826  Assert(nbytes > 0);
5827 
5828  totbytes = nbytes * nitems;
5829 
5830  /* check for overflow of multiplication or total request */
5831  if (totbytes / nbytes != nitems ||
5832  !AllocSizeIsValid(totbytes))
5833  ereport(ERROR,
5834  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5835  errmsg("array size exceeds the maximum allowed (%d)",
5836  (int) MaxAllocSize)));
5837 
5838  /*
5839  * This addition can't overflow, but it might cause us to go past
5840  * MaxAllocSize. We leave it to palloc to complain in that case.
5841  */
5842  totbytes += ARR_OVERHEAD_NONULLS(ndims);
5843 
5844  result = create_array_envelope(ndims, dimv, lbsv, totbytes,
5845  elmtype, 0);
5846 
5847  p = ARR_DATA_PTR(result);
5848  for (i = 0; i < nitems; i++)
5849  p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, p);
5850  }
5851  else
5852  {
5853  int nbytes;
5854  int dataoffset;
5855 
5856  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
5857  nbytes = dataoffset;
5858 
5859  result = create_array_envelope(ndims, dimv, lbsv, nbytes,
5860  elmtype, dataoffset);
5861 
5862  /* create_array_envelope already zeroed the bitmap, so we're done */
5863  }
5864 
5865  return result;
5866 }
signed short int16
Definition: c.h:241
#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:404
static ArrayType * create_array_envelope(int ndims, int *dimv, int *lbv, int nbytes, Oid elmtype, int dataoffset)
Definition: arrayfuncs.c:5677
static int ArrayCastAndSet(Datum src, int typlen, bool typbyval, char typalign, char *dest)
Definition: arrayfuncs.c:4456
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1924
#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:569
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3395
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
#define ARR_LBOUND(a)
Definition: array.h:277
bool typbyval
Definition: array.h:221
FmgrInfo * flinfo
Definition: fmgr.h:71
#define ERROR
Definition: elog.h:41
static struct @72 value
#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:864
#define ereport(elevel, rest)
Definition: elog.h:132
#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:215
#define Assert(condition)
Definition: c.h:656
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:791
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:750
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:3513
Datum array_fill_with_lower_bounds ( PG_FUNCTION_ARGS  )

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

5602 {
5603  ArrayType *dims;
5604  ArrayType *lbs;
5605  ArrayType *result;
5606  Oid elmtype;
5607  Datum value;
5608  bool isnull;
5609 
5610  if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
5611  ereport(ERROR,
5612  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5613  errmsg("dimension array or low bound array cannot be null")));
5614 
5615  dims = PG_GETARG_ARRAYTYPE_P(1);
5616  lbs = PG_GETARG_ARRAYTYPE_P(2);
5617 
5618  if (!PG_ARGISNULL(0))
5619  {
5620  value = PG_GETARG_DATUM(0);
5621  isnull = false;
5622  }
5623  else
5624  {
5625  value = 0;
5626  isnull = true;
5627  }
5628 
5629  elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
5630  if (!OidIsValid(elmtype))
5631  elog(ERROR, "could not determine data type of input");
5632 
5633  result = array_fill_internal(dims, lbs, value, isnull, elmtype, fcinfo);
5634  PG_RETURN_ARRAYTYPE_P(result);
5635 }
static ArrayType * array_fill_internal(ArrayType *dims, ArrayType *lbs, Datum value, bool isnull, Oid elmtype, FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:5694
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
int errcode(int sqlerrcode)
Definition: elog.c:569
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:519
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:41
static struct @72 value
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2313
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define ereport(elevel, rest)
Definition: elog.h:132
uintptr_t Datum
Definition: postgres.h:374
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
int errmsg(const char *fmt,...)
Definition: elog.c:791
#define elog
Definition: elog.h:228
void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4388 of file arrayfuncs.c.

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

Referenced by array_position_common(), array_positions(), and exec_stmt_foreach_a().

4389 {
4390  if (iterator->slice_ndim > 0)
4391  {
4392  pfree(iterator->slice_values);
4393  pfree(iterator->slice_nulls);
4394  }
4395  pfree(iterator);
4396 }
bool * slice_nulls
Definition: arrayfuncs.c:82
void pfree(void *pointer)
Definition: mcxt.c:993
Datum * slice_values
Definition: arrayfuncs.c:81
Datum array_ge ( PG_FUNCTION_ARGS  )

Definition at line 3713 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3714 {
3715  PG_RETURN_BOOL(array_cmp(fcinfo) >= 0);
3716 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3731
#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:404
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:261
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:215
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4495
static Datum ArrayCast(char *value, bool byval, int len)
Definition: arrayfuncs.c:4445
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4410
#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:404
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:656
int i
static bool array_get_isnull ( const bits8 nullbitmap,
int  offset 
)
static

Definition at line 4410 of file arrayfuncs.c.

References NULL.

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

4411 {
4412  if (nullbitmap == NULL)
4413  return false; /* assume not null */
4414  if (nullbitmap[offset / 8] & (1 << (offset % 8)))
4415  return false; /* not null */
4416  return true;
4417 }
#define NULL
Definition: c.h:215
Datum array_get_slice ( Datum  arraydatum,
int  nSubscripts,
int *  upperIndx,
int *  lowerIndx,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

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

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

References array_cmp(), and PG_RETURN_BOOL.

3702 {
3703  PG_RETURN_BOOL(array_cmp(fcinfo) > 0);
3704 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3731
#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:404
char * pstrdup(const char *in)
Definition: mcxt.c:1160
int32 dataoffset
Definition: array.h:80
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:569
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3395
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
signed int int32
Definition: c.h:242
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:993
#define ERROR
Definition: elog.h:41
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:864
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:170
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define ereport(elevel, rest)
Definition: elog.h:132
#define ASSGN
Definition: arrayfuncs.c:44
void * palloc0(Size size)
Definition: mcxt.c:921
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:215
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:892
int errmsg(const char *fmt,...)
Definition: elog.c:791
FmgrInfo proc
Definition: array.h:226
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:750
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:1978
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 4799 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().

4810 {
4811  char *destPtr = ARR_DATA_PTR(destArray);
4812  char *origPtr = ARR_DATA_PTR(origArray);
4813  char *srcPtr = ARR_DATA_PTR(srcArray);
4814  bits8 *destBitmap = ARR_NULLBITMAP(destArray);
4815  bits8 *origBitmap = ARR_NULLBITMAP(origArray);
4816  bits8 *srcBitmap = ARR_NULLBITMAP(srcArray);
4817  int orignitems = ArrayGetNItems(ARR_NDIM(origArray),
4818  ARR_DIMS(origArray));
4819  int dest_offset,
4820  orig_offset,
4821  src_offset,
4822  prod[MAXDIM],
4823  span[MAXDIM],
4824  dist[MAXDIM],
4825  indx[MAXDIM];
4826  int i,
4827  j,
4828  inc;
4829 
4830  dest_offset = ArrayGetOffset(ndim, dim, lb, st);
4831  /* copy items before the slice start */
4832  inc = array_copy(destPtr, dest_offset,
4833  origPtr, 0, origBitmap,
4834  typlen, typbyval, typalign);
4835  destPtr += inc;
4836  origPtr += inc;
4837  if (destBitmap)
4838  array_bitmap_copy(destBitmap, 0, origBitmap, 0, dest_offset);
4839  orig_offset = dest_offset;
4840  mda_get_prod(ndim, dim, prod);
4841  mda_get_range(ndim, span, st, endp);
4842  mda_get_offset_values(ndim, dist, prod, span);
4843  for (i = 0; i < ndim; i++)
4844  indx[i] = 0;
4845  src_offset = 0;
4846  j = ndim - 1;
4847  do
4848  {
4849  /* Copy/advance over elements between here and next part of slice */
4850  if (dist[j])
4851  {
4852  inc = array_copy(destPtr, dist[j],
4853  origPtr, orig_offset, origBitmap,
4854  typlen, typbyval, typalign);
4855  destPtr += inc;
4856  origPtr += inc;
4857  if (destBitmap)
4858  array_bitmap_copy(destBitmap, dest_offset,
4859  origBitmap, orig_offset,
4860  dist[j]);
4861  dest_offset += dist[j];
4862  orig_offset += dist[j];
4863  }
4864  /* Copy new element at this slice position */
4865  inc = array_copy(destPtr, 1,
4866  srcPtr, src_offset, srcBitmap,
4867  typlen, typbyval, typalign);
4868  if (destBitmap)
4869  array_bitmap_copy(destBitmap, dest_offset,
4870  srcBitmap, src_offset,
4871  1);
4872  destPtr += inc;
4873  srcPtr += inc;
4874  dest_offset++;
4875  src_offset++;
4876  /* Advance over old element at this slice position */
4877  origPtr = array_seek(origPtr, orig_offset, origBitmap, 1,
4878  typlen, typbyval, typalign);
4879  orig_offset++;
4880  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4881 
4882  /* don't miss any data at the end */
4883  array_copy(destPtr, orignitems - orig_offset,
4884  origPtr, orig_offset, origBitmap,
4885  typlen, typbyval, typalign);
4886  if (destBitmap)
4887  array_bitmap_copy(destBitmap, dest_offset,
4888  origBitmap, orig_offset,
4889  orignitems - orig_offset);
4890 }
#define MAXDIM
Definition: c.h:404
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:4595
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:4565
#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:261
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:4495
#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 4305 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().

4306 {
4307  /* Done if we have reached the end of the array */
4308  if (iterator->current_item >= iterator->nitems)
4309  return false;
4310 
4311  if (iterator->slice_ndim == 0)
4312  {
4313  /*
4314  * Scalar case: return one element.
4315  */
4316  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4317  {
4318  *isnull = true;
4319  *value = (Datum) 0;
4320  }
4321  else
4322  {
4323  /* non-NULL, so fetch the individual Datum to return */
4324  char *p = iterator->data_ptr;
4325 
4326  *isnull = false;
4327  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4328 
4329  /* Move our data pointer forward to the next element */
4330  p = att_addlength_pointer(p, iterator->typlen, p);
4331  p = (char *) att_align_nominal(p, iterator->typalign);
4332  iterator->data_ptr = p;
4333  }
4334  }
4335  else
4336  {
4337  /*
4338  * Slice case: build and return an array of the requested size.
4339  */
4340  ArrayType *result;
4341  Datum *values = iterator->slice_values;
4342  bool *nulls = iterator->slice_nulls;
4343  char *p = iterator->data_ptr;
4344  int i;
4345 
4346  for (i = 0; i < iterator->slice_len; i++)
4347  {
4348  if (array_get_isnull(iterator->nullbitmap,
4349  iterator->current_item++))
4350  {
4351  nulls[i] = true;
4352  values[i] = (Datum) 0;
4353  }
4354  else
4355  {
4356  nulls[i] = false;
4357  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4358 
4359  /* Move our data pointer forward to the next element */
4360  p = att_addlength_pointer(p, iterator->typlen, p);
4361  p = (char *) att_align_nominal(p, iterator->typalign);
4362  }
4363  }
4364 
4365  iterator->data_ptr = p;
4366 
4367  result = construct_md_array(values,
4368  nulls,
4369  iterator->slice_ndim,
4370  iterator->slice_dims,
4371  iterator->slice_lbound,
4372  ARR_ELEMTYPE(iterator->arr),
4373  iterator->typlen,
4374  iterator->typbyval,
4375  iterator->typalign);
4376 
4377  *isnull = false;
4378  *value = PointerGetDatum(result);
4379  }
4380 
4381  return true;
4382 }
bits8 * nullbitmap
Definition: arrayfuncs.c:70
#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
static struct @72 value
#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:4410
static Datum values[MAXATTR]
Definition: bootstrap.c:159
#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:3311
#define ARR_ELEMTYPE(a)
Definition: array.h:273
ArrayType * arr
Definition: arrayfuncs.c:69
Datum array_larger ( PG_FUNCTION_ARGS  )

Definition at line 5496 of file arrayfuncs.c.

References array_cmp(), PG_GETARG_DATUM, and PG_RETURN_DATUM.

5497 {
5498  if (array_cmp(fcinfo) > 0)
5500  else
5502 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3731
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
Datum array_le ( PG_FUNCTION_ARGS  )

Definition at line 3707 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3708 {
3709  PG_RETURN_BOOL(array_cmp(fcinfo) <= 0);
3710 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3731
#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:404
#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:404
#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 3695 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_BOOL.

3696 {
3697  PG_RETURN_BOOL(array_cmp(fcinfo) < 0);
3698 }
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3731
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
Datum array_map ( FunctionCallInfo  fcinfo,
Oid  retType,
ArrayMapState amstate 
)

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

3092 {
3093  AnyArrayType *v;
3094  ArrayType *result;
3095  Datum *values;
3096  bool *nulls;
3097  int *dim;
3098  int ndim;
3099  int nitems;
3100  int i;
3101  int32 nbytes = 0;
3102  int32 dataoffset;
3103  bool hasnulls;
3104  Oid inpType;
3105  int inp_typlen;
3106  bool inp_typbyval;
3107  char inp_typalign;
3108  int typlen;
3109  bool typbyval;
3110  char typalign;
3111  array_iter iter;
3112  ArrayMetaState *inp_extra;
3113  ArrayMetaState *ret_extra;
3114 
3115  /* Get input array */
3116  if (fcinfo->nargs < 1)
3117  elog(ERROR, "invalid nargs: %d", fcinfo->nargs);
3118  if (PG_ARGISNULL(0))
3119  elog(ERROR, "null input array");
3120  v = PG_GETARG_ANY_ARRAY(0);
3121 
3122  inpType = AARR_ELEMTYPE(v);
3123  ndim = AARR_NDIM(v);
3124  dim = AARR_DIMS(v);
3125  nitems = ArrayGetNItems(ndim, dim);
3126 
3127  /* Check for empty array */
3128  if (nitems <= 0)
3129  {
3130  /* Return empty array */
3132  }
3133 
3134  /*
3135  * We arrange to look up info about input and return element types only
3136  * once per series of calls, assuming the element type doesn't change
3137  * underneath us.
3138  */
3139  inp_extra = &amstate->inp_extra;
3140  ret_extra = &amstate->ret_extra;
3141 
3142  if (inp_extra->element_type != inpType)
3143  {
3144  get_typlenbyvalalign(inpType,
3145  &inp_extra->typlen,
3146  &inp_extra->typbyval,
3147  &inp_extra->typalign);
3148  inp_extra->element_type = inpType;
3149  }
3150  inp_typlen = inp_extra->typlen;
3151  inp_typbyval = inp_extra->typbyval;
3152  inp_typalign = inp_extra->typalign;
3153 
3154  if (ret_extra->element_type != retType)
3155  {
3156  get_typlenbyvalalign(retType,
3157  &ret_extra->typlen,
3158  &ret_extra->typbyval,
3159  &ret_extra->typalign);
3160  ret_extra->element_type = retType;
3161  }
3162  typlen = ret_extra->typlen;
3163  typbyval = ret_extra->typbyval;
3164  typalign = ret_extra->typalign;
3165 
3166  /* Allocate temporary arrays for new values */
3167  values = (Datum *) palloc(nitems * sizeof(Datum));
3168  nulls = (bool *) palloc(nitems * sizeof(bool));
3169 
3170  /* Loop over source data */
3171  array_iter_setup(&iter, v);
3172  hasnulls = false;
3173 
3174  for (i = 0; i < nitems; i++)
3175  {
3176  bool callit = true;
3177 
3178  /* Get source element, checking for NULL */
3179  fcinfo->arg[0] = array_iter_next(&iter, &fcinfo->argnull[0], i,
3180  inp_typlen, inp_typbyval, inp_typalign);
3181 
3182  /*
3183  * Apply the given function to source elt and extra args.
3184  */
3185  if (fcinfo->flinfo->fn_strict)
3186  {
3187  int j;
3188 
3189  for (j = 0; j < fcinfo->nargs; j++)
3190  {
3191  if (fcinfo->argnull[j])
3192  {
3193  callit = false;
3194  break;
3195  }
3196  }
3197  }
3198 
3199  if (callit)
3200  {
3201  fcinfo->isnull = false;
3202  values[i] = FunctionCallInvoke(fcinfo);
3203  }
3204  else
3205  fcinfo->isnull = true;
3206 
3207  nulls[i] = fcinfo->isnull;
3208  if (fcinfo->isnull)
3209  hasnulls = true;
3210  else
3211  {
3212  /* Ensure data is not toasted */
3213  if (typlen == -1)
3214  values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
3215  /* Update total result size */
3216  nbytes = att_addlength_datum(nbytes, typlen, values[i]);
3217  nbytes = att_align_nominal(nbytes, typalign);
3218  /* check for overflow of total request */
3219  if (!AllocSizeIsValid(nbytes))
3220  ereport(ERROR,
3221  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3222  errmsg("array size exceeds the maximum allowed (%d)",
3223  (int) MaxAllocSize)));
3224  }
3225  }
3226 
3227  /* Allocate and initialize the result array */
3228  if (hasnulls)
3229  {
3230  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3231  nbytes += dataoffset;
3232  }
3233  else
3234  {
3235  dataoffset = 0; /* marker for no null bitmap */
3236  nbytes += ARR_OVERHEAD_NONULLS(ndim);
3237  }
3238  result = (ArrayType *) palloc0(nbytes);
3239  SET_VARSIZE(result, nbytes);
3240  result->ndim = ndim;
3241  result->dataoffset = dataoffset;
3242  result->elemtype = retType;
3243  memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
3244  memcpy(ARR_LBOUND(result), AARR_LBOUND(v), ndim * sizeof(int));
3245 
3246  /*
3247  * Note: do not risk trying to pfree the results of the called function
3248  */
3249  CopyArrayEls(result,
3250  values, nulls, nitems,
3251  typlen, typbyval, typalign,
3252  false);
3253 
3254  pfree(values);
3255  pfree(nulls);
3256 
3257  PG_RETURN_ARRAYTYPE_P(result);
3258 }
#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:1924
#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:569
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3395
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
signed int int32
Definition: c.h:242
#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:993
#define ERROR
Definition: elog.h:41
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:132
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void * palloc0(Size size)
Definition: mcxt.c:921
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:159
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
void * palloc(Size size)
Definition: mcxt.c:892
int errmsg(const char *fmt,...)
Definition: elog.c:791
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:228
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:404
#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 3689 of file arrayfuncs.c.

References array_eq(), DatumGetBool, and PG_RETURN_BOOL.

3690 {
3692 }
#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:3560
static int array_nelems_size ( char *  ptr,
int  offset,
bits8 nullbitmap,
int  nitems,
int  typlen,
bool  typbyval,
char  typalign 
)
static

Definition at line 4543 of file arrayfuncs.c.

References array_seek().

Referenced by array_copy(), and array_set_slice().

4545 {
4546  return array_seek(ptr, offset, nullbitmap, nitems,
4547  typlen, typbyval, typalign) - ptr;
4548 }
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4495
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:404
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:1160
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:1943
bool typbyval
Definition: array.h:221
void pfree(void *pointer)
Definition: mcxt.c:993
#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:170
#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:215
#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:159
void * palloc(Size size)
Definition: mcxt.c:892
FmgrInfo proc
Definition: array.h:226
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:750
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:1978
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:404
int32 dataoffset
Definition: array.h:80
StringInfoData * StringInfo
Definition: stringinfo.h:43
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:569
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:3395
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:519
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
signed int int32
Definition: c.h:242
#define ARR_LBOUND(a)
Definition: array.h:277
bool typbyval
Definition: array.h:221
void pfree(void *pointer)
Definition: mcxt.c:993
#define ERROR
Definition: elog.h:41
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:170
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define ereport(elevel, rest)
Definition: elog.h:132
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:921
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:215
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:892
int errmsg(const char *fmt,...)
Definition: elog.c:791
FmgrInfo proc
Definition: array.h:226
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:750
int i
Oid element_type
Definition: array.h:219
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:447
#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:1978
Datum array_ref ( ArrayType array,
int  nSubscripts,
int *  indx,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign,
bool isNull 
)

Definition at line 3034 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3037 {
3038  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3039  arraytyplen, elmlen, elmbyval, elmalign,
3040  isNull);
3041 }
#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 6225 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.

6226 {
6227  ArrayType *array;
6228  Datum search = PG_GETARG_DATUM(1);
6229  bool search_isnull = PG_ARGISNULL(1);
6230 
6231  if (PG_ARGISNULL(0))
6232  PG_RETURN_NULL();
6233  array = PG_GETARG_ARRAYTYPE_P(0);
6234 
6235  array = array_replace_internal(array,
6236  search, search_isnull,
6237  (Datum) 0, true,
6238  true, PG_GET_COLLATION(),
6239  fcinfo);
6240  PG_RETURN_ARRAYTYPE_P(array);
6241 }
#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:5967
#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 6247 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.

6248 {
6249  ArrayType *array;
6250  Datum search = PG_GETARG_DATUM(1);
6251  bool search_isnull = PG_ARGISNULL(1);
6252  Datum replace = PG_GETARG_DATUM(2);
6253  bool replace_isnull = PG_ARGISNULL(2);
6254 
6255  if (PG_ARGISNULL(0))
6256  PG_RETURN_NULL();
6257  array = PG_GETARG_ARRAYTYPE_P(0);
6258 
6259  array = array_replace_internal(array,
6260  search, search_isnull,
6261  replace, replace_isnull,
6262  false, PG_GET_COLLATION(),
6263  fcinfo);
6264  PG_RETURN_ARRAYTYPE_P(array);
6265 }
#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:5967
#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 5967 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().

5972 {
5973  ArrayType *result;
5974  Oid element_type;
5975  Datum *values;
5976  bool *nulls;
5977  int *dim;
5978  int ndim;
5979  int nitems,
5980  nresult;
5981  int i;
5982  int32 nbytes = 0;
5983  int32 dataoffset;
5984  bool hasnulls;
5985  int typlen;
5986  bool typbyval;
5987  char typalign;
5988  char *arraydataptr;
5989  bits8 *bitmap;
5990  int bitmask;
5991  bool changed = false;
5992  TypeCacheEntry *typentry;
5993  FunctionCallInfoData locfcinfo;
5994 
5995  element_type = ARR_ELEMTYPE(array);
5996  ndim = ARR_NDIM(array);
5997  dim = ARR_DIMS(array);
5998  nitems = ArrayGetNItems(ndim, dim);
5999 
6000  /* Return input array unmodified if it is empty */
6001  if (nitems <= 0)
6002  return array;
6003 
6004  /*
6005  * We can't remove elements from multi-dimensional arrays, since the
6006  * result might not be rectangular.
6007  */
6008  if (remove && ndim > 1)
6009  ereport(ERROR,
6010  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6011  errmsg("removing elements from multidimensional arrays is not supported")));
6012 
6013  /*
6014  * We arrange to look up the equality function only once per series of
6015  * calls, assuming the element type doesn't change underneath us.
6016  */
6017  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
6018  if (typentry == NULL ||
6019  typentry->type_id != element_type)
6020  {
6021  typentry = lookup_type_cache(element_type,
6023  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
6024  ereport(ERROR,
6025  (errcode(ERRCODE_UNDEFINED_FUNCTION),
6026  errmsg("could not identify an equality operator for type %s",
6027  format_type_be(element_type))));
6028  fcinfo->flinfo->fn_extra = (void *) typentry;
6029  }
6030  typlen = typentry->typlen;
6031  typbyval = typentry->typbyval;
6032  typalign = typentry->typalign;
6033 
6034  /*
6035  * Detoast values if they are toasted. The replacement value must be
6036  * detoasted for insertion into the result array, while detoasting the
6037  * search value only once saves cycles.
6038  */
6039  if (typlen == -1)
6040  {
6041  if (!search_isnull)
6042  search = PointerGetDatum(PG_DETOAST_DATUM(search));
6043  if (!replace_isnull)
6044  replace = PointerGetDatum(PG_DETOAST_DATUM(replace));
6045  }
6046 
6047  /* Prepare to apply the comparison operator */
6048  InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
6049  collation, NULL, NULL);
6050 
6051  /* Allocate temporary arrays for new values */
6052  values = (Datum *) palloc(nitems * sizeof(Datum));
6053  nulls = (bool *) palloc(nitems * sizeof(bool));
6054 
6055  /* Loop over source data */
6056  arraydataptr = ARR_DATA_PTR(array);
6057  bitmap = ARR_NULLBITMAP(array);
6058  bitmask = 1;
6059  hasnulls = false;
6060  nresult = 0;
6061 
6062  for (i = 0; i < nitems; i++)
6063  {
6064  Datum elt;
6065  bool isNull;
6066  bool oprresult;
6067  bool skip = false;
6068 
6069  /* Get source element, checking for NULL */
6070  if (bitmap && (*bitmap & bitmask) == 0)
6071  {
6072  isNull = true;
6073  /* If searching for NULL, we have a match */
6074  if (search_isnull)
6075  {
6076  if (remove)
6077  {
6078  skip = true;
6079  changed = true;
6080  }
6081  else if (!replace_isnull)
6082  {
6083  values[nresult] = replace;
6084  isNull = false;
6085  changed = true;
6086  }
6087  }
6088  }
6089  else
6090  {
6091  isNull = false;
6092  elt = fetch_att(arraydataptr, typbyval, typlen);
6093  arraydataptr = att_addlength_datum(arraydataptr, typlen, elt);
6094  arraydataptr = (char *) att_align_nominal(arraydataptr, typalign);
6095 
6096  if (search_isnull)
6097  {
6098  /* no match possible, keep element */
6099  values[nresult] = elt;
6100  }
6101  else
6102  {
6103  /*
6104  * Apply the operator to the element pair
6105  */
6106  locfcinfo.arg[0] = elt;
6107  locfcinfo.arg[1] = search;
6108  locfcinfo.argnull[0] = false;
6109  locfcinfo.argnull[1] = false;
6110  locfcinfo.isnull = false;
6111  oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
6112  if (!oprresult)
6113  {
6114  /* no match, keep element */
6115  values[nresult] = elt;
6116  }
6117  else
6118  {
6119  /* match, so replace or delete */
6120  changed = true;
6121  if (remove)
6122  skip = true;
6123  else
6124  {
6125  values[nresult] = replace;
6126  isNull = replace_isnull;
6127  }
6128  }
6129  }
6130  }
6131 
6132  if (!skip)
6133  {
6134  nulls[nresult] = isNull;
6135  if (isNull)
6136  hasnulls = true;
6137  else
6138  {
6139  /* Update total result size */
6140  nbytes = att_addlength_datum(nbytes, typlen, values[nresult]);
6141  nbytes = att_align_nominal(nbytes, typalign);
6142  /* check for overflow of total request */
6143  if (!AllocSizeIsValid(nbytes))
6144  ereport(ERROR,
6145  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
6146  errmsg("array size exceeds the maximum allowed (%d)",
6147  (int) MaxAllocSize)));
6148  }
6149  nresult++;
6150  }
6151 
6152  /* advance bitmap pointer if any */
6153  if (bitmap)
6154  {
6155  bitmask <<= 1;
6156  if (bitmask == 0x100)
6157  {
6158  bitmap++;
6159  bitmask = 1;
6160  }
6161  }
6162  }
6163 
6164  /*
6165  * If not changed just return the original array
6166  */
6167  if (!changed)
6168  {
6169  pfree(values);
6170  pfree(nulls);
6171  return array;
6172  }
6173 
6174  /* If all elements were removed return an empty array */
6175  if (nresult == 0)
6176  {
6177  pfree(values);
6178  pfree(nulls);
6179  return construct_empty_array(element_type);
6180  }
6181 
6182  /* Allocate and initialize the result array */
6183  if (hasnulls)
6184  {
6185  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nresult);
6186  nbytes += dataoffset;
6187  }
6188  else
6189  {
6190  dataoffset = 0; /* marker for no null bitmap */
6191  nbytes += ARR_OVERHEAD_NONULLS(ndim);
6192  }
6193  result = (ArrayType *) palloc0(nbytes);
6194  SET_VARSIZE(result, nbytes);
6195  result->ndim = ndim;
6196  result->dataoffset = dataoffset;
6197  result->elemtype = element_type;
6198  memcpy(ARR_DIMS(result), ARR_DIMS(array), ndim * sizeof(int));
6199  memcpy(ARR_LBOUND(result), ARR_LBOUND(array), ndim * sizeof(int));
6200 
6201  if (remove)
6202  {
6203  /* Adjust the result length */
6204  ARR_DIMS(result)[0] = nresult;
6205  }
6206 
6207  /* Insert data into result array */
6208  CopyArrayEls(result,
6209  values, nulls, nresult,
6210  typlen, typbyval, typalign,
6211  false);
6212 
6213  pfree(values);
6214  pfree(nulls);
6215 
6216  return result;
6217 }
static void skip(struct vars *v)
Definition: regc_lex.c:1081
#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:569
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3395
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:519
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
signed int int32
Definition: c.h:242
#define ARR_LBOUND(a)
Definition: array.h:277
FmgrInfo * flinfo
Definition: fmgr.h:71
void pfree(void *pointer)
Definition: mcxt.c:993
#define ERROR
Definition: elog.h:41
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:132
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
uint8 bits8
Definition: c.h:261
void * palloc0(Size size)
Definition: mcxt.c:921
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:182
Oid fn_oid
Definition: fmgr.h:56
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:215
#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:159
#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:892
int errmsg(const char *fmt,...)
Definition: elog.c:791
#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 4495 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().

4497 {
4498  int bitmask;
4499  int i;
4500 
4501  /* easy if fixed-size elements and no NULLs */
4502  if (typlen > 0 && !nullbitmap)
4503  return ptr + nitems * ((Size) att_align_nominal(typlen, typalign));
4504 
4505  /* seems worth having separate loops for NULL and no-NULLs cases */
4506  if (nullbitmap)
4507  {
4508  nullbitmap += offset / 8;
4509  bitmask = 1 << (offset % 8);
4510 
4511  for (i = 0; i < nitems; i++)
4512  {
4513  if (*nullbitmap & bitmask)
4514  {
4515  ptr = att_addlength_pointer(ptr, typlen, ptr);
4516  ptr = (char *) att_align_nominal(ptr, typalign);
4517  }
4518  bitmask <<= 1;
4519  if (bitmask == 0x100)
4520  {
4521  nullbitmap++;
4522  bitmask = 1;
4523  }
4524  }
4525  }
4526  else
4527  {
4528  for (i = 0; i < nitems; i++)
4529  {
4530  ptr = att_addlength_pointer(ptr, typlen, ptr);
4531  ptr = (char *) att_align_nominal(ptr, typalign);
4532  }
4533  }
4534  return ptr;
4535 }
#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:341
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:358
#define VARHDRSZ
Definition: c.h:429
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:569
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:519
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:378
bool typbyval
Definition: array.h:221
void pfree(void *pointer)
Definition: mcxt.c:993
#define ERROR
Definition: elog.h:41
#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:2020
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:170
#define ereport(elevel, rest)
Definition: elog.h:132
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:215
#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:114
int errmsg(const char *fmt,...)
Definition: elog.c:791
void pq_sendint(StringInfo buf, int i, int b)
Definition: pqformat.c:235
FmgrInfo proc
Definition: array.h:226
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:750
int i
Oid element_type
Definition: array.h:219
Definition: c.h:423
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:1978
ArrayType* array_set ( ArrayType array,
int  nSubscripts,
int *  indx,
Datum  dataValue,
bool  isNull,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 3051 of file arrayfuncs.c.

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3054 {
3056  nSubscripts, indx,
3057  dataValue, isNull,
3058  arraytyplen,
3059  elmlen, elmbyval, elmalign));
3060 }
#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:2179
#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 2179 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().

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

2466 {
2467  ExpandedArrayHeader *eah;
2468  Datum *dvalues;
2469  bool *dnulls;
2470  int i,
2471  ndim,
2472  dim[MAXDIM],
2473  lb[MAXDIM],
2474  offset;
2475  bool dimschanged,
2476  newhasnulls;
2477  int addedbefore,
2478  addedafter;
2479  char *oldValue;
2480 
2481  /* Convert to R/W object if not so already */
2482  eah = DatumGetExpandedArray(arraydatum);
2483 
2484  /* Sanity-check caller's info against object; we don't use it otherwise */
2485  Assert(arraytyplen == -1);
2486  Assert(elmlen == eah->typlen);
2487  Assert(elmbyval == eah->typbyval);
2488  Assert(elmalign == eah->typalign);
2489 
2490  /*
2491  * Copy dimension info into local storage. This allows us to modify the
2492  * dimensions if needed, while not messing up the expanded value if we
2493  * fail partway through.
2494  */
2495  ndim = eah->ndims;
2496  Assert(ndim >= 0 && ndim <= MAXDIM);
2497  memcpy(dim, eah->dims, ndim * sizeof(int));
2498  memcpy(lb, eah->lbound, ndim * sizeof(int));
2499  dimschanged = false;
2500 
2501  /*
2502  * if number of dims is zero, i.e. an empty array, create an array with
2503  * nSubscripts dimensions, and set the lower bounds to the supplied
2504  * subscripts.
2505  */
2506  if (ndim == 0)
2507  {
2508  /*
2509  * Allocate adequate space for new dimension info. This is harmless
2510  * if we fail later.
2511  */
2512  Assert(nSubscripts > 0 && nSubscripts <= MAXDIM);
2513  eah->dims = (int *) MemoryContextAllocZero(eah->hdr.eoh_context,
2514  nSubscripts * sizeof(int));
2515  eah->lbound = (int *) MemoryContextAllocZero(eah->hdr.eoh_context,
2516  nSubscripts * sizeof(int));
2517 
2518  /* Update local copies of dimension info */
2519  ndim = nSubscripts;
2520  for (i = 0; i < nSubscripts; i++)
2521  {
2522  dim[i] = 0;
2523  lb[i] = indx[i];
2524  }
2525  dimschanged = true;
2526  }
2527  else if (ndim != nSubscripts)
2528  ereport(ERROR,
2529  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2530  errmsg("wrong number of array subscripts")));
2531 
2532  /*
2533  * Deconstruct array if we didn't already. (Someday maybe add a special
2534  * case path for fixed-length, no-nulls cases, where we can overwrite an
2535  * element in place without ever deconstructing. But today is not that
2536  * day.)
2537  */
2539 
2540  /*
2541  * Copy new element into array's context, if needed (we assume it's
2542  * already detoasted, so no junk should be created). If we fail further
2543  * down, this memory is leaked, but that's reasonably harmless.
2544  */
2545  if (!eah->typbyval && !isNull)
2546  {
2548 
2549  dataValue = datumCopy(dataValue, false, eah->typlen);
2550  MemoryContextSwitchTo(oldcxt);
2551  }
2552 
2553  dvalues = eah->dvalues;
2554  dnulls = eah->dnulls;
2555 
2556  newhasnulls = ((dnulls != NULL) || isNull);
2557  addedbefore = addedafter = 0;
2558 
2559  /*
2560  * Check subscripts (this logic matches original array_set_element)
2561  */
2562  if (ndim == 1)
2563  {
2564  if (indx[0] < lb[0])
2565  {
2566  addedbefore = lb[0] - indx[0];
2567  dim[0] += addedbefore;
2568  lb[0] = indx[0];
2569  dimschanged = true;
2570  if (addedbefore > 1)
2571  newhasnulls = true; /* will insert nulls */
2572  }
2573  if (indx[0] >= (dim[0] + lb[0]))
2574  {
2575  addedafter = indx[0] - (dim[0] + lb[0]) + 1;
2576  dim[0] += addedafter;
2577  dimschanged = true;
2578  if (addedafter > 1)
2579  newhasnulls = true; /* will insert nulls */
2580  }
2581  }
2582  else
2583  {
2584  /*
2585  * XXX currently we do not support extending multi-dimensional arrays
2586  * during assignment
2587  */
2588  for (i = 0; i < ndim; i++)
2589  {
2590  if (indx[i] < lb[i] ||
2591  indx[i] >= (dim[i] + lb[i]))
2592  ereport(ERROR,
2593  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2594  errmsg("array subscript out of range")));
2595  }
2596  }
2597 
2598  /* Now we can calculate linear offset of target item in array */
2599  offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
2600 
2601  /* Physically enlarge existing dvalues/dnulls arrays if needed */
2602  if (dim[0] > eah->dvalueslen)
2603  {
2604  /* We want some extra space if we're enlarging */
2605  int newlen = dim[0] + dim[0] / 8;
2606 
2607  newlen = Max(newlen, dim[0]); /* integer overflow guard */
2608  eah->dvalues = dvalues = (Datum *)
2609  repalloc(dvalues, newlen * sizeof(Datum));
2610  if (dnulls)
2611  eah->dnulls = dnulls = (bool *)
2612  repalloc(dnulls, newlen * sizeof(bool));
2613  eah->dvalueslen = newlen;
2614  }
2615 
2616  /*
2617  * If we need a nulls bitmap and don't already have one, create it, being
2618  * sure to mark all existing entries as not null.
2619  */
2620  if (newhasnulls && dnulls == NULL)
2621  eah->dnulls = dnulls = (bool *)
2623  eah->dvalueslen * sizeof(bool));
2624 
2625  /*
2626  * We now have all the needed space allocated, so we're ready to make
2627  * irreversible changes. Be very wary of allowing failure below here.
2628  */
2629 
2630  /* Flattened value will no longer represent array accurately */
2631  eah->fvalue = NULL;
2632  /* And we don't know the flattened size either */
2633  eah->flat_size = 0;
2634 
2635  /* Update dimensionality info if needed */
2636  if (dimschanged)
2637  {
2638  eah->ndims = ndim;
2639  memcpy(eah->dims, dim, ndim * sizeof(int));
2640  memcpy(eah->lbound, lb, ndim * sizeof(int));
2641  }
2642 
2643  /* Reposition items if needed, and fill addedbefore items with nulls */
2644  if (addedbefore > 0)
2645  {
2646  memmove(dvalues + addedbefore, dvalues, eah->nelems * sizeof(Datum));
2647  for (i = 0; i < addedbefore; i++)
2648  dvalues[i] = (Datum) 0;
2649  if (dnulls)
2650  {
2651  memmove(dnulls + addedbefore, dnulls, eah->nelems * sizeof(bool));
2652  for (i = 0; i < addedbefore; i++)
2653  dnulls[i] = true;
2654  }
2655  eah->nelems += addedbefore;
2656  }
2657 
2658  /* fill addedafter items with nulls */
2659  if (addedafter > 0)
2660  {
2661  for (i = 0; i < addedafter; i++)
2662  dvalues[eah->nelems + i] = (Datum) 0;
2663  if (dnulls)
2664  {
2665  for (i = 0; i < addedafter; i++)
2666  dnulls[eah->nelems + i] = true;
2667  }
2668  eah->nelems += addedafter;
2669  }
2670 
2671  /* Grab old element value for pfree'ing, if needed. */
2672  if (!eah->typbyval && (dnulls == NULL || !dnulls[offset]))
2673  oldValue = (char *) DatumGetPointer(dvalues[offset]);
2674  else
2675  oldValue = NULL;
2676 
2677  /* And finally we can insert the new element. */
2678  dvalues[offset] = dataValue;
2679  if (dnulls)
2680  dnulls[offset] = isNull;
2681 
2682  /*
2683  * Free old element if needed; this keeps repeated element replacements
2684  * from bloating the array's storage. If the pfree somehow fails, it
2685  * won't corrupt the array.
2686  */
2687  if (oldValue)
2688  {
2689  /* Don't try to pfree a part of the original flat array */
2690  if (oldValue < eah->fstartptr || oldValue >= eah->fendptr)
2691  pfree(oldValue);
2692  }
2693 
2694  /* Done, return standard TOAST pointer for object */
2695  return EOHPGetRWDatum(&eah->hdr);
2696 }
void deconstruct_expanded_array(ExpandedArrayHeader *eah)
#define MAXDIM
Definition: c.h:404
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:569
Datum * dvalues
Definition: array.h:130
char * fendptr
Definition: array.h:151
void pfree(void *pointer)
Definition: mcxt.c:993
#define ERROR
Definition: elog.h:41
ExpandedArrayHeader * DatumGetExpandedArray(Datum d)
ExpandedObjectHeader hdr
Definition: array.h:102
#define memmove(d, s, c)
Definition: c.h:1027
#define ereport(elevel, rest)
Definition: elog.h:132
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
ArrayType * fvalue
Definition: array.h:149
uintptr_t Datum
Definition: postgres.h:374
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:785
#define Max(x, y)
Definition: c.h:781
#define NULL
Definition: c.h:215
#define Assert(condition)
Definition: c.h:656
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1022
#define DatumGetPointer(X)
Definition: postgres.h:557
#define EOHPGetRWDatum(eohptr)
int errmsg(const char *fmt,...)
Definition: elog.c:791
int i
MemoryContext eoh_context
static void array_set_isnull ( bits8 nullbitmap,
int  offset,
bool  isNull 
)
static

Definition at line 4427 of file arrayfuncs.c.

Referenced by array_set_element().

4428 {
4429  int bitmask;
4430 
4431  nullbitmap += offset / 8;
4432  bitmask = 1 << (offset % 8);
4433  if (isNull)
4434  *nullbitmap &= ~bitmask;
4435  else
4436  *nullbitmap |= bitmask;
4437 }
Datum array_set_slice ( Datum  arraydatum,
int  nSubscripts,
int *  upperIndx,
int *  lowerIndx,
Datum  srcArrayDatum,
bool  isNull,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 2734 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_insert_slice(), array_nelems_size(), array_slice_size(), ArrayGetNItems(), Assert, construct_md_array(), ArrayType::dataoffset, DatumGetArrayTypeP, deconstruct_array(), ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, Max, MAXDIM, mda_get_range(), MemSet, Min, ArrayType::ndim, palloc0(), PointerGetDatum, and SET_VARSIZE.

Referenced by ExecEvalArrayRef().

2744 {
2745  ArrayType *array;
2746  ArrayType *srcArray;
2747  ArrayType *newarray;
2748  int i,
2749  ndim,
2750  dim[MAXDIM],
2751  lb[MAXDIM],
2752  span[MAXDIM];
2753  bool newhasnulls;
2754  int nitems,
2755  nsrcitems,
2756  olddatasize,
2757  newsize,
2758  olditemsize,
2759  newitemsize,
2760  overheadlen,
2761  oldoverheadlen,
2762  addedbefore,
2763  addedafter,
2764  lenbefore,
2765  lenafter,
2766  itemsbefore,
2767  itemsafter,
2768  nolditems;
2769 
2770  /* Currently, assignment from a NULL source array is a no-op */
2771  if (isNull)
2772  return arraydatum;
2773 
2774  if (arraytyplen > 0)
2775  {
2776  /*
2777  * fixed-length arrays -- not got round to doing this...
2778  */
2779  ereport(ERROR,
2780  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2781  errmsg("updates on slices of fixed-length arrays not implemented")));
2782  }
2783 
2784  /* detoast arrays if necessary */
2785  array = DatumGetArrayTypeP(arraydatum);
2786  srcArray = DatumGetArrayTypeP(srcArrayDatum);
2787 
2788  /* note: we assume srcArray contains no toasted elements */
2789 
2790  ndim = ARR_NDIM(array);
2791 
2792  /*
2793  * if number of dims is zero, i.e. an empty array, create an array with
2794  * nSubscripts dimensions, and set the upper and lower bounds to the
2795  * supplied subscripts
2796  */
2797  if (ndim == 0)
2798  {
2799  Datum *dvalues;
2800  bool *dnulls;
2801  int nelems;
2802  Oid elmtype = ARR_ELEMTYPE(array);
2803 
2804  deconstruct_array(srcArray, elmtype, elmlen, elmbyval, elmalign,
2805  &dvalues, &dnulls, &nelems);
2806 
2807  for (i = 0; i < nSubscripts; i++)
2808  {
2809  dim[i] = 1 + upperIndx[i] - lowerIndx[i];
2810  lb[i] = lowerIndx[i];
2811  }
2812 
2813  /* complain if too few source items; we ignore extras, however */
2814  if (nelems < ArrayGetNItems(nSubscripts, dim))
2815  ereport(ERROR,
2816  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2817  errmsg("source array too small")));
2818 
2819  return PointerGetDatum(construct_md_array(dvalues, dnulls, nSubscripts,
2820  dim, lb, elmtype,
2821  elmlen, elmbyval, elmalign));
2822  }
2823 
2824  if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
2825  ereport(ERROR,
2826  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2827  errmsg("wrong number of array subscripts")));
2828 
2829  /* copy dim/lb since we may modify them */
2830  memcpy(dim, ARR_DIMS(array), ndim * sizeof(int));
2831  memcpy(lb, ARR_LBOUND(array), ndim * sizeof(int));
2832 
2833  newhasnulls = (ARR_HASNULL(array) || ARR_HASNULL(srcArray));
2834  addedbefore = addedafter = 0;
2835 
2836  /*
2837  * Check subscripts
2838  */
2839  if (ndim == 1)
2840  {
2841  Assert(nSubscripts == 1);
2842  if (lowerIndx[0] > upperIndx[0])
2843  ereport(ERROR,
2844  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2845  errmsg("upper bound cannot be less than lower bound")));
2846  if (lowerIndx[0] < lb[0])
2847  {
2848  if (upperIndx[0] < lb[0] - 1)
2849  newhasnulls = true; /* will insert nulls */
2850  addedbefore = lb[0] - lowerIndx[0];
2851  dim[0] += addedbefore;
2852  lb[0] = lowerIndx[0];
2853  }
2854  if (upperIndx[0] >= (dim[0] + lb[0]))
2855  {
2856  if (lowerIndx[0] > (dim[0] + lb[0]))
2857  newhasnulls = true; /* will insert nulls */
2858  addedafter = upperIndx[0] - (dim[0] + lb[0]) + 1;
2859  dim[0] += addedafter;
2860  }
2861  }
2862  else
2863  {
2864  /*
2865  * XXX currently we do not support extending multi-dimensional arrays
2866  * during assignment
2867  */
2868  for (i = 0; i < nSubscripts; i++)
2869  {
2870  if (lowerIndx[i] > upperIndx[i])
2871  ereport(ERROR,
2872  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2873  errmsg("upper bound cannot be less than lower bound")));
2874  if (lowerIndx[i] < lb[i] ||
2875  upperIndx[i] >= (dim[i] + lb[i]))
2876  ereport(ERROR,
2877  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2878  errmsg("array subscript out of range")));
2879  }
2880  /* fill any missing subscript positions with full array range */
2881  for (; i < ndim; i++)
2882  {
2883  lowerIndx[i] = lb[i];
2884  upperIndx[i] = dim[i] + lb[i] - 1;
2885  if (lowerIndx[i] > upperIndx[i])
2886  ereport(ERROR,
2887  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2888  errmsg("upper bound cannot be less than lower bound")));
2889  }
2890  }
2891 
2892  /* Do this mainly to check for overflow */
2893  nitems = ArrayGetNItems(ndim, dim);
2894 
2895  /*
2896  * Make sure source array has enough entries. Note we ignore the shape of
2897  * the source array and just read entries serially.
2898  */
2899  mda_get_range(ndim, span, lowerIndx, upperIndx);
2900  nsrcitems = ArrayGetNItems(ndim, span);
2901  if (nsrcitems > ArrayGetNItems(ARR_NDIM(srcArray), ARR_DIMS(srcArray)))
2902  ereport(ERROR,
2903  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
2904  errmsg("source array too small")));
2905 
2906  /*
2907  * Compute space occupied by new entries, space occupied by replaced
2908  * entries, and required space for new array.
2909  */
2910  if (newhasnulls)
2911  overheadlen = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
2912  else
2913  overheadlen = ARR_OVERHEAD_NONULLS(ndim);
2914  newitemsize = array_nelems_size(ARR_DATA_PTR(srcArray), 0,
2915  ARR_NULLBITMAP(srcArray), nsrcitems,
2916  elmlen, elmbyval, elmalign);
2917  oldoverheadlen = ARR_DATA_OFFSET(array);
2918  olddatasize = ARR_SIZE(array) - oldoverheadlen;
2919  if (ndim > 1)
2920  {
2921  /*
2922  * here we do not need to cope with extension of the array; it would
2923  * be a lot more complicated if we had to do so...
2924  */
2925  olditemsize = array_slice_size(ARR_DATA_PTR(array),
2926  ARR_NULLBITMAP(array),
2927  ndim, dim, lb,
2928  lowerIndx, upperIndx,
2929  elmlen, elmbyval, elmalign);
2930  lenbefore = lenafter = 0; /* keep compiler quiet */
2931  itemsbefore = itemsafter = nolditems = 0;
2932  }
2933  else
2934  {
2935  /*
2936  * here we must allow for possibility of slice larger than orig array
2937  * and/or not adjacent to orig array subscripts
2938  */
2939  int oldlb = ARR_LBOUND(array)[0];
2940  int oldub = oldlb + ARR_DIMS(array)[0] - 1;
2941  int slicelb = Max(oldlb, lowerIndx[0]);
2942  int sliceub = Min(oldub, upperIndx[0]);
2943  char *oldarraydata = ARR_DATA_PTR(array);
2944  bits8 *oldarraybitmap = ARR_NULLBITMAP(array);
2945 
2946  /* count/size of old array entries that will go before the slice */
2947  itemsbefore = Min(slicelb, oldub + 1) - oldlb;
2948  lenbefore = array_nelems_size(oldarraydata, 0, oldarraybitmap,
2949  itemsbefore,
2950  elmlen, elmbyval, elmalign);
2951  /* count/size of old array entries that will be replaced by slice */
2952  if (slicelb > sliceub)
2953  {
2954  nolditems = 0;
2955  olditemsize = 0;
2956  }
2957  else
2958  {
2959  nolditems = sliceub - slicelb + 1;
2960  olditemsize = array_nelems_size(oldarraydata + lenbefore,
2961  itemsbefore, oldarraybitmap,
2962  nolditems,
2963  elmlen, elmbyval, elmalign);
2964  }
2965  /* count/size of old array entries that will go after the slice */
2966  itemsafter = oldub + 1 - Max(sliceub + 1, oldlb);
2967  lenafter = olddatasize - lenbefore - olditemsize;
2968  }
2969 
2970  newsize = overheadlen + olddatasize - olditemsize + newitemsize;
2971 
2972  newarray = (ArrayType *) palloc0(newsize);
2973  SET_VARSIZE(newarray, newsize);
2974  newarray->ndim = ndim;
2975  newarray->dataoffset = newhasnulls ? overheadlen : 0;
2976  newarray->elemtype = ARR_ELEMTYPE(array);
2977  memcpy(ARR_DIMS(newarray), dim, ndim * sizeof(int));
2978  memcpy(ARR_LBOUND(newarray), lb, ndim * sizeof(int));
2979 
2980  if (ndim > 1)
2981  {
2982  /*
2983  * here we do not need to cope with extension of the array; it would
2984  * be a lot more complicated if we had to do so...
2985  */
2986  array_insert_slice(newarray, array, srcArray,
2987  ndim, dim, lb,
2988  lowerIndx, upperIndx,
2989  elmlen, elmbyval, elmalign);
2990  }
2991  else
2992  {
2993  /* fill in data */
2994  memcpy((char *) newarray + overheadlen,
2995  (char *) array + oldoverheadlen,
2996  lenbefore);
2997  memcpy((char *) newarray + overheadlen + lenbefore,
2998  ARR_DATA_PTR(srcArray),
2999  newitemsize);
3000  memcpy((char *) newarray + overheadlen + lenbefore + newitemsize,
3001  (char *) array + oldoverheadlen + lenbefore + olditemsize,
3002  lenafter);
3003  /* fill in nulls bitmap if needed */
3004  if (newhasnulls)
3005  {
3006  bits8 *newnullbitmap = ARR_NULLBITMAP(newarray);
3007  bits8 *oldnullbitmap = ARR_NULLBITMAP(array);
3008 
3009  /* Zero the bitmap to handle marking inserted positions null */
3010  MemSet(newnullbitmap, 0, (nitems + 7) / 8);
3011  array_bitmap_copy(newnullbitmap, addedbefore,
3012  oldnullbitmap, 0,
3013  itemsbefore);
3014  array_bitmap_copy(newnullbitmap, lowerIndx[0] - lb[0],
3015  ARR_NULLBITMAP(srcArray), 0,
3016  nsrcitems);
3017  array_bitmap_copy(newnullbitmap, addedbefore + itemsbefore + nolditems,
3018  oldnullbitmap, itemsbefore + nolditems,
3019  itemsafter);
3020  }
3021  }
3022 
3023  return PointerGetDatum(newarray);
3024 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define ARR_SIZE(a)
Definition: array.h:270
#define MAXDIM
Definition: c.h:404
#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:4595
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:4666
#define Min(x, y)
Definition: c.h:787
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:569
#define MemSet(start, val, len)
Definition: c.h:838
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:41
Oid elemtype
Definition: array.h:81
#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:132
uint8 bits8
Definition: c.h:261
void * palloc0(Size size)
Definition: mcxt.c:921
uintptr_t Datum
Definition: postgres.h:374
void mda_get_range(int n, int *span, const int *st, const int *endp)
Definition: arrayutils.c:120
#define Max(x, y)
Definition: c.h:781
#define Assert(condition)
Definition: c.h:656
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)
Definition: arrayfuncs.c:4799
#define ARR_NDIM(a)
Definition: array.h:271
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3446
int errmsg(const char *fmt,...)
Definition: elog.c:791
int i
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
static int array_nelems_size(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4543
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:3311
#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 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

Definition at line 4666 of file arrayfuncs.c.

References array_get_isnull(), array_seek(), ArrayGetNItems(), ArrayGetOffset(), att_addlength_pointer, att_align_nominal, i, MAXDIM, mda_get_offset_values(), mda_get_prod(), mda_get_range(), and mda_next_tuple().

Referenced by array_get_slice(), and array_set_slice().

4670 {
4671  int src_offset,
4672  span[MAXDIM],
4673  prod[MAXDIM],
4674  dist[MAXDIM],
4675  indx[MAXDIM];
4676  char *ptr;
4677  int i,
4678  j,
4679  inc;
4680  int count = 0;
4681 
4682  mda_get_range(ndim, span, st, endp);
4683 
4684  /* Pretty easy for fixed element length without nulls ... */
4685  if (typlen > 0 && !arraynullsptr)
4686  return ArrayGetNItems(ndim, span) * att_align_nominal(typlen, typalign);
4687 
4688  /* Else gotta do it the hard way */
4689  src_offset = ArrayGetOffset(ndim, dim, lb, st);
4690  ptr = array_seek(arraydataptr, 0, arraynullsptr, src_offset,
4691  typlen, typbyval, typalign);
4692  mda_get_prod(ndim, dim, prod);
4693  mda_get_offset_values(ndim, dist, prod, span);
4694  for (i = 0; i < ndim; i++)
4695  indx[i] = 0;
4696  j = ndim - 1;
4697  do
4698  {
4699  if (dist[j])
4700  {
4701  ptr = array_seek(ptr, src_offset, arraynullsptr, dist[j],
4702  typlen, typbyval, typalign);
4703  src_offset += dist[j];
4704  }
4705  if (!array_get_isnull(arraynullsptr, src_offset))
4706  {
4707  inc = att_addlength_pointer(0, typlen, ptr);
4708  inc = att_align_nominal(inc, typalign);
4709  ptr += inc;
4710  count += inc;
4711  }
4712  src_offset++;
4713  } while ((j = mda_next_tuple(ndim, indx, span)) != -1);
4714  return count;
4715 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define MAXDIM
Definition: c.h:404
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
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
void mda_get_offset_values(int n, int *dist, const int *prod, const int *span)
Definition: arrayutils.c:150
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:4495
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4410
int mda_next_tuple(int n, int *curr, const int *span)
Definition: arrayutils.c:175
int i
Datum array_smaller ( PG_FUNCTION_ARGS  )

Definition at line 5505 of file arrayfuncs.c.

References array_cmp(), PG_GETARG_DATUM, and PG_RETURN_DATUM.

5506 {
5507  if (array_cmp(fcinfo) < 0)
5509  else
5511 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3731
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
Datum array_unnest ( PG_FUNCTION_ARGS  )

Definition at line 5873 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_NDIM, array_iter_next(), array_iter_setup(), ArrayGetNItems(), get_typlenbyvalalign(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, palloc(), PG_GETARG_ANY_ARRAY, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, ExpandedArrayHeader::typalign, ExpandedArrayHeader::typbyval, ExpandedArrayHeader::typlen, FuncCallContext::user_fctx, VARATT_IS_EXPANDED_HEADER, and AnyArrayType::xpn.

5874 {
5875  typedef struct
5876  {
5877  array_iter iter;
5878  int nextelem;
5879  int numelems;
5880  int16 elmlen;
5881  bool elmbyval;
5882  char elmalign;
5883  } array_unnest_fctx;
5884 
5885  FuncCallContext *funcctx;
5886  array_unnest_fctx *fctx;
5887  MemoryContext oldcontext;
5888 
5889  /* stuff done only on the first call of the function */
5890  if (SRF_IS_FIRSTCALL())
5891  {
5892  AnyArrayType *arr;
5893 
5894  /* create a function context for cross-call persistence */
5895  funcctx = SRF_FIRSTCALL_INIT();
5896 
5897  /*
5898  * switch to memory context appropriate for multiple function calls
5899  */
5900  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
5901 
5902  /*
5903  * Get the array value and detoast if needed. We can't do this
5904  * earlier because if we have to detoast, we want the detoasted copy
5905  * to be in multi_call_memory_ctx, so it will go away when we're done
5906  * and not before. (If no detoast happens, we assume the originally
5907  * passed array will stick around till then.)
5908  */
5909  arr = PG_GETARG_ANY_ARRAY(0);
5910 
5911  /* allocate memory for user context */
5912  fctx = (array_unnest_fctx *) palloc(sizeof(array_unnest_fctx));
5913 
5914  /* initialize state */
5915  array_iter_setup(&fctx->iter, arr);
5916  fctx->nextelem = 0;
5917  fctx->numelems = ArrayGetNItems(AARR_NDIM(arr), AARR_DIMS(arr));
5918 
5919  if (VARATT_IS_EXPANDED_HEADER(arr))
5920  {
5921  /* we can just grab the type data from expanded array */
5922  fctx->elmlen = arr->xpn.typlen;
5923  fctx->elmbyval = arr->xpn.typbyval;
5924  fctx->elmalign = arr->xpn.typalign;
5925  }
5926  else
5928  &fctx->elmlen,
5929  &fctx->elmbyval,
5930  &fctx->elmalign);
5931 
5932  funcctx->user_fctx = fctx;
5933  MemoryContextSwitchTo(oldcontext);
5934  }
5935 
5936  /* stuff done on every call of the function */
5937  funcctx = SRF_PERCALL_SETUP();
5938  fctx = funcctx->user_fctx;
5939 
5940  if (fctx->nextelem < fctx->numelems)
5941  {
5942  int offset = fctx->nextelem++;
5943  Datum elem;
5944 
5945  elem = array_iter_next(&fctx->iter, &fcinfo->isnull, offset,
5946  fctx->elmlen, fctx->elmbyval, fctx->elmalign);
5947 
5948  SRF_RETURN_NEXT(funcctx, elem);
5949  }
5950  else
5951  {
5952  /* do when there is no more left */
5953  SRF_RETURN_DONE(funcctx);
5954  }
5955 }
signed short int16
Definition: c.h:241
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1924
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExpandedArrayHeader xpn
Definition: array.h:161
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
uintptr_t Datum
Definition: postgres.h:374
#define AARR_DIMS(a)
Definition: array.h:317
#define AARR_ELEMTYPE(a)
Definition: array.h:315
#define AARR_NDIM(a)
Definition: array.h:309
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
#define VARATT_IS_EXPANDED_HEADER(PTR)
void * user_fctx
Definition: funcapi.h:90
void * palloc(Size size)
Definition: mcxt.c:892
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
Datum array_upper ( PG_FUNCTION_ARGS  )

Definition at line 1719 of file arrayfuncs.c.

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

1720 {
1722  int reqdim = PG_GETARG_INT32(1);
1723  int *dimv,
1724  *lb;
1725  int result;
1726 
1727  /* Sanity check: does it look like an array at all? */
1728  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
1729  PG_RETURN_NULL();
1730 
1731  /* Sanity check: was the requested dim valid */
1732  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
1733  PG_RETURN_NULL();
1734 
1735  lb = AARR_LBOUND(v);
1736  dimv = AARR_DIMS(v);
1737 
1738  result = dimv[reqdim - 1] + lb[reqdim - 1] - 1;
1739 
1740  PG_RETURN_INT32(result);
1741 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define MAXDIM
Definition: c.h:404
#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_LBOUND(a)
Definition: array.h:319
#define AARR_NDIM(a)
Definition: array.h:309
#define PG_RETURN_NULL()
Definition: fmgr.h:289
static Datum ArrayCast ( char *  value,
bool  byval,
int  len 
)
static

Definition at line 4445 of file arrayfuncs.c.

References fetch_att.

Referenced by array_get_element().

4446 {
4447  return fetch_att(value, byval, len);
4448 }
static struct @72 value
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
static int ArrayCastAndSet ( Datum  src,
int  typlen,
bool  typbyval,
char  typalign,
char *  dest 
)
static

Definition at line 4456 of file arrayfuncs.c.

References Assert, att_addlength_datum, att_align_nominal, DatumGetPointer, memmove, and store_att_byval.

Referenced by array_fill_internal(), array_set_element(), and CopyArrayEls().

4461 {
4462  int inc;
4463 
4464  if (typlen > 0)
4465  {
4466  if (typbyval)
4467  store_att_byval(dest, src, typlen);
4468  else
4469  memmove(dest, DatumGetPointer(src), typlen);
4470  inc = att_align_nominal(typlen, typalign);
4471  }
4472  else
4473  {
4474  Assert(!typbyval);
4475  inc = att_addlength_datum(0, typlen, src);
4476  memmove(dest, DatumGetPointer(src), inc);
4477  inc = att_align_nominal(inc, typalign);
4478  }
4479 
4480  return inc;
4481 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define memmove(d, s, c)
Definition: c.h:1027
#define store_att_byval(T, newdatum, attlen)
Definition: tupmacs.h:222
#define Assert(condition)
Definition: c.h:656
#define DatumGetPointer(X)
Definition: postgres.h:557
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
Datum arraycontained ( PG_FUNCTION_ARGS  )

Definition at line 4189 of file arrayfuncs.c.

References AARR_FREE_IF_COPY, array_contain_compare(), PG_GET_COLLATION, PG_GETARG_ANY_ARRAY, and PG_RETURN_BOOL.

4190 {
4191  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY(0);
4192  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY(1);
4193  Oid collation = PG_GET_COLLATION();
4194  bool result;
4195 
4196  result = array_contain_compare(array1, array2, collation, true,
4197  &fcinfo->flinfo->fn_extra);
4198 
4199  /* Avoid leaking memory when handed toasted input. */
4200  AARR_FREE_IF_COPY(array1, 0);
4201  AARR_FREE_IF_COPY(array2, 1);
4202 
4203  PG_RETURN_BOOL(result);
4204 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GET_COLLATION()
Definition: fmgr.h:155
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
static bool array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, bool matchall, void **fn_extra)
Definition: arrayfuncs.c:4010
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
#define AARR_FREE_IF_COPY(array, n)
Definition: arrayfuncs.c:46
Datum arraycontains ( PG_FUNCTION_ARGS  )

Definition at line 4171 of file arrayfuncs.c.

References AARR_FREE_IF_COPY, array_contain_compare(), PG_GET_COLLATION, PG_GETARG_ANY_ARRAY, and PG_RETURN_BOOL.

4172 {
4173  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY(0);
4174  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY(1);
4175  Oid collation = PG_GET_COLLATION();
4176  bool result;
4177 
4178  result = array_contain_compare(array2, array1, collation, true,
4179  &fcinfo->flinfo->fn_extra);
4180 
4181  /* Avoid leaking memory when handed toasted input. */
4182  AARR_FREE_IF_COPY(array1, 0);
4183  AARR_FREE_IF_COPY(array2, 1);
4184 
4185  PG_RETURN_BOOL(result);
4186 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GET_COLLATION()
Definition: fmgr.h:155
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
static bool array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, bool matchall, void **fn_extra)
Definition: arrayfuncs.c:4010
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
#define AARR_FREE_IF_COPY(array, n)
Definition: arrayfuncs.c:46
static int ArrayCount ( const char *  str,
int *  dim,
char  typdelim 
)
static

Definition at line 451 of file arrayfuncs.c.

References ARRAY_ELEM_COMPLETED, ARRAY_ELEM_DELIMITED, ARRAY_ELEM_STARTED, array_isspace(), ARRAY_LEVEL_COMPLETED, ARRAY_LEVEL_DELIMITED, ARRAY_LEVEL_STARTED, ARRAY_NO_LEVEL, ARRAY_QUOTED_ELEM_COMPLETED, ARRAY_QUOTED_ELEM_STARTED, ereport, errcode(), errdetail(), errmsg(), ERROR, i, and MAXDIM.

Referenced by array_in().

452 {
453  int nest_level = 0,
454  i;
455  int ndim = 1,
456  temp[MAXDIM],
457  nelems[MAXDIM],
458  nelems_last[MAXDIM];
459  bool in_quotes = false;
460  bool eoArray = false;
461  bool empty_array = true;
462  const char *ptr;
463  ArrayParseState parse_state = ARRAY_NO_LEVEL;
464 
465  for (i = 0; i < MAXDIM; ++i)
466  {
467  temp[i] = dim[i] = nelems_last[i] = 0;
468  nelems[i] = 1;
469  }
470 
471  ptr = str;
472  while (!eoArray)
473  {
474  bool itemdone = false;
475 
476  while (!itemdone)
477  {
478  if (parse_state == ARRAY_ELEM_STARTED ||
479  parse_state == ARRAY_QUOTED_ELEM_STARTED)
480  empty_array = false;
481 
482  switch (*ptr)
483  {
484  case '\0':
485  /* Signal a premature end of the string */
486  ereport(ERROR,
487  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
488  errmsg("malformed array literal: \"%s\"", str),
489  errdetail("Unexpected end of input.")));
490  break;
491  case '\\':
492 
493  /*
494  * An escape must be after a level start, after an element
495  * start, or after an element delimiter. In any case we
496  * now must be past an element start.
497  */
498  if (parse_state != ARRAY_LEVEL_STARTED &&
499  parse_state != ARRAY_ELEM_STARTED &&
500  parse_state != ARRAY_QUOTED_ELEM_STARTED &&
501  parse_state != ARRAY_ELEM_DELIMITED)
502  ereport(ERROR,
503  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
504  errmsg("malformed array literal: \"%s\"", str),
505  errdetail("Unexpected \"%c\" character.",
506  '\\')));
507  if (parse_state != ARRAY_QUOTED_ELEM_STARTED)
508  parse_state = ARRAY_ELEM_STARTED;
509  /* skip the escaped character */
510  if (*(ptr + 1))
511  ptr++;
512  else
513  ereport(ERROR,
514  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
515  errmsg("malformed array literal: \"%s\"", str),
516  errdetail("Unexpected end of input.")));
517  break;
518  case '\"':
519 
520  /*
521  * A quote must be after a level start, after a quoted
522  * element start, or after an element delimiter. In any
523  * case we now must be past an element start.
524  */
525  if (parse_state != ARRAY_LEVEL_STARTED &&
526  parse_state != ARRAY_QUOTED_ELEM_STARTED &&
527  parse_state != ARRAY_ELEM_DELIMITED)
528  ereport(ERROR,
529  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
530  errmsg("malformed array literal: \"%s\"", str),
531  errdetail("Unexpected array element.")));
532  in_quotes = !in_quotes;
533  if (in_quotes)
534  parse_state = ARRAY_QUOTED_ELEM_STARTED;
535  else
536  parse_state = ARRAY_QUOTED_ELEM_COMPLETED;
537  break;
538  case '{':
539  if (!in_quotes)
540  {
541  /*
542  * A left brace can occur if no nesting has occurred
543  * yet, after a level start, or after a level
544  * delimiter.
545  */
546  if (parse_state != ARRAY_NO_LEVEL &&
547  parse_state != ARRAY_LEVEL_STARTED &&
548  parse_state != ARRAY_LEVEL_DELIMITED)
549  ereport(ERROR,
550  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
551  errmsg("malformed array literal: \"%s\"", str),
552  errdetail("Unexpected \"%c\" character.",
553  '{')));
554  parse_state = ARRAY_LEVEL_STARTED;
555  if (nest_level >= MAXDIM)
556  ereport(ERROR,
557  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
558  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
559  nest_level + 1, MAXDIM)));
560  temp[nest_level] = 0;
561  nest_level++;
562  if (ndim < nest_level)
563  ndim = nest_level;
564  }
565  break;
566  case '}':
567  if (!in_quotes)
568  {
569  /*
570  * A right brace can occur after an element start, an
571  * element completion, a quoted element completion, or
572  * a level completion.
573  */
574  if (parse_state != ARRAY_ELEM_STARTED &&
575  parse_state != ARRAY_ELEM_COMPLETED &&
576  parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
577  parse_state != ARRAY_LEVEL_COMPLETED &&
578  !(nest_level == 1 && parse_state == ARRAY_LEVEL_STARTED))
579  ereport(ERROR,
580  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
581  errmsg("malformed array literal: \"%s\"", str),
582  errdetail("Unexpected \"%c\" character.",
583  '}')));
584  parse_state = ARRAY_LEVEL_COMPLETED;
585  if (nest_level == 0)
586  ereport(ERROR,
587  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
588  errmsg("malformed array literal: \"%s\"", str),
589  errdetail("Unmatched \"%c\" character.", '}')));
590  nest_level--;
591 
592  if (nelems_last[nest_level] != 0 &&
593  nelems[nest_level] != nelems_last[nest_level])
594  ereport(ERROR,
595  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
596  errmsg("malformed array literal: \"%s\"", str),
597  errdetail("Multidimensional arrays must have "
598  "sub-arrays with matching "
599  "dimensions.")));
600  nelems_last[nest_level] = nelems[nest_level];
601  nelems[nest_level] = 1;
602  if (nest_level == 0)
603  eoArray = itemdone = true;
604  else
605  {
606  /*
607  * We don't set itemdone here; see comments in
608  * ReadArrayStr
609  */
610  temp[nest_level - 1]++;
611  }
612  }
613  break;
614  default:
615  if (!in_quotes)
616  {
617  if (*ptr == typdelim)
618  {
619  /*
620  * Delimiters can occur after an element start, an
621  * element completion, a quoted element
622  * completion, or a level completion.
623  */
624  if (parse_state != ARRAY_ELEM_STARTED &&
625  parse_state != ARRAY_ELEM_COMPLETED &&
626  parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
627  parse_state != ARRAY_LEVEL_COMPLETED)
628  ereport(ERROR,
629  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
630  errmsg("malformed array literal: \"%s\"", str),
631  errdetail("Unexpected \"%c\" character.",
632  typdelim)));
633  if (parse_state == ARRAY_LEVEL_COMPLETED)
634  parse_state = ARRAY_LEVEL_DELIMITED;
635  else
636  parse_state = ARRAY_ELEM_DELIMITED;
637  itemdone = true;
638  nelems[nest_level - 1]++;
639  }
640  else if (!array_isspace(*ptr))
641  {
642  /*
643  * Other non-space characters must be after a
644  * level start, after an element start, or after
645  * an element delimiter. In any case we now must
646  * be past an element start.
647  */
648  if (parse_state != ARRAY_LEVEL_STARTED &&
649  parse_state != ARRAY_ELEM_STARTED &&
650  parse_state != ARRAY_ELEM_DELIMITED)
651  ereport(ERROR,
652  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
653  errmsg("malformed array literal: \"%s\"", str),
654  errdetail("Unexpected array element.")));
655  parse_state = ARRAY_ELEM_STARTED;
656  }
657  }
658  break;
659  }
660  if (!itemdone)
661  ptr++;
662  }
663  temp[ndim - 1]++;
664  ptr++;
665  }
666 
667  /* only whitespace is allowed after the closing brace */
668  while (*ptr)
669  {
670  if (!array_isspace(*ptr++))
671  ereport(ERROR,
672  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
673  errmsg("malformed array literal: \"%s\"", str),
674  errdetail("Junk after closing right brace.")));
675  }
676 
677  /* special case for an empty array */
678  if (empty_array)
679  return 0;
680 
681  for (i = 0; i < ndim; ++i)
682  dim[i] = temp[i];
683 
684  return ndim;
685 }
static bool array_isspace(char ch)
Definition: arrayfuncs.c:431
#define MAXDIM
Definition: c.h:404
int errcode(int sqlerrcode)
Definition: elog.c:569
ArrayParseState
Definition: arrayfuncs.c:52
#define ERROR
Definition: elog.h:41
int errdetail(const char *fmt,...)
Definition: elog.c:864
#define ereport(elevel, rest)
Definition: elog.h:132
int errmsg(const char *fmt,...)
Definition: elog.c:791
int i
Datum arrayoverlap ( PG_FUNCTION_ARGS  )

Definition at line 4153 of file arrayfuncs.c.

References AARR_FREE_IF_COPY, array_contain_compare(), PG_GET_COLLATION, PG_GETARG_ANY_ARRAY, and PG_RETURN_BOOL.

4154 {
4155  AnyArrayType *array1 = PG_GETARG_ANY_ARRAY(0);
4156  AnyArrayType *array2 = PG_GETARG_ANY_ARRAY(1);
4157  Oid collation = PG_GET_COLLATION();
4158  bool result;
4159 
4160  result = array_contain_compare(array1, array2, collation, false,
4161  &fcinfo->flinfo->fn_extra);
4162 
4163  /* Avoid leaking memory when handed toasted input. */
4164  AARR_FREE_IF_COPY(array1, 0);
4165  AARR_FREE_IF_COPY(array2, 1);
4166 
4167  PG_RETURN_BOOL(result);
4168 }
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GET_COLLATION()
Definition: fmgr.h:155
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
static bool array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, bool matchall, void **fn_extra)
Definition: arrayfuncs.c:4010
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
#define AARR_FREE_IF_COPY(array, n)
Definition: arrayfuncs.c:46
Datum btarraycmp ( PG_FUNCTION_ARGS  )

Definition at line 3719 of file arrayfuncs.c.

References array_cmp(), and PG_RETURN_INT32.

3720 {
3721  PG_RETURN_INT32(array_cmp(fcinfo));
3722 }
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
static int array_cmp(FunctionCallInfo fcinfo)
Definition: arrayfuncs.c:3731
ArrayType* construct_array ( Datum elems,
int  nelems,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 3277 of file arrayfuncs.c.

References construct_md_array(), and NULL.

Referenced by AlterPolicy(), build_regtype_array(), CreateConstraintEntry(), CreateFunction(), CreatePolicy(), current_schemas(), enum_range_internal(), extension_config_remove(), filter_list_to_array(), float4_accum(), float8_accum(), float8_regr_accum(), get_available_versions_for_extension(), gin_leafpage_items(), gin_page_opaque_info(), GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), hstore_akeys(), interpret_function_parameter_list(), interval_accum(), interval_accum_inv(), pg_extension_config_dump(), pull_row_security_policies(), RelationBuildRowSecurity(), show_trgm(), strlist_to_textarray(), test_rls_hooks_permissive(), test_rls_hooks_restrictive(), ts_lexize(), typenameTypeMod(), and update_attstats().

3280 {
3281  int dims[1];
3282  int lbs[1];
3283 
3284  dims[0] = nelems;
3285  lbs[0] = 1;
3286 
3287  return construct_md_array(elems, NULL, 1, dims, lbs,
3288  elmtype, elmlen, elmbyval, elmalign);
3289 }
#define NULL
Definition: c.h:215
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:3311
ExpandedArrayHeader* construct_empty_expanded_array ( Oid  element_type,
MemoryContext  parentcontext,
ArrayMetaState metacache 
)

Definition at line 3412 of file arrayfuncs.c.

References construct_empty_array(), DatumGetEOHP(), expand_array(), pfree(), and PointerGetDatum.

Referenced by fetch_array_arg_replace_nulls().

3415 {
3416  ArrayType *array = construct_empty_array(element_type);
3417  Datum d;
3418 
3419  d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3420  pfree(array);
3421  return (ExpandedArrayHeader *) DatumGetEOHP(d);
3422 }
#define PointerGetDatum(X)
Definition: postgres.h:564
Datum expand_array(Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3395
void pfree(void *pointer)
Definition: mcxt.c:993
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
uintptr_t Datum
Definition: postgres.h:374
ArrayType* construct_md_array ( Datum elems,
bool nulls,
int  ndims,
int *  dims,
int *  lbs,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 3311 of file arrayfuncs.c.

References AllocSizeIsValid, ARR_DIMS, ARR_LBOUND, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ArrayGetNItems(), att_addlength_datum, att_align_nominal, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, MaxAllocSize, MAXDIM, ArrayType::ndim, palloc0(), PG_DETOAST_DATUM, PointerGetDatum, and SET_VARSIZE.

Referenced by array_iterate(), array_set_element(), array_set_slice(), build_regexp_matches_result(), construct_array(), create_singleton_array(), ExecEvalArray(), hstore_avals(), hstore_slice_to_array(), hstore_to_array_internal(), makeMdArrayResult(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), plpgsql_exec_trigger(), and PLySequence_ToArray().

3317 {
3318  ArrayType *result;
3319  bool hasnulls;
3320  int32 nbytes;
3321  int32 dataoffset;
3322  int i;
3323  int nelems;
3324 
3325  if (ndims < 0) /* we do allow zero-dimension arrays */
3326  ereport(ERROR,
3327  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3328  errmsg("invalid number of dimensions: %d", ndims)));
3329  if (ndims > MAXDIM)
3330  ereport(ERROR,
3331  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3332  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
3333  ndims, MAXDIM)));
3334 
3335  /* fast track for empty array */
3336  if (ndims == 0)
3337  return construct_empty_array(elmtype);
3338 
3339  nelems = ArrayGetNItems(ndims, dims);
3340 
3341  /* compute required space */
3342  nbytes = 0;
3343  hasnulls = false;
3344  for (i = 0; i < nelems; i++)
3345  {
3346  if (nulls && nulls[i])
3347  {
3348  hasnulls = true;
3349  continue;
3350  }
3351  /* make sure data is not toasted */
3352  if (elmlen == -1)
3353  elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i]));
3354  nbytes = att_addlength_datum(nbytes, elmlen, elems[i]);
3355  nbytes = att_align_nominal(nbytes, elmalign);
3356  /* check for overflow of total request */
3357  if (!AllocSizeIsValid(nbytes))
3358  ereport(ERROR,
3359  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3360  errmsg("array size exceeds the maximum allowed (%d)",
3361  (int) MaxAllocSize)));
3362  }
3363 
3364  /* Allocate and initialize result array */
3365  if (hasnulls)
3366  {
3367  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nelems);
3368  nbytes += dataoffset;
3369  }
3370  else
3371  {
3372  dataoffset = 0; /* marker for no null bitmap */
3373  nbytes += ARR_OVERHEAD_NONULLS(ndims);
3374  }
3375  result = (ArrayType *) palloc0(nbytes);
3376  SET_VARSIZE(result, nbytes);
3377  result->ndim = ndims;
3378  result->dataoffset = dataoffset;
3379  result->elemtype = elmtype;
3380  memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
3381  memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
3382 
3383  CopyArrayEls(result,
3384  elems, nulls, nelems,
3385  elmlen, elmbyval, elmalign,
3386  false);
3387 
3388  return result;
3389 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define MAXDIM
Definition: c.h:404
#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:569
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3395
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
signed int int32
Definition: c.h:242
#define ARR_LBOUND(a)
Definition: array.h:277
#define ERROR
Definition: elog.h:41
Oid elemtype
Definition: array.h:81
#define ARR_DIMS(a)
Definition: array.h:275
#define ereport(elevel, rest)
Definition: elog.h:132
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void * palloc0(Size size)
Definition: mcxt.c:921
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:956
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
int errmsg(const char *fmt,...)
Definition: elog.c:791
int i
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:196
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
int ndim
Definition: array.h:79
void CopyArrayEls ( ArrayType array,
Datum values,
bool nulls,
int  nitems,
int  typlen,
bool  typbyval,
char  typalign,
bool  freedata 
)

Definition at line 956 of file arrayfuncs.c.

References ARR_DATA_PTR, ARR_NULLBITMAP, ArrayCastAndSet(), DatumGetPointer, elog, ERROR, i, and pfree().

Referenced by array_in(), array_map(), array_recv(), array_replace_internal(), construct_md_array(), and EA_flatten_into().

964 {
965  char *p = ARR_DATA_PTR(array);
966  bits8 *bitmap = ARR_NULLBITMAP(array);
967  int bitval = 0;
968  int bitmask = 1;
969  int i;
970 
971  if (typbyval)
972  freedata = false;
973 
974  for (i = 0; i < nitems; i++)
975  {
976  if (nulls && nulls[i])
977  {
978  if (!bitmap) /* shouldn't happen */
979  elog(ERROR, "null array element where not supported");
980  /* bitmap bit stays 0 */
981  }
982  else
983  {
984  bitval |= bitmask;
985  p += ArrayCastAndSet(values[i], typlen, typbyval, typalign, p);
986  if (freedata)
988  }
989  if (bitmap)
990  {
991  bitmask <<= 1;
992  if (bitmask == 0x100)
993  {
994  *bitmap++ = bitval;
995  bitval = 0;
996  bitmask = 1;
997  }
998  }
999  }
1000 
1001  if (bitmap && bitmask != 1)
1002  *bitmap = bitval;
1003 }
static int ArrayCastAndSet(Datum src, int typlen, bool typbyval, char typalign, char *dest)
Definition: arrayfuncs.c:4456
void pfree(void *pointer)
Definition: mcxt.c:993
#define ERROR
Definition: elog.h:41
#define ARR_DATA_PTR(a)
Definition: array.h:303
uint8 bits8
Definition: c.h:261
#define DatumGetPointer(X)
Definition: postgres.h:557
static Datum values[MAXATTR]
Definition: bootstrap.c:159
int i
#define elog
Definition: elog.h:228
#define ARR_NULLBITMAP(a)
Definition: array.h:281
static ArrayType * create_array_envelope ( int  ndims,
int *  dimv,
int *  lbv,
int  nbytes,
Oid  elmtype,
int  dataoffset 
)
static

Definition at line 5677 of file arrayfuncs.c.

References ARR_DIMS, ARR_LBOUND, ArrayType::dataoffset, ArrayType::elemtype, ArrayType::ndim, palloc0(), and SET_VARSIZE.

Referenced by array_fill_internal().

5679 {
5680  ArrayType *result;
5681 
5682  result = (ArrayType *) palloc0(nbytes);
5683  SET_VARSIZE(result, nbytes);
5684  result->ndim = ndims;
5685  result->dataoffset = dataoffset;
5686  result->elemtype = elmtype;
5687  memcpy(ARR_DIMS(result), dimv, ndims * sizeof(int));
5688  memcpy(ARR_LBOUND(result), lbsv, ndims * sizeof(int));
5689 
5690  return result;
5691 }
int32 dataoffset
Definition: array.h:80
#define ARR_LBOUND(a)
Definition: array.h:277
Oid elemtype
Definition: array.h:81
#define ARR_DIMS(a)
Definition: array.h:275
void * palloc0(Size size)
Definition: mcxt.c:921
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
int ndim
Definition: array.h:79
void deconstruct_array ( ArrayType array,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign,
Datum **  elemsp,
bool **  nullsp,
int *  nelemsp 
)

Definition at line 3446 of file arrayfuncs.c.

References ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), Assert, att_addlength_pointer, att_align_nominal, ereport, errcode(), errmsg(), ERROR, fetch_att, i, NULL, palloc(), and palloc0().

Referenced by _bt_preprocess_array_keys(), array_contain_compare(), array_set_slice(), array_to_json_internal(), array_to_jsonb_internal(), arrayconst_startup_fn(), ArrayGetIntegerTypmods(), binary_upgrade_create_empty_extension(), build_function_result_tupdesc_d(), compute_array_stats(), DecodeTextArrayToCString(), decompile_column_index_array(), deconstruct_expanded_array(), ExecIndexEvalArrayKeys(), extension_config_remove(), generateClonedIndexStmt(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_jsonb_path_all(), get_path_all(), ghstore_consistent(), gin_extract_hstore_query(), gin_extract_jsonb_query(), ginarrayextract(), gincost_scalararrayopexpr(), ginqueryarrayextract(), hstore_from_array(), hstore_from_arrays(), hstore_slice_to_array(), hstoreArrayToPairs(), interval_accum(), interval_accum_inv(), interval_avg(), json_object(), json_object_two_arg(), jsonb_delete_path(), jsonb_exists_all(), jsonb_exists_any(), jsonb_object(), jsonb_object_two_arg(), jsonb_set(), map_sql_value_to_xml_value(), mcelem_array_selec(), oid_array_to_list(), parse_key_value_arrays(), parseRelOptions(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), pg_get_constraintdef_worker(), pg_get_object_address(), pg_logical_slot_get_changes_guts(), plperl_ref_from_pg_array(), scalararraysel(), text_format(), textarray_to_strvaluelist(), TidListCreate(), transformRelOptions(), tsa_rewrite_accum(), and untransformRelOptions().

3450 {
3451  Datum *elems;
3452  bool *nulls;
3453  int nelems;
3454  char *p;
3455  bits8 *bitmap;
3456  int bitmask;
3457  int i;
3458 
3459  Assert(ARR_ELEMTYPE(array) == elmtype);
3460 
3461  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3462  *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
3463  if (nullsp)
3464  *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
3465  else
3466  nulls = NULL;
3467  *nelemsp = nelems;
3468 
3469  p = ARR_DATA_PTR(array);
3470  bitmap = ARR_NULLBITMAP(array);
3471  bitmask = 1;
3472 
3473  for (i = 0; i < nelems; i++)
3474  {
3475  /* Get source element, checking for NULL */
3476  if (bitmap && (*bitmap & bitmask) == 0)
3477  {
3478  elems[i] = (Datum) 0;
3479  if (nulls)
3480  nulls[i] = true;
3481  else
3482  ereport(ERROR,
3483  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3484  errmsg("null array element not allowed in this context")));
3485  }
3486  else
3487  {
3488  elems[i] = fetch_att(p, elmbyval, elmlen);
3489  p = att_addlength_pointer(p, elmlen, p);
3490  p = (char *) att_align_nominal(p, elmalign);
3491  }
3492 
3493  /* advance bitmap pointer if any */
3494  if (bitmap)
3495  {
3496  bitmask <<= 1;
3497  if (bitmask == 0x100)
3498  {
3499  bitmap++;
3500  bitmask = 1;
3501  }
3502  }
3503  }
3504 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:569
#define ERROR
Definition: elog.h:41
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
#define ereport(elevel, rest)
Definition: elog.h:132
uint8 bits8
Definition: c.h:261
void * palloc0(Size size)
Definition: mcxt.c:921
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:215
#define Assert(condition)
Definition: c.h:656
#define ARR_NDIM(a)
Definition: array.h:271
void * palloc(Size size)
Definition: mcxt.c:892
int errmsg(const char *fmt,...)
Definition: elog.c:791
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
int i
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define ARR_NULLBITMAP(a)
Definition: array.h:281
Datum generate_subscripts ( PG_FUNCTION_ARGS  )

Definition at line 5526 of file arrayfuncs.c.

References AARR_DIMS, AARR_LBOUND, AARR_NDIM, Int32GetDatum, generate_subscripts_fctx::lower, MAXDIM, MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, palloc(), PG_GETARG_ANY_ARRAY, PG_GETARG_BOOL, PG_GETARG_INT32, PG_NARGS, generate_subscripts_fctx::reverse, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, generate_subscripts_fctx::upper, and FuncCallContext::user_fctx.

Referenced by generate_subscripts_nodir().

5527 {
5528  FuncCallContext *funcctx;
5529  MemoryContext oldcontext;
5531 
5532  /* stuff done only on the first call of the function */
5533  if (SRF_IS_FIRSTCALL())
5534  {
5536  int reqdim = PG_GETARG_INT32(1);
5537  int *lb,
5538  *dimv;
5539 
5540  /* create a function context for cross-call persistence */
5541  funcctx = SRF_FIRSTCALL_INIT();
5542 
5543  /* Sanity check: does it look like an array at all? */
5544  if (AARR_NDIM(v) <= 0 || AARR_NDIM(v) > MAXDIM)
5545  SRF_RETURN_DONE(funcctx);
5546 
5547  /* Sanity check: was the requested dim valid */
5548  if (reqdim <= 0 || reqdim > AARR_NDIM(v))
5549  SRF_RETURN_DONE(funcctx);
5550 
5551  /*
5552  * switch to memory context appropriate for multiple function calls
5553  */
5554  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
5556 
5557  lb = AARR_LBOUND(v);
5558  dimv = AARR_DIMS(v);
5559 
5560  fctx->lower = lb[reqdim - 1];
5561  fctx->upper = dimv[reqdim - 1] + lb[reqdim - 1] - 1;
5562  fctx->reverse = (PG_NARGS() < 3) ? false : PG_GETARG_BOOL(2);
5563 
5564  funcctx->user_fctx = fctx;
5565 
5566  MemoryContextSwitchTo(oldcontext);
5567  }
5568 
5569  funcctx = SRF_PERCALL_SETUP();
5570 
5571  fctx = funcctx->user_fctx;
5572 
5573  if (fctx->lower <= fctx->upper)
5574  {
5575  if (!fctx->reverse)
5576  SRF_RETURN_NEXT(funcctx, Int32GetDatum(fctx->lower++));
5577  else
5578  SRF_RETURN_NEXT(funcctx, Int32GetDatum(fctx->upper--));
5579  }
5580  else
5581  /* done when there are no more elements left */
5582  SRF_RETURN_DONE(funcctx);
5583 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define MAXDIM
Definition: c.h:404
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:230
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
#define PG_GETARG_ANY_ARRAY(n)
Definition: array.h:255
#define AARR_DIMS(a)
Definition: array.h:317
#define AARR_LBOUND(a)
Definition: array.h:319
#define AARR_NDIM(a)
Definition: array.h:309
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
#define PG_NARGS()
Definition: fmgr.h:160
#define Int32GetDatum(X)
Definition: postgres.h:487
void * user_fctx
Definition: funcapi.h:90
void * palloc(Size size)
Definition: mcxt.c:892
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
Datum generate_subscripts_nodir ( PG_FUNCTION_ARGS  )

Definition at line 5590 of file arrayfuncs.c.

References generate_subscripts().

5591 {
5592  /* just call the other one -- it can handle both cases */
5593  return generate_subscripts(fcinfo);
5594 }
Datum generate_subscripts(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:5526
Datum hash_array ( PG_FUNCTION_ARGS  )

Definition at line 3902 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_FREE_IF_COPY, AARR_NDIM, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, array_iter_next(), array_iter_setup(), ArrayGetNItems(), DatumGetUInt32, ereport, errcode(), errmsg(), ERROR, FmgrInfo::fn_oid, format_type_be(), FunctionCallInvoke, TypeCacheEntry::hash_proc_finfo, i, InitFunctionCallInfoData, InvalidOid, FunctionCallInfoData::isnull, lookup_type_cache(), NULL, OidIsValid, PG_GETARG_ANY_ARRAY, PG_RETURN_UINT32, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TYPECACHE_HASH_PROC_FINFO, and TypeCacheEntry::typlen.

3903 {
3904  AnyArrayType *array = PG_GETARG_ANY_ARRAY(0);
3905  int ndims = AARR_NDIM(array);
3906  int *dims = AARR_DIMS(array);
3907  Oid element_type = AARR_ELEMTYPE(array);
3908  uint32 result = 1;
3909  int nitems;
3910  TypeCacheEntry *typentry;
3911  int typlen;
3912  bool typbyval;
3913  char typalign;
3914  int i;
3915  array_iter iter;
3916  FunctionCallInfoData locfcinfo;
3917 
3918  /*
3919  * We arrange to look up the hash function only once per series of calls,
3920  * assuming the element type doesn't change underneath us. The typcache
3921  * is used so that we have no memory leakage when being used as an index
3922  * support function.
3923  */
3924  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
3925  if (typentry == NULL ||
3926  typentry->type_id != element_type)
3927  {
3928  typentry = lookup_type_cache(element_type,
3930  if (!OidIsValid(typentry->hash_proc_finfo.fn_oid))
3931  ereport(ERROR,
3932  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3933  errmsg("could not identify a hash function for type %s",
3934  format_type_be(element_type))));
3935  fcinfo->flinfo->fn_extra = (void *) typentry;
3936  }
3937  typlen = typentry->typlen;
3938  typbyval = typentry->typbyval;
3939  typalign = typentry->typalign;
3940 
3941  /*
3942  * apply the hash function to each array element.
3943  */
3944  InitFunctionCallInfoData(locfcinfo, &typentry->hash_proc_finfo, 1,
3945  InvalidOid, NULL, NULL);
3946 
3947  /* Loop over source data */
3948  nitems = ArrayGetNItems(ndims, dims);
3949  array_iter_setup(&iter, array);
3950 
3951  for (i = 0; i < nitems; i++)
3952  {
3953  Datum elt;
3954  bool isnull;
3955  uint32 elthash;
3956 
3957  /* Get element, checking for NULL */
3958  elt = array_iter_next(&iter, &isnull, i, typlen, typbyval, typalign);
3959 
3960  if (isnull)
3961  {
3962  /* Treat nulls as having hashvalue 0 */
3963  elthash = 0;
3964  }
3965  else
3966  {
3967  /* Apply the hash function */
3968  locfcinfo.arg[0] = elt;
3969  locfcinfo.argnull[0] = false;
3970  locfcinfo.isnull = false;
3971  elthash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo));
3972  }
3973 
3974  /*
3975  * Combine hash values of successive elements by multiplying the
3976  * current value by 31 and adding on the new element's hash value.
3977  *
3978  * The result is a sum in which each element's hash value is
3979  * multiplied by a different power of 31. This is modulo 2^32
3980  * arithmetic, and the powers of 31 modulo 2^32 form a cyclic group of
3981  * order 2^27. So for arrays of up to 2^27 elements, each element's
3982  * hash value is multiplied by a different (odd) number, resulting in
3983  * a good mixing of all the elements' hash values.
3984  */
3985  result = (result << 5) - result + elthash;
3986  }
3987 
3988  /* Avoid leaking memory when handed toasted input. */
3989  AARR_FREE_IF_COPY(array, 0);
3990 
3991  PG_RETURN_UINT32(result);
3992 }
#define DatumGetUInt32(X)
Definition: postgres.h:494
static Datum array_iter_next(array_iter *it, bool *isnull, int i, int elmlen, bool elmbyval, char elmalign)
Definition: arrayaccess.h:81
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:117
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:569
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:519
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:299
#define ERROR
Definition: elog.h:41
#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
unsigned int uint32
Definition: c.h:254
FmgrInfo hash_proc_finfo
Definition: typcache.h:69
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
#define ereport(elevel, rest)
Definition: elog.h:132
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:182
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:56
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:215
#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:791
int i
ArrayBuildState* initArrayResult ( Oid  element_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 4922 of file arrayfuncs.c.

References ArrayBuildState::alen, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), ArrayBuildState::dnulls, ArrayBuildState::dvalues, ArrayBuildState::element_type, get_typlenbyvalalign(), ArrayBuildState::mcontext, MemoryContextAlloc(), ArrayBuildState::nelems, ArrayBuildState::private_cxt, ArrayBuildState::typalign, ArrayBuildState::typbyval, and ArrayBuildState::typlen.

Referenced by accumArrayResult(), array_agg_transfn(), array_positions(), initArrayResultAny(), plperl_array_to_datum(), and xpath().

4923 {
4924  ArrayBuildState *astate;
4925  MemoryContext arr_context = rcontext;
4926 
4927  /* Make a temporary context to hold all the junk */
4928  if (subcontext)
4929  arr_context = AllocSetContextCreate(rcontext,
4930  "accumArrayResult",
4934 
4935  astate = (ArrayBuildState *)
4936  MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
4937  astate->mcontext = arr_context;
4938  astate->private_cxt = subcontext;
4939  astate->alen = (subcontext ? 64 : 8); /* arbitrary starting array
4940  * size */
4941  astate->dvalues = (Datum *)
4942  MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
4943  astate->dnulls = (bool *)
4944  MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
4945  astate->nelems = 0;
4946  astate->element_type = element_type;
4947  get_typlenbyvalalign(element_type,
4948  &astate->typlen,
4949  &astate->typbyval,
4950  &astate->typalign);
4951 
4952  return astate;
4953 }
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1924
Datum * dvalues
Definition: array.h:171
bool typbyval
Definition: array.h:177
Oid element_type
Definition: array.h:175
bool private_cxt
Definition: array.h:179
#define ALLOCSET_DEFAULT_MINSIZE
Definition: memutils.h:142
bool * dnulls
Definition: array.h:172
char typalign
Definition: array.h:178
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:436
uintptr_t Datum
Definition: postgres.h:374
MemoryContext mcontext
Definition: array.h:170
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:750
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:143
int16 typlen
Definition: array.h:176
#define ALLOCSET_DEFAULT_MAXSIZE
Definition: memutils.h:144
ArrayBuildStateAny* initArrayResultAny ( Oid  input_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 5393 of file arrayfuncs.c.

References ArrayBuildStateAny::arraystate, Assert, get_array_type(), get_element_type(), initArrayResult(), initArrayResultArr(), InvalidOid, ArrayBuildState::mcontext, ArrayBuildStateArr::mcontext, MemoryContextAlloc(), NULL, OidIsValid, and ArrayBuildStateAny::scalarstate.

Referenced by accumArrayResultAny(), ExecScanSubPlan(), and ExecSetParamPlan().

5394 {
5395  ArrayBuildStateAny *astate;
5396  Oid element_type = get_element_type(input_type);
5397 
5398  if (OidIsValid(element_type))
5399  {
5400  /* Array case */
5401  ArrayBuildStateArr *arraystate;
5402 
5403  arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5404  astate = (ArrayBuildStateAny *)
5405  MemoryContextAlloc(arraystate->mcontext,
5406  sizeof(ArrayBuildStateAny));
5407  astate->scalarstate = NULL;
5408  astate->arraystate = arraystate;
5409  }
5410  else
5411  {
5412  /* Scalar case */
5413  ArrayBuildState *scalarstate;
5414 
5415  /* Let's just check that we have a type that can be put into arrays */
5416  Assert(OidIsValid(get_array_type(input_type)));
5417 
5418  scalarstate = initArrayResult(input_type, rcontext, subcontext);
5419  astate = (ArrayBuildStateAny *)
5420  MemoryContextAlloc(scalarstate->mcontext,
5421  sizeof(ArrayBuildStateAny));
5422  astate->scalarstate = scalarstate;
5423  astate->arraystate = NULL;
5424  }
5425 
5426  return astate;
5427 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:4922
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2387
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2415
unsigned int Oid
Definition: postgres_ext.h:31
ArrayBuildState * scalarstate
Definition: array.h:210
#define OidIsValid(objectId)
Definition: c.h:519
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5112
ArrayBuildStateArr * arraystate
Definition: array.h:211
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:215
#define Assert(condition)
Definition: c.h:656
MemoryContext mcontext
Definition: array.h:170
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:750
MemoryContext mcontext
Definition: array.h:188
ArrayBuildStateArr* initArrayResultArr ( Oid  array_type,
Oid  element_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 5112 of file arrayfuncs.c.

References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), ArrayBuildStateArr::array_type, ArrayBuildStateArr::element_type, ereport, errcode(), errmsg(), ERROR, format_type_be(), get_element_type(), ArrayBuildStateArr::mcontext, MemoryContextAllocZero(), OidIsValid, and ArrayBuildStateArr::private_cxt.

Referenced by accumArrayResultArr(), array_agg_array_transfn(), and initArrayResultAny().

5114 {
5115  ArrayBuildStateArr *astate;
5116  MemoryContext arr_context = rcontext; /* by default use the parent
5117  * ctx */
5118 
5119  /* Lookup element type, unless element_type already provided */
5120  if (!OidIsValid(element_type))
5121  {
5122  element_type = get_element_type(array_type);
5123 
5124  if (!OidIsValid(element_type))
5125  ereport(ERROR,
5126  (errcode(ERRCODE_DATATYPE_MISMATCH),
5127  errmsg("data type %s is not an array type",
5128  format_type_be(array_type))));
5129  }
5130 
5131  /* Make a temporary context to hold all the junk */
5132  if (subcontext)
5133  arr_context = AllocSetContextCreate(rcontext,
5134  "accumArrayResultArr",
5138 
5139  /* Note we initialize all fields to zero */
5140  astate = (ArrayBuildStateArr *)
5141  MemoryContextAllocZero(arr_context, sizeof(ArrayBuildStateArr));
5142  astate->mcontext = arr_context;
5143  astate->private_cxt = subcontext;
5144 
5145  /* Save relevant datatype information */
5146  astate->array_type = array_type;
5147  astate->element_type = element_type;
5148 
5149  return astate;
5150 }
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2387
int errcode(int sqlerrcode)
Definition: elog.c:569
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define OidIsValid(objectId)
Definition: c.h:519
#define ALLOCSET_DEFAULT_MINSIZE
Definition: memutils.h:142
#define ERROR
Definition: elog.h:41
#define ereport(elevel, rest)
Definition: elog.h:132
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:436
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:785
int errmsg(const char *fmt,...)
Definition: elog.c:791
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:143
bool private_cxt
Definition: array.h:200
#define ALLOCSET_DEFAULT_MAXSIZE
Definition: memutils.h:144
MemoryContext mcontext
Definition: array.h:188
Datum makeArrayResult ( ArrayBuildState astate,
MemoryContext  rcontext 
)

Definition at line 5028 of file arrayfuncs.c.

References makeMdArrayResult(), ArrayBuildState::nelems, and ArrayBuildState::private_cxt.

Referenced by array_positions(), dblink_get_connections(), get_altertable_subcmdtypes(), optionListToArray(), regexp_split_to_array(), text_to_array_internal(), transformRelOptions(), and xpath().

5030 {
5031  int ndims;
5032  int dims[1];
5033  int lbs[1];
5034 
5035  /* If no elements were presented, we want to create an empty array */
5036  ndims = (astate->nelems > 0) ? 1 : 0;
5037  dims[0] = astate->nelems;
5038  lbs[0] = 1;
5039 
5040  return makeMdArrayResult(astate, ndims, dims, lbs, rcontext,
5041  astate->private_cxt);
5042 }
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5060
bool private_cxt
Definition: array.h:179
Datum makeArrayResultAny ( ArrayBuildStateAny astate,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5466 of file arrayfuncs.c.

References ArrayBuildStateAny::arraystate, makeArrayResultArr(), makeMdArrayResult(), ArrayBuildState::nelems, and ArrayBuildStateAny::scalarstate.

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5468 {
5469  Datum result;
5470 
5471  if (astate->scalarstate)
5472  {
5473  /* Must use makeMdArrayResult to support "release" parameter */
5474  int ndims;
5475  int dims[1];
5476  int lbs[1];
5477 
5478  /* If no elements were presented, we want to create an empty array */
5479  ndims = (astate->scalarstate->nelems > 0) ? 1 : 0;
5480  dims[0] = astate->scalarstate->nelems;
5481  lbs[0] = 1;
5482 
5483  result = makeMdArrayResult(astate->scalarstate, ndims, dims, lbs,
5484  rcontext, release);
5485  }
5486  else
5487  {
5488  result = makeArrayResultArr(astate->arraystate,
5489  rcontext, release);
5490  }
5491  return result;
5492 }
Datum makeArrayResultArr(ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5318
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5060
ArrayBuildState * scalarstate
Definition: array.h:210
ArrayBuildStateArr * arraystate
Definition: array.h:211
uintptr_t Datum
Definition: postgres.h:374
Datum makeArrayResultArr ( ArrayBuildStateArr astate,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5318 of file arrayfuncs.c.

References ARR_DATA_PTR, ARR_DIMS, ARR_LBOUND, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_bitmap_copy(), Assert, construct_empty_array(), ArrayBuildStateArr::data, ArrayType::dataoffset, ArrayBuildStateArr::dims, ArrayBuildStateArr::element_type, ArrayType::elemtype, ArrayBuildStateArr::lbs, ArrayBuildStateArr::mcontext, MemoryContextDelete(), MemoryContextSwitchTo(), ArrayBuildStateArr::nbytes, ArrayType::ndim, ArrayBuildStateArr::ndims, ArrayBuildStateArr::nitems, NULL, ArrayBuildStateArr::nullbitmap, palloc0(), PointerGetDatum, ArrayBuildStateArr::private_cxt, and SET_VARSIZE.

Referenced by array_agg_array_finalfn(), and makeArrayResultAny().

5321 {
5322  ArrayType *result;
5323  MemoryContext oldcontext;
5324 
5325  /* Build the final array result in rcontext */
5326  oldcontext = MemoryContextSwitchTo(rcontext);
5327 
5328  if (astate->ndims == 0)
5329  {
5330  /* No inputs, return empty array */
5331  result = construct_empty_array(astate->element_type);
5332  }
5333  else
5334  {
5335  int dataoffset,
5336  nbytes;
5337 
5338  /* Compute required space */
5339  nbytes = astate->nbytes;
5340  if (astate->nullbitmap != NULL)
5341  {
5342  dataoffset = ARR_OVERHEAD_WITHNULLS(astate->ndims, astate->nitems);
5343  nbytes += dataoffset;
5344  }
5345  else
5346  {
5347  dataoffset = 0;
5348  nbytes += ARR_OVERHEAD_NONULLS(astate->ndims);
5349  }
5350 
5351  result = (ArrayType *) palloc0(nbytes);
5352  SET_VARSIZE(result, nbytes);
5353  result->ndim = astate->ndims;
5354  result->dataoffset = dataoffset;
5355  result->elemtype = astate->element_type;
5356 
5357  memcpy(ARR_DIMS(result), astate->dims, astate->ndims * sizeof(int));
5358  memcpy(ARR_LBOUND(result), astate->lbs, astate->ndims * sizeof(int));
5359  memcpy(ARR_DATA_PTR(result), astate->data, astate->nbytes);
5360 
5361  if (astate->nullbitmap != NULL)
5362  array_bitmap_copy(ARR_NULLBITMAP(result), 0,
5363  astate->nullbitmap, 0,
5364  astate->nitems);
5365  }
5366 
5367  MemoryContextSwitchTo(oldcontext);
5368 
5369  /* Clean up all the junk */
5370  if (release)
5371  {
5372  Assert(astate->private_cxt);
5373  MemoryContextDelete(astate->mcontext);
5374  }
5375 
5376  return PointerGetDatum(result);
5377 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:203
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#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:4595
int32 dataoffset
Definition: array.h:80
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3395
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
#define ARR_LBOUND(a)
Definition: array.h:277
bits8 * nullbitmap
Definition: array.h:190
Oid elemtype
Definition: array.h:81
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
void * palloc0(Size size)
Definition: mcxt.c:921
int lbs[MAXDIM]
Definition: array.h:197
#define NULL
Definition: c.h:215
#define Assert(condition)
Definition: c.h:656
int dims[MAXDIM]
Definition: array.h:196
bool private_cxt
Definition: array.h:200
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
#define ARR_NULLBITMAP(a)
Definition: array.h:281
MemoryContext mcontext
Definition: array.h:188
int ndim
Definition: array.h:79
Datum makeMdArrayResult ( ArrayBuildState astate,
int  ndims,
int *  dims,
int *  lbs,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5060 of file arrayfuncs.c.

References Assert, construct_md_array(), ArrayBuildState::dnulls, ArrayBuildState::dvalues, ArrayBuildState::element_type, ArrayBuildState::mcontext, MemoryContextDelete(), MemoryContextSwitchTo(), PointerGetDatum, ArrayBuildState::private_cxt, ArrayBuildState::typalign, ArrayBuildState::typbyval, and ArrayBuildState::typlen.

Referenced by array_agg_finalfn(), makeArrayResult(), makeArrayResultAny(), and plperl_array_to_datum().

5066 {
5067  ArrayType *result;
5068  MemoryContext oldcontext;
5069 
5070  /* Build the final array result in rcontext */
5071  oldcontext = MemoryContextSwitchTo(rcontext);
5072 
5073  result = construct_md_array(astate->dvalues,
5074  astate->dnulls,
5075  ndims,
5076  dims,
5077  lbs,
5078  astate->element_type,
5079  astate->typlen,
5080  astate->typbyval,
5081  astate->typalign);
5082 
5083  MemoryContextSwitchTo(oldcontext);
5084 
5085  /* Clean up all the junk */
5086  if (release)
5087  {
5088  Assert(astate->private_cxt);
5089  MemoryContextDelete(astate->mcontext);
5090  }
5091 
5092  return PointerGetDatum(result);
5093 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:203
#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 private_cxt
Definition: array.h:179
bool * dnulls
Definition: array.h:172
char typalign
Definition: array.h:178
#define Assert(condition)
Definition: c.h:656
MemoryContext mcontext
Definition: array.h:170
int16 typlen
Definition: array.h:176
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:3311
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

Definition at line 1429 of file arrayfuncs.c.

References AllocSizeIsValid, att_addlength_datum, att_align_nominal, StringInfoData::cursor, StringInfoData::data, ereport, errcode(), errmsg(), ERROR, i, StringInfoData::len, MaxAllocSize, StringInfoData::maxlen, NULL, PG_DETOAST_DATUM, PointerGetDatum, pq_getmsgint(), and ReceiveFunctionCall().

Referenced by array_recv().

1441 {
1442  int i;
1443  bool hasnull;
1444  int32 totbytes;
1445 
1446  for (i = 0; i < nitems; i++)
1447  {
1448  int itemlen;
1449  StringInfoData elem_buf;
1450  char csave;
1451 
1452  /* Get and check the item length */
1453  itemlen = pq_getmsgint(buf, 4);
1454  if (itemlen < -1 || itemlen > (buf->len - buf->cursor))
1455  ereport(ERROR,
1456  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1457  errmsg("insufficient data left in message")));
1458 
1459  if (itemlen == -1)
1460  {
1461  /* -1 length means NULL */
1462  values[i] = ReceiveFunctionCall(receiveproc, NULL,
1463  typioparam, typmod);
1464  nulls[i] = true;
1465  continue;
1466  }
1467 
1468  /*
1469  * Rather than copying data around, we just set up a phony StringInfo
1470  * pointing to the correct portion of the input buffer. We assume we
1471  * can scribble on the input buffer so as to maintain the convention
1472  * that StringInfos have a trailing null.
1473  */
1474  elem_buf.data = &buf->data[buf->cursor];
1475  elem_buf.maxlen = itemlen + 1;
1476  elem_buf.len = itemlen;
1477  elem_buf.cursor = 0;
1478 
1479  buf->cursor += itemlen;
1480 
1481  csave = buf->data[buf->cursor];
1482  buf->data[buf->cursor] = '\0';
1483 
1484  /* Now call the element's receiveproc */
1485  values[i] = ReceiveFunctionCall(receiveproc, &elem_buf,
1486  typioparam, typmod);
1487  nulls[i] = false;
1488 
1489  /* Trouble if it didn't eat the whole buffer */
1490  if (elem_buf.cursor != itemlen)
1491  ereport(ERROR,
1492  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1493  errmsg("improper binary format in array element %d",
1494  i + 1)));
1495 
1496  buf->data[buf->cursor] = csave;
1497  }
1498 
1499  /*
1500  * Check for nulls, compute total data space needed
1501  */
1502  hasnull = false;
1503  totbytes = 0;
1504  for (i = 0; i < nitems; i++)
1505  {
1506  if (nulls[i])
1507  hasnull = true;
1508  else
1509  {
1510  /* let's just make sure data is not toasted */
1511  if (typlen == -1)
1513  totbytes = att_addlength_datum(totbytes, typlen, values[i]);
1514  totbytes = att_align_nominal(totbytes, typalign);
1515  /* check for overflow of total request */
1516  if (!AllocSizeIsValid(totbytes))
1517  ereport(ERROR,
1518  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1519  errmsg("array size exceeds the maximum allowed (%d)",
1520  (int) MaxAllocSize)));
1521  }
1522  }
1523  *hasnulls = hasnull;
1524  *nbytes = totbytes;
1525 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define PointerGetDatum(X)
Definition: postgres.h:564
int errcode(int sqlerrcode)
Definition: elog.c:569
signed int int32
Definition: c.h:242
#define ERROR
Definition: elog.h:41
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
Definition: fmgr.c:1967
#define ereport(elevel, rest)
Definition: elog.h:132
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
#define NULL
Definition: c.h:215
static Datum values[MAXATTR]
Definition: bootstrap.c:159
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
int errmsg(const char *fmt,...)
Definition: elog.c:791
int i
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:196
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:447
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

Definition at line 716 of file arrayfuncs.c.

References AllocSizeIsValid, array_isspace(), Array_nulls, ArrayGetOffset0(), Assert, att_addlength_datum, att_align_nominal, ereport, errcode(), errmsg(), ERROR, i, InputFunctionCall(), MaxAllocSize, MAXDIM, mda_get_prod(), MemSet, NULL, PG_DETOAST_DATUM, pg_strcasecmp(), and PointerGetDatum.

Referenced by array_in().

732 {
733  int i,
734  nest_level = 0;
735  char *srcptr;
736  bool in_quotes = false;
737  bool eoArray = false;
738  bool hasnull;
739  int32 totbytes;
740  int indx[MAXDIM],
741  prod[MAXDIM];
742 
743  mda_get_prod(ndim, dim, prod);
744  MemSet(indx, 0, sizeof(indx));
745 
746  /* Initialize is-null markers to true */
747  memset(nulls, true, nitems * sizeof(bool));
748 
749  /*
750  * We have to remove " and \ characters to create a clean item value to
751  * pass to the datatype input routine. We overwrite each item value
752  * in-place within arrayStr to do this. srcptr is the current scan point,
753  * and dstptr is where we are copying to.
754  *
755  * We also want to suppress leading and trailing unquoted whitespace. We
756  * use the leadingspace flag to suppress leading space. Trailing space is
757  * tracked by using dstendptr to point to the last significant output
758  * character.
759  *
760  * The error checking in this routine is mostly pro-forma, since we expect
761  * that ArrayCount() already validated the string. So we don't bother
762  * with errdetail messages.
763  */
764  srcptr = arrayStr;
765  while (!eoArray)
766  {
767  bool itemdone = false;
768  bool leadingspace = true;
769  bool hasquoting = false;
770  char *itemstart;
771  char *dstptr;
772  char *dstendptr;
773 
774  i = -1;
775  itemstart = dstptr = dstendptr = srcptr;
776 
777  while (!itemdone)
778  {
779  switch (*srcptr)
780  {
781  case '\0':
782  /* Signal a premature end of the string */
783  ereport(ERROR,
784  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
785  errmsg("malformed array literal: \"%s\"",
786  origStr)));
787  break;
788  case '\\':
789  /* Skip backslash, copy next character as-is. */
790  srcptr++;
791  if (*srcptr == '\0')
792  ereport(ERROR,
793  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
794  errmsg("malformed array literal: \"%s\"",
795  origStr)));
796  *dstptr++ = *srcptr++;
797  /* Treat the escaped character as non-whitespace */
798  leadingspace = false;
799  dstendptr = dstptr;
800  hasquoting = true; /* can't be a NULL marker */
801  break;
802  case '\"':
803  in_quotes = !in_quotes;
804  if (in_quotes)
805  leadingspace = false;
806  else
807  {
808  /*
809  * Advance dstendptr when we exit in_quotes; this
810  * saves having to do it in all the other in_quotes
811  * cases.
812  */
813  dstendptr = dstptr;
814  }
815  hasquoting = true; /* can't be a NULL marker */
816  srcptr++;
817  break;
818  case '{':
819  if (!in_quotes)
820  {
821  if (nest_level >= ndim)
822  ereport(ERROR,
823  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
824  errmsg("malformed array literal: \"%s\"",
825  origStr)));
826  nest_level++;
827  indx[nest_level - 1] = 0;
828  srcptr++;
829  }
830  else
831  *dstptr++ = *srcptr++;
832  break;
833  case '}':
834  if (!in_quotes)
835  {
836  if (nest_level == 0)
837  ereport(ERROR,
838  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
839  errmsg("malformed array literal: \"%s\"",
840  origStr)));
841  if (i == -1)
842  i = ArrayGetOffset0(ndim, indx, prod);
843  indx[nest_level - 1] = 0;
844  nest_level--;
845  if (nest_level == 0)
846  eoArray = itemdone = true;
847  else
848  indx[nest_level - 1]++;
849  srcptr++;
850  }
851  else
852  *dstptr++ = *srcptr++;
853  break;
854  default:
855  if (in_quotes)
856  *dstptr++ = *srcptr++;
857  else if (*srcptr == typdelim)
858  {
859  if (i == -1)
860  i = ArrayGetOffset0(ndim, indx, prod);
861  itemdone = true;
862  indx[ndim - 1]++;
863  srcptr++;
864  }
865  else if (array_isspace(*srcptr))
866  {
867  /*
868  * If leading space, drop it immediately. Else, copy
869  * but don't advance dstendptr.
870  */
871  if (leadingspace)
872  srcptr++;
873  else
874  *dstptr++ = *srcptr++;
875  }
876  else
877  {
878  *dstptr++ = *srcptr++;
879  leadingspace = false;
880  dstendptr = dstptr;
881  }
882  break;
883  }
884  }
885 
886  Assert(dstptr < srcptr);
887  *dstendptr = '\0';
888 
889  if (i < 0 || i >= nitems)
890  ereport(ERROR,
891  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
892  errmsg("malformed array literal: \"%s\"",
893  origStr)));
894 
895  if (Array_nulls && !hasquoting &&
896  pg_strcasecmp(itemstart, "NULL") == 0)
897  {
898  /* it's a NULL item */
899  values[i] = InputFunctionCall(inputproc, NULL,
900  typioparam, typmod);
901  nulls[i] = true;
902  }
903  else
904  {
905  values[i] = InputFunctionCall(inputproc, itemstart,
906  typioparam, typmod);
907  nulls[i] = false;
908  }
909  }
910 
911  /*
912  * Check for nulls, compute total data space needed
913  */
914  hasnull = false;
915  totbytes = 0;
916  for (i = 0; i < nitems; i++)
917  {
918  if (nulls[i])
919  hasnull = true;
920  else
921  {
922  /* let's just make sure data is not toasted */
923  if (typlen == -1)
925  totbytes = att_addlength_datum(totbytes, typlen, values[i]);
926  totbytes = att_align_nominal(totbytes, typalign);
927  /* check for overflow of total request */
928  if (!AllocSizeIsValid(totbytes))
929  ereport(ERROR,
930  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
931  errmsg("array size exceeds the maximum allowed (%d)",
932  (int) MaxAllocSize)));
933  }
934  }
935  *hasnulls = hasnull;
936  *nbytes = totbytes;
937 }
static bool array_isspace(char ch)
Definition: arrayfuncs.c:431
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define MAXDIM
Definition: c.h:404
#define PointerGetDatum(X)
Definition: postgres.h:564
void mda_get_prod(int n, const int *range, int *prod)
Definition: arrayutils.c:134
bool Array_nulls
Definition: arrayfuncs.c:39
int errcode(int sqlerrcode)
Definition: elog.c:569
#define MemSet(start, val, len)
Definition: c.h:838
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
signed int int32
Definition: c.h:242
#define ERROR
Definition: elog.h:41
#define ereport(elevel, rest)
Definition: elog.h:132
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1893
#define NULL
Definition: c.h:215
#define Assert(condition)
Definition: c.h:656
static Datum values[MAXATTR]
Definition: bootstrap.c:159
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
int errmsg(const char *fmt,...)
Definition: elog.c:791
int i
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:196
int ArrayGetOffset0(int n, const int *tup, const int *scale)
Definition: arrayutils.c:50
Datum width_bucket_array ( PG_FUNCTION_ARGS  )

Definition at line 6276 of file arrayfuncs.c.

References ARR_ELEMTYPE, ARR_NDIM, array_contains_nulls(), TypeCacheEntry::cmp_proc_finfo, ereport, errcode(), errmsg(), ERROR, FLOAT8OID, FmgrInfo::fn_oid, format_type_be(), lookup_type_cache(), NULL, OidIsValid, PG_FREE_IF_COPY, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_INT32, TypeCacheEntry::type_id, TYPECACHE_CMP_PROC_FINFO, TypeCacheEntry::typlen, width_bucket_array_fixed(), width_bucket_array_float8(), and width_bucket_array_variable().

6277 {
6278  Datum operand = PG_GETARG_DATUM(0);
6279  ArrayType *thresholds = PG_GETARG_ARRAYTYPE_P(1);
6280  Oid collation = PG_GET_COLLATION();
6281  Oid element_type = ARR_ELEMTYPE(thresholds);
6282  int result;
6283 
6284  /* Check input */
6285  if (ARR_NDIM(thresholds) > 1)
6286  ereport(ERROR,
6287  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
6288  errmsg("thresholds must be one-dimensional array")));
6289 
6290  if (array_contains_nulls(thresholds))
6291  ereport(ERROR,
6292  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
6293  errmsg("thresholds array must not contain NULLs")));
6294 
6295  /* We have a dedicated implementation for float8 data */
6296  if (element_type == FLOAT8OID)
6297  result = width_bucket_array_float8(operand, thresholds);
6298  else
6299  {
6300  TypeCacheEntry *typentry;
6301 
6302  /* Cache information about the input type */
6303  typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
6304  if (typentry == NULL ||
6305  typentry->type_id != element_type)
6306  {
6307  typentry = lookup_type_cache(element_type,
6309  if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
6310  ereport(ERROR,
6311  (errcode(ERRCODE_UNDEFINED_FUNCTION),
6312  errmsg("could not identify a comparison function for type %s",
6313  format_type_be(element_type))));
6314  fcinfo->flinfo->fn_extra = (void *) typentry;
6315  }
6316 
6317  /*
6318  * We have separate implementation paths for fixed- and variable-width
6319  * types, since indexing the array is a lot cheaper in the first case.
6320  */
6321  if (typentry->typlen > 0)
6322  result = width_bucket_array_fixed(operand, thresholds,
6323  collation, typentry);
6324  else
6325  result = width_bucket_array_variable(operand, thresholds,
6326  collation, typentry);
6327  }
6328 
6329  /* Avoid leaking memory when handed toasted input. */
6330  PG_FREE_IF_COPY(thresholds, 1);
6331 
6332  PG_RETURN_INT32(result);
6333 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
int errcode(int sqlerrcode)
Definition: elog.c:569
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
#define OidIsValid(objectId)
Definition: c.h:519
#define PG_GET_COLLATION()
Definition: fmgr.h:155
FmgrInfo cmp_proc_finfo
Definition: typcache.h:68
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:41
static int width_bucket_array_variable(Datum operand, ArrayType *thresholds, Oid collation, TypeCacheEntry *typentry)
Definition: arrayfuncs.c:6436
static int width_bucket_array_fixed(Datum operand, ArrayType *thresholds, Oid collation, TypeCacheEntry *typentry)
Definition: arrayfuncs.c:6383
#define ereport(elevel, rest)
Definition: elog.h:132
uintptr_t Datum
Definition: postgres.h:374
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:182
Oid fn_oid
Definition: fmgr.h:56
#define NULL
Definition: c.h:215
#define FLOAT8OID
Definition: pg_type.h:411
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:216
#define ARR_NDIM(a)
Definition: array.h:271
int errmsg(const char *fmt,...)
Definition: elog.c:791
static int width_bucket_array_float8(Datum operand, ArrayType *thresholds)
Definition: arrayfuncs.c:6339
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:116
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3513
#define ARR_ELEMTYPE(a)
Definition: array.h:273
static int width_bucket_array_fixed ( Datum  operand,
ArrayType thresholds,
Oid  collation,
TypeCacheEntry typentry 
)
static

Definition at line 6383 of file arrayfuncs.c.

References FunctionCallInfoData::arg, FunctionCallInfoData::argnull, ARR_DATA_PTR, ARR_DIMS, ARR_NDIM, ArrayGetNItems(), TypeCacheEntry::cmp_proc_finfo, DatumGetInt32, fetch_att, FunctionCallInvoke, InitFunctionCallInfoData, FunctionCallInfoData::isnull, NULL, TypeCacheEntry::typbyval, and TypeCacheEntry::typlen.

Referenced by width_bucket_array().

6387 {
6388  char *thresholds_data;
6389  int typlen = typentry->typlen;
6390  bool typbyval = typentry->typbyval;
6391  FunctionCallInfoData locfcinfo;
6392  int left;
6393  int right;
6394 
6395  /*
6396  * Since we know the array contains no NULLs, we can just index it
6397  * directly.
6398  */
6399  thresholds_data = (char *) ARR_DATA_PTR(thresholds);
6400 
6401  InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
6402  collation, NULL, NULL);
6403 
6404  /* Find the bucket */
6405  left = 0;
6406  right = ArrayGetNItems(ARR_NDIM(thresholds), ARR_DIMS(thresholds));
6407  while (left < right)
6408  {
6409  int mid = (left + right) / 2;
6410  char *ptr;
6411  int32 cmpresult;
6412 
6413  ptr = thresholds_data + mid * typlen;
6414 
6415  locfcinfo.arg[0] = operand;
6416  locfcinfo.arg[1] = fetch_att(ptr, typbyval, typlen);
6417  locfcinfo.argnull[0] = false;
6418  locfcinfo.argnull[1] = false;
6419  locfcinfo.isnull = false;
6420 
6421  cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
6422 
6423  if (cmpresult < 0)
6424  right = mid;
6425  else
6426  left = mid + 1;
6427  }
6428 
6429  return left;
6430 }
#define DatumGetInt32(X)
Definition: postgres.h:480
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int16 typlen
Definition: typcache.h:35
bool typbyval
Definition: typcache.h:36
signed int int32
Definition: c.h:242
FmgrInfo cmp_proc_finfo
Definition: typcache.h:68
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:215
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:112
#define ARR_NDIM(a)
Definition: array.h:271
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
static int width_bucket_array_float8 ( Datum  operand,
ArrayType thresholds 
)
static

Definition at line 6339 of file arrayfuncs.c.

References ARR_DATA_PTR, ARR_DIMS, ARR_NDIM, ArrayGetNItems(), and DatumGetFloat8.

Referenced by width_bucket_array().

6340 {
6341  float8 op = DatumGetFloat8(operand);
6342  float8 *thresholds_data;
6343  int left;
6344  int right;
6345 
6346  /*
6347  * Since we know the array contains no NULLs, we can just index it
6348  * directly.
6349  */
6350  thresholds_data = (float8 *) ARR_DATA_PTR(thresholds);
6351 
6352  left = 0;
6353  right = ArrayGetNItems(ARR_NDIM(thresholds), ARR_DIMS(thresholds));
6354 
6355  /*
6356  * If the probe value is a NaN, it's greater than or equal to all possible
6357  * threshold values (including other NaNs), so we need not search. Note
6358  * that this would give the same result as searching even if the array
6359  * contains multiple NaNs (as long as they're correctly sorted), since the
6360  * loop logic will find the rightmost of multiple equal threshold values.
6361  */
6362  if (isnan(op))
6363  return right;
6364 
6365  /* Find the bucket */
6366  while (left < right)
6367  {
6368  int mid = (left + right) / 2;
6369 
6370  if (isnan(thresholds_data[mid]) || op < thresholds_data[mid])
6371  right = mid;
6372  else
6373  left = mid + 1;
6374  }
6375 
6376  return left;
6377 }
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
double float8
Definition: c.h:366
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define DatumGetFloat8(X)
Definition: postgres.h:665
#define ARR_NDIM(a)
Definition: array.h:271
static int width_bucket_array_variable ( Datum  operand,
ArrayType thresholds,
Oid  collation,
TypeCacheEntry typentry 
)
static

Definition at line 6436 of file arrayfuncs.c.

References FunctionCallInfoData::arg, FunctionCallInfoData::argnull, ARR_DATA_PTR, ARR_DIMS, ARR_NDIM, ArrayGetNItems(), att_addlength_pointer, att_align_nominal, TypeCacheEntry::cmp_proc_finfo, DatumGetInt32, fetch_att, FunctionCallInvoke, i, InitFunctionCallInfoData, FunctionCallInfoData::isnull, NULL, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, and TypeCacheEntry::typlen.

Referenced by width_bucket_array().

6440 {
6441  char *thresholds_data;
6442  int typlen = typentry->typlen;
6443  bool typbyval = typentry->typbyval;
6444  char typalign = typentry->typalign;
6445  FunctionCallInfoData locfcinfo;
6446  int left;
6447  int right;
6448 
6449  thresholds_data = (char *) ARR_DATA_PTR(thresholds);
6450 
6451  InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
6452  collation, NULL, NULL);
6453 
6454  /* Find the bucket */
6455  left = 0;
6456  right = ArrayGetNItems(ARR_NDIM(thresholds), ARR_DIMS(thresholds));
6457  while (left < right)
6458  {
6459  int mid = (left + right) / 2;
6460  char *ptr;
6461  int i;
6462  int32 cmpresult;
6463 
6464  /* Locate mid'th array element by advancing from left element */
6465  ptr = thresholds_data;
6466  for (i = left; i < mid; i++)
6467  {
6468  ptr = att_addlength_pointer(ptr, typlen, ptr);
6469  ptr = (char *) att_align_nominal(ptr, typalign);
6470  }
6471 
6472  locfcinfo.arg[0] = operand;
6473  locfcinfo.arg[1] = fetch_att(ptr, typbyval, typlen);
6474  locfcinfo.argnull[0] = false;
6475  locfcinfo.argnull[1] = false;
6476  locfcinfo.isnull = false;
6477 
6478  cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
6479 
6480  if (cmpresult < 0)
6481  right = mid;
6482  else
6483  {
6484  left = mid + 1;
6485 
6486  /*
6487  * Move the thresholds pointer to match new "left" index, so we
6488  * don't have to seek over those elements again. This trick
6489  * ensures we do only O(N) array indexing work, not O(N^2).
6490  */
6491  ptr = att_addlength_pointer(ptr, typlen, ptr);
6492  thresholds_data = (char *) att_align_nominal(ptr, typalign);
6493  }
6494  }
6495 
6496  return left;
6497 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define DatumGetInt32(X)
Definition: postgres.h:480
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int16 typlen
Definition: typcache.h:35
bool typbyval
Definition: typcache.h:36
signed int int32
Definition: c.h:242
FmgrInfo cmp_proc_finfo
Definition: typcache.h:68
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:215
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:112
#define ARR_NDIM(a)
Definition: array.h:271
char typalign
Definition: typcache.h:37
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
int i

Variable Documentation

bool Array_nulls = true

Definition at line 39 of file arrayfuncs.c.

Referenced by ReadArrayStr().