PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
array_userfuncs.c File Reference
#include "postgres.h"
#include "catalog/pg_type.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/typcache.h"
Include dependency graph for array_userfuncs.c:

Go to the source code of this file.

Functions

static Datum array_position_common (FunctionCallInfo fcinfo)
 
static ExpandedArrayHeaderfetch_array_arg_replace_nulls (FunctionCallInfo fcinfo, int argno)
 
Datum array_append (PG_FUNCTION_ARGS)
 
Datum array_prepend (PG_FUNCTION_ARGS)
 
Datum array_cat (PG_FUNCTION_ARGS)
 
ArrayTypecreate_singleton_array (FunctionCallInfo fcinfo, Oid element_type, Datum element, bool isNull, int ndims)
 
Datum array_agg_transfn (PG_FUNCTION_ARGS)
 
Datum array_agg_finalfn (PG_FUNCTION_ARGS)
 
Datum array_agg_array_transfn (PG_FUNCTION_ARGS)
 
Datum array_agg_array_finalfn (PG_FUNCTION_ARGS)
 
Datum array_position (PG_FUNCTION_ARGS)
 
Datum array_position_start (PG_FUNCTION_ARGS)
 
Datum array_positions (PG_FUNCTION_ARGS)
 

Function Documentation

Datum array_agg_array_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 656 of file array_userfuncs.c.

References AggCheckCallContext(), Assert, CurrentMemoryContext, makeArrayResultArr(), NULL, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_DATUM, and PG_RETURN_NULL.

657 {
658  Datum result;
660 
661  /* cannot be called directly because of internal-type argument */
662  Assert(AggCheckCallContext(fcinfo, NULL));
663 
665 
666  if (state == NULL)
667  PG_RETURN_NULL(); /* returns null iff no input values */
668 
669  /*
670  * Make the result. We cannot release the ArrayBuildStateArr because
671  * sometimes aggregate final functions are re-executed. Rather, it is
672  * nodeAgg.c's responsibility to reset the aggcontext when it's safe to do
673  * so.
674  */
675  result = makeArrayResultArr(state, CurrentMemoryContext, false);
676 
677  PG_RETURN_DATUM(result);
678 }
Datum makeArrayResultArr(ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5343
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
Definition: regguts.h:298
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum array_agg_array_transfn ( PG_FUNCTION_ARGS  )

Definition at line 612 of file array_userfuncs.c.

References accumArrayResultArr(), AggCheckCallContext(), elog, ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), initArrayResultArr(), InvalidOid, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, and PG_RETURN_POINTER.

613 {
614  Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1);
615  MemoryContext aggcontext;
617 
618  if (arg1_typeid == InvalidOid)
619  ereport(ERROR,
620  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
621  errmsg("could not determine input data type")));
622 
623  /*
624  * Note: we do not need a run-time check about whether arg1_typeid is a
625  * valid array type, because the parser would have verified that while
626  * resolving the input/result types of this polymorphic aggregate.
627  */
628 
629  if (!AggCheckCallContext(fcinfo, &aggcontext))
630  {
631  /* cannot be called directly because of internal-type argument */
632  elog(ERROR, "array_agg_array_transfn called in non-aggregate context");
633  }
634 
635 
636  if (PG_ARGISNULL(0))
637  state = initArrayResultArr(arg1_typeid, InvalidOid, aggcontext, false);
638  else
639  state = (ArrayBuildStateArr *) PG_GETARG_POINTER(0);
640 
641  state = accumArrayResultArr(state,
642  PG_GETARG_DATUM(1),
643  PG_ARGISNULL(1),
644  arg1_typeid,
645  aggcontext);
646 
647  /*
648  * The transition type for array_agg() is declared to be "internal", which
649  * is a pass-by-value type the same size as a pointer. So we can safely
650  * pass the ArrayBuildStateArr pointer through nodeAgg.c's machinations.
651  */
652  PG_RETURN_POINTER(state);
653 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
unsigned int Oid
Definition: postgres_ext.h:31
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5139
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2220
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5186
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
Definition: regguts.h:298
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
Datum array_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 577 of file array_userfuncs.c.

References AggCheckCallContext(), Assert, CurrentMemoryContext, makeMdArrayResult(), ArrayBuildState::nelems, NULL, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_DATUM, and PG_RETURN_NULL.

578 {
579  Datum result;
581  int dims[1];
582  int lbs[1];
583 
584  /* cannot be called directly because of internal-type argument */
585  Assert(AggCheckCallContext(fcinfo, NULL));
586 
587  state = PG_ARGISNULL(0) ? NULL : (ArrayBuildState *) PG_GETARG_POINTER(0);
588 
589  if (state == NULL)
590  PG_RETURN_NULL(); /* returns null iff no input values */
591 
592  dims[0] = state->nelems;
593  lbs[0] = 1;
594 
595  /*
596  * Make the result. We cannot release the ArrayBuildState because
597  * sometimes aggregate final functions are re-executed. Rather, it is
598  * nodeAgg.c's responsibility to reset the aggcontext when it's safe to do
599  * so.
600  */
601  result = makeMdArrayResult(state, 1, dims, lbs,
603  false);
604 
605  PG_RETURN_DATUM(result);
606 }
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5087
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
Definition: regguts.h:298
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum array_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 531 of file array_userfuncs.c.

References accumArrayResult(), AggCheckCallContext(), elog, ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), initArrayResult(), InvalidOid, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, and PG_RETURN_POINTER.

532 {
533  Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1);
534  MemoryContext aggcontext;
536  Datum elem;
537 
538  if (arg1_typeid == InvalidOid)
539  ereport(ERROR,
540  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
541  errmsg("could not determine input data type")));
542 
543  /*
544  * Note: we do not need a run-time check about whether arg1_typeid is a
545  * valid array element type, because the parser would have verified that
546  * while resolving the input/result types of this polymorphic aggregate.
547  */
548 
549  if (!AggCheckCallContext(fcinfo, &aggcontext))
550  {
551  /* cannot be called directly because of internal-type argument */
552  elog(ERROR, "array_agg_transfn called in non-aggregate context");
553  }
554 
555  if (PG_ARGISNULL(0))
556  state = initArrayResult(arg1_typeid, aggcontext, false);
557  else
558  state = (ArrayBuildState *) PG_GETARG_POINTER(0);
559 
560  elem = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
561 
562  state = accumArrayResult(state,
563  elem,
564  PG_ARGISNULL(1),
565  arg1_typeid,
566  aggcontext);
567 
568  /*
569  * The transition type for array_agg() is declared to be "internal", which
570  * is a pass-by-value type the same size as a pointer. So we can safely
571  * pass the ArrayBuildState pointer through nodeAgg.c's machinations.
572  */
573  PG_RETURN_POINTER(state);
574 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:4951
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2220
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
Definition: regguts.h:298
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:4991
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
Datum array_append ( PG_FUNCTION_ARGS  )

Definition at line 100 of file array_userfuncs.c.

References array_set_element(), ExpandedArrayHeader::dims, EOHPGetRWDatum, ereport, errcode(), errmsg(), ERROR, fetch_array_arg_replace_nulls(), ExpandedArrayHeader::hdr, ExpandedArrayHeader::lbound, ExpandedArrayHeader::ndims, PG_ARGISNULL, PG_GETARG_DATUM, PG_RETURN_DATUM, ArrayMetaState::typalign, ArrayMetaState::typbyval, and ArrayMetaState::typlen.

101 {
102  ExpandedArrayHeader *eah;
103  Datum newelem;
104  bool isNull;
105  Datum result;
106  int *dimv,
107  *lb;
108  int indx;
109  ArrayMetaState *my_extra;
110 
111  eah = fetch_array_arg_replace_nulls(fcinfo, 0);
112  isNull = PG_ARGISNULL(1);
113  if (isNull)
114  newelem = (Datum) 0;
115  else
116  newelem = PG_GETARG_DATUM(1);
117 
118  if (eah->ndims == 1)
119  {
120  /* append newelem */
121  int ub;
122 
123  lb = eah->lbound;
124  dimv = eah->dims;
125  ub = dimv[0] + lb[0] - 1;
126  indx = ub + 1;
127 
128  /* overflow? */
129  if (indx < ub)
130  ereport(ERROR,
131  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
132  errmsg("integer out of range")));
133  }
134  else if (eah->ndims == 0)
135  indx = 1;
136  else
137  ereport(ERROR,
138  (errcode(ERRCODE_DATA_EXCEPTION),
139  errmsg("argument must be empty or one-dimensional array")));
140 
141  /* Perform element insertion */
142  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
143 
144  result = array_set_element(EOHPGetRWDatum(&eah->hdr),
145  1, &indx, newelem, isNull,
146  -1, my_extra->typlen, my_extra->typbyval, my_extra->typalign);
147 
148  PG_RETURN_DATUM(result);
149 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum array_set_element(Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:2186
bool typbyval
Definition: array.h:221
static ExpandedArrayHeader * fetch_array_arg_replace_nulls(FunctionCallInfo fcinfo, int argno)
#define ERROR
Definition: elog.h:43
ExpandedObjectHeader hdr
Definition: array.h:102
int16 typlen
Definition: array.h:220
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
char typalign
Definition: array.h:222
#define EOHPGetRWDatum(eohptr)
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum array_cat ( PG_FUNCTION_ARGS  )

Definition at line 223 of file array_userfuncs.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(), ArrayGetNItems(), ArrayType::dataoffset, ArrayType::elemtype, ereport, errcode(), errdetail(), errmsg(), ERROR, format_type_be(), i, ArrayType::ndim, palloc(), palloc0(), PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_RETURN_ARRAYTYPE_P, PG_RETURN_NULL, and SET_VARSIZE.

224 {
225  ArrayType *v1,
226  *v2;
227  ArrayType *result;
228  int *dims,
229  *lbs,
230  ndims,
231  nitems,
232  ndatabytes,
233  nbytes;
234  int *dims1,
235  *lbs1,
236  ndims1,
237  nitems1,
238  ndatabytes1;
239  int *dims2,
240  *lbs2,
241  ndims2,
242  nitems2,
243  ndatabytes2;
244  int i;
245  char *dat1,
246  *dat2;
247  bits8 *bitmap1,
248  *bitmap2;
249  Oid element_type;
250  Oid element_type1;
251  Oid element_type2;
252  int32 dataoffset;
253 
254  /* Concatenating a null array is a no-op, just return the other input */
255  if (PG_ARGISNULL(0))
256  {
257  if (PG_ARGISNULL(1))
258  PG_RETURN_NULL();
259  result = PG_GETARG_ARRAYTYPE_P(1);
260  PG_RETURN_ARRAYTYPE_P(result);
261  }
262  if (PG_ARGISNULL(1))
263  {
264  result = PG_GETARG_ARRAYTYPE_P(0);
265  PG_RETURN_ARRAYTYPE_P(result);
266  }
267 
268  v1 = PG_GETARG_ARRAYTYPE_P(0);
269  v2 = PG_GETARG_ARRAYTYPE_P(1);
270 
271  element_type1 = ARR_ELEMTYPE(v1);
272  element_type2 = ARR_ELEMTYPE(v2);
273 
274  /* Check we have matching element types */
275  if (element_type1 != element_type2)
276  ereport(ERROR,
277  (errcode(ERRCODE_DATATYPE_MISMATCH),
278  errmsg("cannot concatenate incompatible arrays"),
279  errdetail("Arrays with element types %s and %s are not "
280  "compatible for concatenation.",
281  format_type_be(element_type1),
282  format_type_be(element_type2))));
283 
284  /* OK, use it */
285  element_type = element_type1;
286 
287  /*----------
288  * We must have one of the following combinations of inputs:
289  * 1) one empty array, and one non-empty array
290  * 2) both arrays empty
291  * 3) two arrays with ndims1 == ndims2
292  * 4) ndims1 == ndims2 - 1
293  * 5) ndims1 == ndims2 + 1
294  *----------
295  */
296  ndims1 = ARR_NDIM(v1);
297  ndims2 = ARR_NDIM(v2);
298 
299  /*
300  * short circuit - if one input array is empty, and the other is not, we
301  * return the non-empty one as the result
302  *
303  * if both are empty, return the first one
304  */
305  if (ndims1 == 0 && ndims2 > 0)
307 
308  if (ndims2 == 0)
310 
311  /* the rest fall under rule 3, 4, or 5 */
312  if (ndims1 != ndims2 &&
313  ndims1 != ndims2 - 1 &&
314  ndims1 != ndims2 + 1)
315  ereport(ERROR,
316  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
317  errmsg("cannot concatenate incompatible arrays"),
318  errdetail("Arrays of %d and %d dimensions are not "
319  "compatible for concatenation.",
320  ndims1, ndims2)));
321 
322  /* get argument array details */
323  lbs1 = ARR_LBOUND(v1);
324  lbs2 = ARR_LBOUND(v2);
325  dims1 = ARR_DIMS(v1);
326  dims2 = ARR_DIMS(v2);
327  dat1 = ARR_DATA_PTR(v1);
328  dat2 = ARR_DATA_PTR(v2);
329  bitmap1 = ARR_NULLBITMAP(v1);
330  bitmap2 = ARR_NULLBITMAP(v2);
331  nitems1 = ArrayGetNItems(ndims1, dims1);
332  nitems2 = ArrayGetNItems(ndims2, dims2);
333  ndatabytes1 = ARR_SIZE(v1) - ARR_DATA_OFFSET(v1);
334  ndatabytes2 = ARR_SIZE(v2) - ARR_DATA_OFFSET(v2);
335 
336  if (ndims1 == ndims2)
337  {
338  /*
339  * resulting array is made up of the elements (possibly arrays
340  * themselves) of the input argument arrays
341  */
342  ndims = ndims1;
343  dims = (int *) palloc(ndims * sizeof(int));
344  lbs = (int *) palloc(ndims * sizeof(int));
345 
346  dims[0] = dims1[0] + dims2[0];
347  lbs[0] = lbs1[0];
348 
349  for (i = 1; i < ndims; i++)
350  {
351  if (dims1[i] != dims2[i] || lbs1[i] != lbs2[i])
352  ereport(ERROR,
353  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
354  errmsg("cannot concatenate incompatible arrays"),
355  errdetail("Arrays with differing element dimensions are "
356  "not compatible for concatenation.")));
357 
358  dims[i] = dims1[i];
359  lbs[i] = lbs1[i];
360  }
361  }
362  else if (ndims1 == ndims2 - 1)
363  {
364  /*
365  * resulting array has the second argument as the outer array, with
366  * the first argument inserted at the front of the outer dimension
367  */
368  ndims = ndims2;
369  dims = (int *) palloc(ndims * sizeof(int));
370  lbs = (int *) palloc(ndims * sizeof(int));
371  memcpy(dims, dims2, ndims * sizeof(int));
372  memcpy(lbs, lbs2, ndims * sizeof(int));
373 
374  /* increment number of elements in outer array */
375  dims[0] += 1;
376 
377  /* make sure the added element matches our existing elements */
378  for (i = 0; i < ndims1; i++)
379  {
380  if (dims1[i] != dims[i + 1] || lbs1[i] != lbs[i + 1])
381  ereport(ERROR,
382  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
383  errmsg("cannot concatenate incompatible arrays"),
384  errdetail("Arrays with differing dimensions are not "
385  "compatible for concatenation.")));
386  }
387  }
388  else
389  {
390  /*
391  * (ndims1 == ndims2 + 1)
392  *
393  * resulting array has the first argument as the outer array, with the
394  * second argument appended to the end of the outer dimension
395  */
396  ndims = ndims1;
397  dims = (int *) palloc(ndims * sizeof(int));
398  lbs = (int *) palloc(ndims * sizeof(int));
399  memcpy(dims, dims1, ndims * sizeof(int));
400  memcpy(lbs, lbs1, ndims * sizeof(int));
401 
402  /* increment number of elements in outer array */
403  dims[0] += 1;
404 
405  /* make sure the added element matches our existing elements */
406  for (i = 0; i < ndims2; i++)
407  {
408  if (dims2[i] != dims[i + 1] || lbs2[i] != lbs[i + 1])
409  ereport(ERROR,
410  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
411  errmsg("cannot concatenate incompatible arrays"),
412  errdetail("Arrays with differing dimensions are not "
413  "compatible for concatenation.")));
414  }
415  }
416 
417  /* Do this mainly for overflow checking */
418  nitems = ArrayGetNItems(ndims, dims);
419 
420  /* build the result array */
421  ndatabytes = ndatabytes1 + ndatabytes2;
422  if (ARR_HASNULL(v1) || ARR_HASNULL(v2))
423  {
424  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);
425  nbytes = ndatabytes + dataoffset;
426  }
427  else
428  {
429  dataoffset = 0; /* marker for no null bitmap */
430  nbytes = ndatabytes + ARR_OVERHEAD_NONULLS(ndims);
431  }
432  result = (ArrayType *) palloc0(nbytes);
433  SET_VARSIZE(result, nbytes);
434  result->ndim = ndims;
435  result->dataoffset = dataoffset;
436  result->elemtype = element_type;
437  memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
438  memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
439  /* data area is arg1 then arg2 */
440  memcpy(ARR_DATA_PTR(result), dat1, ndatabytes1);
441  memcpy(ARR_DATA_PTR(result) + ndatabytes1, dat2, ndatabytes2);
442  /* handle the null bitmap if needed */
443  if (ARR_HASNULL(result))
444  {
446  bitmap1, 0,
447  nitems1);
448  array_bitmap_copy(ARR_NULLBITMAP(result), nitems1,
449  bitmap2, 0,
450  nitems2);
451  }
452 
453  PG_RETURN_ARRAYTYPE_P(result);
454 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define ARR_SIZE(a)
Definition: array.h:270
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4624
int32 dataoffset
Definition: array.h:80
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
signed int int32
Definition: c.h:253
#define ARR_DATA_OFFSET(a)
Definition: array.h:297
#define ARR_LBOUND(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:81
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ARR_HASNULL(a)
Definition: array.h:272
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define ereport(elevel, rest)
Definition: elog.h:122
uint8 bits8
Definition: c.h:272
void * palloc0(Size size)
Definition: mcxt.c:920
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define ARR_NDIM(a)
Definition: array.h:271
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define ARR_NULLBITMAP(a)
Definition: array.h:281
#define PG_RETURN_NULL()
Definition: fmgr.h:289
int ndim
Definition: array.h:79
Datum array_position ( PG_FUNCTION_ARGS  )

Definition at line 689 of file array_userfuncs.c.

References array_position_common().

690 {
691  return array_position_common(fcinfo);
692 }
static Datum array_position_common(FunctionCallInfo fcinfo)
static Datum array_position_common ( FunctionCallInfo  fcinfo)
static

Definition at line 708 of file array_userfuncs.c.

References ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, array_contains_nulls(), array_create_iterator(), array_free_iterator(), array_iterate(), array_iterator(), DatumGetBool, ArrayMetaState::element_type, TypeCacheEntry::eq_opr_finfo, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoData::flinfo, fmgr_info_cxt(), FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, FmgrInfo::fn_oid, format_type_be(), FunctionCall2Coll(), get_typlenbyvalalign(), lookup_type_cache(), MemoryContextAlloc(), NULL, OidIsValid, PG_ARGISNULL, PG_FREE_IF_COPY, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_GETARG_INT32, PG_NARGS, PG_RETURN_INT32, PG_RETURN_NULL, ArrayMetaState::proc, ArrayMetaState::typalign, ArrayMetaState::typbyval, TYPECACHE_EQ_OPR_FINFO, ArrayMetaState::typlen, and value.

Referenced by array_position(), and array_position_start().

709 {
710  ArrayType *array;
711  Oid collation = PG_GET_COLLATION();
712  Oid element_type;
713  Datum searched_element,
714  value;
715  bool isnull;
716  int position,
717  position_min;
718  bool found = false;
719  TypeCacheEntry *typentry;
720  ArrayMetaState *my_extra;
721  bool null_search;
723 
724  if (PG_ARGISNULL(0))
725  PG_RETURN_NULL();
726 
727  array = PG_GETARG_ARRAYTYPE_P(0);
728  element_type = ARR_ELEMTYPE(array);
729 
730  /*
731  * We refuse to search for elements in multi-dimensional arrays, since we
732  * have no good way to report the element's location in the array.
733  */
734  if (ARR_NDIM(array) > 1)
735  ereport(ERROR,
736  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
737  errmsg("searching for elements in multidimensional arrays is not supported")));
738 
739  if (PG_ARGISNULL(1))
740  {
741  /* fast return when the array doesn't have nulls */
742  if (!array_contains_nulls(array))
743  PG_RETURN_NULL();
744  searched_element = (Datum) 0;
745  null_search = true;
746  }
747  else
748  {
749  searched_element = PG_GETARG_DATUM(1);
750  null_search = false;
751  }
752 
753  position = (ARR_LBOUND(array))[0] - 1;
754 
755  /* figure out where to start */
756  if (PG_NARGS() == 3)
757  {
758  if (PG_ARGISNULL(2))
759  ereport(ERROR,
760  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
761  errmsg("initial position must not be null")));
762 
763  position_min = PG_GETARG_INT32(2);
764  }
765  else
766  position_min = (ARR_LBOUND(array))[0];
767 
768  /*
769  * We arrange to look up type info for array_create_iterator only once per
770  * series of calls, assuming the element type doesn't change underneath
771  * us.
772  */
773  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
774  if (my_extra == NULL)
775  {
776  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
777  sizeof(ArrayMetaState));
778  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
779  my_extra->element_type = ~element_type;
780  }
781 
782  if (my_extra->element_type != element_type)
783  {
784  get_typlenbyvalalign(element_type,
785  &my_extra->typlen,
786  &my_extra->typbyval,
787  &my_extra->typalign);
788 
789  typentry = lookup_type_cache(element_type, TYPECACHE_EQ_OPR_FINFO);
790 
791  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
792  ereport(ERROR,
793  (errcode(ERRCODE_UNDEFINED_FUNCTION),
794  errmsg("could not identify an equality operator for type %s",
795  format_type_be(element_type))));
796 
797  my_extra->element_type = element_type;
798  fmgr_info_cxt(typentry->eq_opr_finfo.fn_oid, &my_extra->proc,
799  fcinfo->flinfo->fn_mcxt);
800  }
801 
802  /* Examine each array element until we find a match. */
803  array_iterator = array_create_iterator(array, 0, my_extra);
804  while (array_iterate(array_iterator, &value, &isnull))
805  {
806  position++;
807 
808  /* skip initial elements if caller requested so */
809  if (position < position_min)
810  continue;
811 
812  /*
813  * Can't look at the array element's value if it's null; but if we
814  * search for null, we have a hit and are done.
815  */
816  if (isnull || null_search)
817  {
818  if (isnull && null_search)
819  {
820  found = true;
821  break;
822  }
823  else
824  continue;
825  }
826 
827  /* not nulls, so run the operator */
828  if (DatumGetBool(FunctionCall2Coll(&my_extra->proc, collation,
829  searched_element, value)))
830  {
831  found = true;
832  break;
833  }
834  }
835 
836  array_free_iterator(array_iterator);
837 
838  /* Avoid leaking memory when handed toasted input */
839  PG_FREE_IF_COPY(array, 0);
840 
841  if (!found)
842  PG_RETURN_NULL();
843 
844  PG_RETURN_INT32(position);
845 }
ArrayIterator array_create_iterator(ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
Definition: arrayfuncs.c:4255
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
static struct @76 value
MemoryContext fn_mcxt
Definition: fmgr.h:62
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1989
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:115
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1306
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define PG_GET_COLLATION()
Definition: fmgr.h:155
#define ARR_LBOUND(a)
Definition: array.h:277
bool typbyval
Definition: array.h:221
FmgrInfo * flinfo
Definition: fmgr.h:71
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
bool array_iterate(ArrayIterator iterator, Datum *value, bool *isnull)
Definition: arrayfuncs.c:4334
#define ERROR
Definition: elog.h:43
static bool array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
Definition: _ltree_op.c:37
int16 typlen
Definition: array.h:220
#define DatumGetBool(X)
Definition: postgres.h:401
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:169
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
FmgrInfo eq_opr_finfo
Definition: typcache.h:67
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
Oid fn_oid
Definition: fmgr.h:56
void array_free_iterator(ArrayIterator iterator)
Definition: arrayfuncs.c:4417
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:216
#define PG_NARGS()
Definition: fmgr.h:160
void * fn_extra
Definition: fmgr.h:61
#define ARR_NDIM(a)
Definition: array.h:271
char typalign
Definition: array.h:222
int errmsg(const char *fmt,...)
Definition: elog.c:797
FmgrInfo proc
Definition: array.h:226
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
Oid element_type
Definition: array.h:219
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3542
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum array_position_start ( PG_FUNCTION_ARGS  )

Definition at line 695 of file array_userfuncs.c.

References array_position_common().

696 {
697  return array_position_common(fcinfo);
698 }
static Datum array_position_common(FunctionCallInfo fcinfo)
Datum array_positions ( PG_FUNCTION_ARGS  )

Definition at line 859 of file array_userfuncs.c.

References accumArrayResult(), ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, array_contains_nulls(), array_create_iterator(), array_free_iterator(), array_iterate(), array_iterator(), CurrentMemoryContext, DatumGetBool, ArrayMetaState::element_type, TypeCacheEntry::eq_opr_finfo, ereport, errcode(), errmsg(), ERROR, fmgr_info_cxt(), FmgrInfo::fn_mcxt, FmgrInfo::fn_oid, format_type_be(), FunctionCall2Coll(), get_typlenbyvalalign(), initArrayResult(), Int32GetDatum, INT4OID, lookup_type_cache(), makeArrayResult(), MemoryContextAlloc(), NULL, OidIsValid, PG_ARGISNULL, PG_FREE_IF_COPY, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_DATUM, PG_RETURN_NULL, ArrayMetaState::proc, ArrayMetaState::typalign, ArrayMetaState::typbyval, TYPECACHE_EQ_OPR_FINFO, ArrayMetaState::typlen, and value.

860 {
861  ArrayType *array;
862  Oid collation = PG_GET_COLLATION();
863  Oid element_type;
864  Datum searched_element,
865  value;
866  bool isnull;
867  int position;
868  TypeCacheEntry *typentry;
869  ArrayMetaState *my_extra;
870  bool null_search;
872  ArrayBuildState *astate = NULL;
873 
874  if (PG_ARGISNULL(0))
875  PG_RETURN_NULL();
876 
877  array = PG_GETARG_ARRAYTYPE_P(0);
878  element_type = ARR_ELEMTYPE(array);
879 
880  position = (ARR_LBOUND(array))[0] - 1;
881 
882  /*
883  * We refuse to search for elements in multi-dimensional arrays, since we
884  * have no good way to report the element's location in the array.
885  */
886  if (ARR_NDIM(array) > 1)
887  ereport(ERROR,
888  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
889  errmsg("searching for elements in multidimensional arrays is not supported")));
890 
891  astate = initArrayResult(INT4OID, CurrentMemoryContext, false);
892 
893  if (PG_ARGISNULL(1))
894  {
895  /* fast return when the array doesn't have nulls */
896  if (!array_contains_nulls(array))
898  searched_element = (Datum) 0;
899  null_search = true;
900  }
901  else
902  {
903  searched_element = PG_GETARG_DATUM(1);
904  null_search = false;
905  }
906 
907  /*
908  * We arrange to look up type info for array_create_iterator only once per
909  * series of calls, assuming the element type doesn't change underneath
910  * us.
911  */
912  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
913  if (my_extra == NULL)
914  {
915  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
916  sizeof(ArrayMetaState));
917  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
918  my_extra->element_type = ~element_type;
919  }
920 
921  if (my_extra->element_type != element_type)
922  {
923  get_typlenbyvalalign(element_type,
924  &my_extra->typlen,
925  &my_extra->typbyval,
926  &my_extra->typalign);
927 
928  typentry = lookup_type_cache(element_type, TYPECACHE_EQ_OPR_FINFO);
929 
930  if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
931  ereport(ERROR,
932  (errcode(ERRCODE_UNDEFINED_FUNCTION),
933  errmsg("could not identify an equality operator for type %s",
934  format_type_be(element_type))));
935 
936  my_extra->element_type = element_type;
937  fmgr_info_cxt(typentry->eq_opr_finfo.fn_oid, &my_extra->proc,
938  fcinfo->flinfo->fn_mcxt);
939  }
940 
941  /*
942  * Accumulate each array position iff the element matches the given
943  * element.
944  */
945  array_iterator = array_create_iterator(array, 0, my_extra);
946  while (array_iterate(array_iterator, &value, &isnull))
947  {
948  position += 1;
949 
950  /*
951  * Can't look at the array element's value if it's null; but if we
952  * search for null, we have a hit.
953  */
954  if (isnull || null_search)
955  {
956  if (isnull && null_search)
957  astate =
958  accumArrayResult(astate, Int32GetDatum(position), false,
960 
961  continue;
962  }
963 
964  /* not nulls, so run the operator */
965  if (DatumGetBool(FunctionCall2Coll(&my_extra->proc, collation,
966  searched_element, value)))
967  astate =
968  accumArrayResult(astate, Int32GetDatum(position), false,
970  }
971 
972  array_free_iterator(array_iterator);
973 
974  /* Avoid leaking memory when handed toasted input */
975  PG_FREE_IF_COPY(array, 0);
976 
978 }
ArrayIterator array_create_iterator(ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
Definition: arrayfuncs.c:4255
static struct @76 value
MemoryContext fn_mcxt
Definition: fmgr.h:62
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:4951
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1989
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:115
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1306
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define PG_GET_COLLATION()
Definition: fmgr.h:155
#define ARR_LBOUND(a)
Definition: array.h:277
bool typbyval
Definition: array.h:221
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
bool array_iterate(ArrayIterator iterator, Datum *value, bool *isnull)
Definition: arrayfuncs.c:4334
#define ERROR
Definition: elog.h:43
static bool array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
Definition: _ltree_op.c:37
int16 typlen
Definition: array.h:220
#define DatumGetBool(X)
Definition: postgres.h:401
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:169
#define ereport(elevel, rest)
Definition: elog.h:122
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
Definition: arrayfuncs.c:5055
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
FmgrInfo eq_opr_finfo
Definition: typcache.h:67
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
Oid fn_oid
Definition: fmgr.h:56
void array_free_iterator(ArrayIterator iterator)
Definition: arrayfuncs.c:4417
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:216
#define ARR_NDIM(a)
Definition: array.h:271
char typalign
Definition: array.h:222
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:4991
#define Int32GetDatum(X)
Definition: postgres.h:487
int errmsg(const char *fmt,...)
Definition: elog.c:797
FmgrInfo proc
Definition: array.h:226
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
Oid element_type
Definition: array.h:219
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3542
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum array_prepend ( PG_FUNCTION_ARGS  )

Definition at line 157 of file array_userfuncs.c.

References array_set_element(), Assert, EOHPGetRWDatum, ereport, errcode(), errmsg(), ERROR, fetch_array_arg_replace_nulls(), ExpandedArrayHeader::hdr, ExpandedArrayHeader::lbound, ExpandedArrayHeader::ndims, PG_ARGISNULL, PG_GETARG_DATUM, PG_RETURN_DATUM, ArrayMetaState::typalign, ArrayMetaState::typbyval, and ArrayMetaState::typlen.

158 {
159  ExpandedArrayHeader *eah;
160  Datum newelem;
161  bool isNull;
162  Datum result;
163  int *lb;
164  int indx;
165  int lb0;
166  ArrayMetaState *my_extra;
167 
168  isNull = PG_ARGISNULL(0);
169  if (isNull)
170  newelem = (Datum) 0;
171  else
172  newelem = PG_GETARG_DATUM(0);
173  eah = fetch_array_arg_replace_nulls(fcinfo, 1);
174 
175  if (eah->ndims == 1)
176  {
177  /* prepend newelem */
178  lb = eah->lbound;
179  indx = lb[0] - 1;
180  lb0 = lb[0];
181 
182  /* overflow? */
183  if (indx > lb[0])
184  ereport(ERROR,
185  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
186  errmsg("integer out of range")));
187  }
188  else if (eah->ndims == 0)
189  {
190  indx = 1;
191  lb0 = 1;
192  }
193  else
194  ereport(ERROR,
195  (errcode(ERRCODE_DATA_EXCEPTION),
196  errmsg("argument must be empty or one-dimensional array")));
197 
198  /* Perform element insertion */
199  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
200 
201  result = array_set_element(EOHPGetRWDatum(&eah->hdr),
202  1, &indx, newelem, isNull,
203  -1, my_extra->typlen, my_extra->typbyval, my_extra->typalign);
204 
205  /* Readjust result's LB to match the input's, as expected for prepend */
206  Assert(result == EOHPGetRWDatum(&eah->hdr));
207  if (eah->ndims == 1)
208  {
209  /* This is ok whether we've deconstructed or not */
210  eah->lbound[0] = lb0;
211  }
212 
213  PG_RETURN_DATUM(result);
214 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum array_set_element(Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:2186
bool typbyval
Definition: array.h:221
static ExpandedArrayHeader * fetch_array_arg_replace_nulls(FunctionCallInfo fcinfo, int argno)
#define ERROR
Definition: elog.h:43
ExpandedObjectHeader hdr
Definition: array.h:102
int16 typlen
Definition: array.h:220
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define Assert(condition)
Definition: c.h:670
char typalign
Definition: array.h:222
#define EOHPGetRWDatum(eohptr)
int errmsg(const char *fmt,...)
Definition: elog.c:797
ArrayType* create_singleton_array ( FunctionCallInfo  fcinfo,
Oid  element_type,
Datum  element,
bool  isNull,
int  ndims 
)

Definition at line 461 of file array_userfuncs.c.

References construct_md_array(), element(), ArrayMetaState::element_type, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, get_typlenbyvalalign(), i, MAXDIM, MemoryContextAlloc(), NULL, ArrayMetaState::typalign, ArrayMetaState::typbyval, and ArrayMetaState::typlen.

Referenced by text_to_array_internal().

466 {
467  Datum dvalues[1];
468  bool nulls[1];
469  int16 typlen;
470  bool typbyval;
471  char typalign;
472  int dims[MAXDIM];
473  int lbs[MAXDIM];
474  int i;
475  ArrayMetaState *my_extra;
476 
477  if (ndims < 1)
478  ereport(ERROR,
479  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
480  errmsg("invalid number of dimensions: %d", ndims)));
481  if (ndims > MAXDIM)
482  ereport(ERROR,
483  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
484  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
485  ndims, MAXDIM)));
486 
487  dvalues[0] = element;
488  nulls[0] = isNull;
489 
490  for (i = 0; i < ndims; i++)
491  {
492  dims[i] = 1;
493  lbs[i] = 1;
494  }
495 
496  /*
497  * We arrange to look up info about element type only once per series of
498  * calls, assuming the element type doesn't change underneath us.
499  */
500  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
501  if (my_extra == NULL)
502  {
503  fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
504  sizeof(ArrayMetaState));
505  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
506  my_extra->element_type = ~element_type;
507  }
508 
509  if (my_extra->element_type != element_type)
510  {
511  /* Get info about element type */
512  get_typlenbyvalalign(element_type,
513  &my_extra->typlen,
514  &my_extra->typbyval,
515  &my_extra->typalign);
516  my_extra->element_type = element_type;
517  }
518  typlen = my_extra->typlen;
519  typbyval = my_extra->typbyval;
520  typalign = my_extra->typalign;
521 
522  return construct_md_array(dvalues, nulls, ndims, dims, lbs, element_type,
523  typlen, typbyval, typalign);
524 }
signed short int16
Definition: c.h:252
MemoryContext fn_mcxt
Definition: fmgr.h:62
#define MAXDIM
Definition: c.h:415
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1989
int errcode(int sqlerrcode)
Definition: elog.c:575
bool typbyval
Definition: array.h:221
FmgrInfo * flinfo
Definition: fmgr.h:71
#define ERROR
Definition: elog.h:43
int16 typlen
Definition: array.h:220
#define ereport(elevel, rest)
Definition: elog.h:122
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:226
void * fn_extra
Definition: fmgr.h:61
char typalign
Definition: array.h:222
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
int i
Oid element_type
Definition: array.h:219
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3340
static ExpandedArrayHeader* fetch_array_arg_replace_nulls ( FunctionCallInfo  fcinfo,
int  argno 
)
static

Definition at line 41 of file array_userfuncs.c.

References AggCheckCallContext(), construct_empty_expanded_array(), CurrentMemoryContext, ArrayMetaState::element_type, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, get_element_type(), get_fn_expr_argtype(), InvalidOid, MemoryContextAlloc(), MemoryContextSwitchTo(), NULL, OidIsValid, PG_ARGISNULL, and PG_GETARG_EXPANDED_ARRAYX.

Referenced by array_append(), and array_prepend().

42 {
44  Oid element_type;
45  ArrayMetaState *my_extra;
46  MemoryContext resultcxt;
47 
48  /* If first time through, create datatype cache struct */
49  my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
50  if (my_extra == NULL)
51  {
52  my_extra = (ArrayMetaState *)
54  sizeof(ArrayMetaState));
55  my_extra->element_type = InvalidOid;
56  fcinfo->flinfo->fn_extra = my_extra;
57  }
58 
59  /* Figure out which context we want the result in */
60  if (!AggCheckCallContext(fcinfo, &resultcxt))
61  resultcxt = CurrentMemoryContext;
62 
63  /* Now collect the array value */
64  if (!PG_ARGISNULL(argno))
65  {
66  MemoryContext oldcxt = MemoryContextSwitchTo(resultcxt);
67 
68  eah = PG_GETARG_EXPANDED_ARRAYX(argno, my_extra);
69  MemoryContextSwitchTo(oldcxt);
70  }
71  else
72  {
73  /* We have to look up the array type and element type */
74  Oid arr_typeid = get_fn_expr_argtype(fcinfo->flinfo, argno);
75 
76  if (!OidIsValid(arr_typeid))
77  ereport(ERROR,
78  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
79  errmsg("could not determine input data type")));
80  element_type = get_element_type(arr_typeid);
81  if (!OidIsValid(element_type))
82  ereport(ERROR,
83  (errcode(ERRCODE_DATATYPE_MISMATCH),
84  errmsg("input data type is not an array")));
85 
86  eah = construct_empty_expanded_array(element_type,
87  resultcxt,
88  my_extra);
89  }
90 
91  return eah;
92 }
MemoryContext fn_mcxt
Definition: fmgr.h:62
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2452
#define PG_GETARG_EXPANDED_ARRAYX(n, metacache)
Definition: array.h:250
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
FmgrInfo * flinfo
Definition: fmgr.h:71
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:2220
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
ExpandedArrayHeader * construct_empty_expanded_array(Oid element_type, MemoryContext parentcontext, ArrayMetaState *metacache)
Definition: arrayfuncs.c:3441
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
void * fn_extra
Definition: fmgr.h:61
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
Oid element_type
Definition: array.h:219