PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
array.h File Reference
#include "fmgr.h"
#include "utils/expandeddatum.h"
Include dependency graph for array.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ArrayType
 
struct  ExpandedArrayHeader
 
union  AnyArrayType
 
struct  ArrayBuildState
 
struct  ArrayBuildStateArr
 
struct  ArrayBuildStateAny
 
struct  ArrayMetaState
 
struct  ArrayMapState
 

Macros

#define EA_MAGIC   689375833 /* ID for debugging crosschecks */
 
#define DatumGetArrayTypeP(X)   ((ArrayType *) PG_DETOAST_DATUM(X))
 
#define DatumGetArrayTypePCopy(X)   ((ArrayType *) PG_DETOAST_DATUM_COPY(X))
 
#define PG_GETARG_ARRAYTYPE_P(n)   DatumGetArrayTypeP(PG_GETARG_DATUM(n))
 
#define PG_GETARG_ARRAYTYPE_P_COPY(n)   DatumGetArrayTypePCopy(PG_GETARG_DATUM(n))
 
#define PG_RETURN_ARRAYTYPE_P(x)   PG_RETURN_POINTER(x)
 
#define PG_GETARG_EXPANDED_ARRAY(n)   DatumGetExpandedArray(PG_GETARG_DATUM(n))
 
#define PG_GETARG_EXPANDED_ARRAYX(n, metacache)   DatumGetExpandedArrayX(PG_GETARG_DATUM(n), metacache)
 
#define PG_RETURN_EXPANDED_ARRAY(x)   PG_RETURN_DATUM(EOHPGetRWDatum(&(x)->hdr))
 
#define PG_GETARG_ANY_ARRAY_P(n)   DatumGetAnyArrayP(PG_GETARG_DATUM(n))
 
#define ARR_SIZE(a)   VARSIZE(a)
 
#define ARR_NDIM(a)   ((a)->ndim)
 
#define ARR_HASNULL(a)   ((a)->dataoffset != 0)
 
#define ARR_ELEMTYPE(a)   ((a)->elemtype)
 
#define ARR_DIMS(a)   ((int *) (((char *) (a)) + sizeof(ArrayType)))
 
#define ARR_LBOUND(a)
 
#define ARR_NULLBITMAP(a)
 
#define ARR_OVERHEAD_NONULLS(ndims)   MAXALIGN(sizeof(ArrayType) + 2 * sizeof(int) * (ndims))
 
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
 
#define ARR_DATA_OFFSET(a)   (ARR_HASNULL(a) ? (a)->dataoffset : ARR_OVERHEAD_NONULLS(ARR_NDIM(a)))
 
#define ARR_DATA_PTR(a)   (((char *) (a)) + ARR_DATA_OFFSET(a))
 
#define AARR_NDIM(a)   (VARATT_IS_EXPANDED_HEADER(a) ? (a)->xpn.ndims : ARR_NDIM(&(a)->flt))
 
#define AARR_HASNULL(a)
 
#define AARR_ELEMTYPE(a)   (VARATT_IS_EXPANDED_HEADER(a) ? (a)->xpn.element_type : ARR_ELEMTYPE(&(a)->flt))
 
#define AARR_DIMS(a)   (VARATT_IS_EXPANDED_HEADER(a) ? (a)->xpn.dims : ARR_DIMS(&(a)->flt))
 
#define AARR_LBOUND(a)   (VARATT_IS_EXPANDED_HEADER(a) ? (a)->xpn.lbound : ARR_LBOUND(&(a)->flt))
 

Typedefs

typedef struct ExpandedArrayHeader ExpandedArrayHeader
 
typedef union AnyArrayType AnyArrayType
 
typedef struct ArrayBuildState ArrayBuildState
 
typedef struct ArrayBuildStateArr ArrayBuildStateArr
 
typedef struct ArrayBuildStateAny ArrayBuildStateAny
 
typedef struct ArrayMetaState ArrayMetaState
 
typedef struct ArrayMapState ArrayMapState
 
typedef struct ArrayIteratorDataArrayIterator
 

Functions

void CopyArrayEls (ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
 
Datum array_get_element (Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
Datum array_set_element (Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_get_slice (Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_set_slice (Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, Datum srcArrayDatum, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_ref (ArrayType *array, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
ArrayTypearray_set (ArrayType *array, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_map (Datum arrayd, struct ExprState *exprstate, struct ExprContext *econtext, Oid retType, ArrayMapState *amstate)
 
void array_bitmap_copy (bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
 
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)
 
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)
 
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)
 
int ArrayGetOffset (int n, const int *dim, const int *lb, const int *indx)
 
int ArrayGetOffset0 (int n, const int *tup, const int *scale)
 
int ArrayGetNItems (int ndim, const int *dims)
 
void mda_get_range (int n, int *span, const int *st, const int *endp)
 
void mda_get_prod (int n, const int *range, int *prod)
 
void mda_get_offset_values (int n, int *dist, const int *prod, const int *span)
 
int mda_next_tuple (int n, int *curr, const int *span)
 
int32ArrayGetIntegerTypmods (ArrayType *arr, int *n)
 
Datum expand_array (Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
 
ExpandedArrayHeaderDatumGetExpandedArray (Datum d)
 
ExpandedArrayHeaderDatumGetExpandedArrayX (Datum d, ArrayMetaState *metacache)
 
AnyArrayTypeDatumGetAnyArrayP (Datum d)
 
void deconstruct_expanded_array (ExpandedArrayHeader *eah)
 

Variables

bool Array_nulls
 

Macro Definition Documentation

#define AARR_ELEMTYPE (   a)    (VARATT_IS_EXPANDED_HEADER(a) ? (a)->xpn.element_type : ARR_ELEMTYPE(&(a)->flt))
#define AARR_HASNULL (   a)
Value:
((a)->xpn.dvalues != NULL ? (a)->xpn.dnulls != NULL : ARR_HASNULL((a)->xpn.fvalue)) : \
ARR_HASNULL(&(a)->flt))
#define ARR_HASNULL(a)
Definition: array.h:276
#define VARATT_IS_EXPANDED_HEADER(PTR)

Definition at line 315 of file array.h.

Referenced by array_send().

#define AARR_LBOUND (   a)    (VARATT_IS_EXPANDED_HEADER(a) ? (a)->xpn.lbound : ARR_LBOUND(&(a)->flt))
#define ARR_DATA_OFFSET (   a)    (ARR_HASNULL(a) ? (a)->dataoffset : ARR_OVERHEAD_NONULLS(ARR_NDIM(a)))
#define ARR_DIMS (   a)    ((int *) (((char *) (a)) + sizeof(ArrayType)))

Definition at line 279 of file array.h.

Referenced by _arrq_cons(), _lca(), _lt_q_regex(), _ltree_compress(), accumArrayResultArr(), aclnewowner(), aclupdate(), allocacl(), AlterPolicy(), array_cat(), array_contains_nulls(), array_create_iterator(), array_fill_internal(), array_get_element(), array_get_slice(), array_in(), array_insert_slice(), array_iterator(), array_map(), array_recv(), array_replace_internal(), array_set_element(), array_set_slice(), array_to_json_internal(), array_to_jsonb_internal(), array_to_text_internal(), arrq_cons(), build_function_result_tupdesc_d(), check_float8_array(), check_role_for_policy(), construct_md_array(), count_nulls(), create_array_envelope(), deconstruct_array(), EA_flatten_into(), equalPolicy(), estimate_array_length(), ExecEvalArrayExpr(), ExecEvalScalarArrayOp(), expand_array(), extension_config_remove(), fetch_statentries_for_relation(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_func_trftypes(), get_primary_key_attnos(), get_text_array_contents(), getWeights(), GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), hstore_from_array(), hstore_from_arrays(), hstore_slice_to_array(), int2vectorrecv(), is_strict_saop(), json_object(), jsonb_object(), lt_q_regex(), makeArrayResultArr(), new_intArrayType(), oidvectorrecv(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), pg_extension_config_dump(), pg_get_functiondef(), pg_get_statisticsobj_worker(), pg_isolation_test_session_is_blocked(), plperl_ref_from_pg_array(), PLyList_FromArray(), predicate_classify(), ProcedureCreate(), ProcessGUCArray(), RelationGetExclusionInfo(), RelationGetFKeyList(), RemoveRoleFromObjectPolicy(), resize_intArrayType(), ri_LoadConstraintInfo(), TryReuseForeignKey(), width_bucket_array_fixed(), width_bucket_array_float8(), and width_bucket_array_variable().

#define ARR_ELEMTYPE (   a)    ((a)->elemtype)
#define ARR_NDIM (   a)    ((a)->ndim)

Definition at line 275 of file array.h.

Referenced by _arrq_cons(), _lca(), _lt_q_regex(), _ltree_compress(), accumArrayResultArr(), array_cat(), array_contains_nulls(), array_create_iterator(), array_fill_internal(), array_get_element(), array_get_slice(), array_insert_slice(), array_iterator(), array_position_common(), array_positions(), array_replace_internal(), array_set_element(), array_set_slice(), array_to_json_internal(), array_to_jsonb_internal(), array_to_text_internal(), ArrayGetIntegerTypmods(), arrq_cons(), build_function_result_tupdesc_d(), check_acl(), check_float8_array(), count_nulls(), DecodeTextArrayToCString(), deconstruct_array(), estimate_array_length(), exec_stmt_foreach_a(), ExecEvalArrayExpr(), ExecEvalScalarArrayOp(), expand_array(), extension_config_remove(), fetch_statentries_for_relation(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_func_trftypes(), get_primary_key_attnos(), get_text_array_contents(), getWeights(), GUCArrayAdd(), hstore_from_array(), hstore_from_arrays(), hstore_slice_to_array(), int2vectorrecv(), is_strict_saop(), json_object(), json_object_two_arg(), jsonb_delete_array(), jsonb_delete_path(), jsonb_insert(), jsonb_object(), jsonb_object_two_arg(), jsonb_set(), lt_q_regex(), new_intArrayType(), oidvectorrecv(), parse_key_value_arrays(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), pg_extension_config_dump(), pg_get_functiondef(), pg_get_statisticsobj_worker(), pg_isolation_test_session_is_blocked(), pg_logical_slot_get_changes_guts(), plperl_ref_from_pg_array(), PLyList_FromArray(), predicate_classify(), ProcedureCreate(), ProcessGUCArray(), RelationGetExclusionInfo(), RelationGetFKeyList(), resize_intArrayType(), ri_LoadConstraintInfo(), TryReuseForeignKey(), width_bucket_array(), width_bucket_array_fixed(), width_bucket_array_float8(), and width_bucket_array_variable().

#define ARR_OVERHEAD_WITHNULLS (   ndims,
  nitems 
)
#define EA_MAGIC   689375833 /* ID for debugging crosschecks */
#define PG_GETARG_ARRAYTYPE_P (   n)    DatumGetArrayTypeP(PG_GETARG_DATUM(n))

Definition at line 248 of file array.h.

Referenced by _lca(), _lt_q_regex(), _ltq_extract_regex(), _ltq_regex(), _ltree_extract_isparent(), _ltree_extract_risparent(), _ltree_isparent(), _ltree_risparent(), _ltxtq_exec(), _ltxtq_extract_exec(), array_cat(), array_fill(), array_fill_with_lower_bounds(), array_position_common(), array_positions(), array_remove(), array_replace(), array_to_text(), array_to_text_null(), array_to_tsvector(), binary_upgrade_create_empty_extension(), bittypmodin(), bpchartypmodin(), concat_internal(), count_nulls(), cube_a_f8(), cube_a_f8_f8(), cube_subset(), dblink_build_sql_delete(), dblink_build_sql_insert(), dblink_build_sql_update(), float4_accum(), float8_accum(), float8_avg(), float8_combine(), float8_corr(), float8_covar_pop(), float8_covar_samp(), float8_regr_accum(), float8_regr_avgx(), float8_regr_avgy(), float8_regr_combine(), float8_regr_intercept(), float8_regr_r2(), float8_regr_slope(), float8_regr_sxx(), float8_regr_sxy(), float8_regr_syy(), float8_stddev_pop(), float8_stddev_samp(), float8_var_pop(), float8_var_samp(), g_int_same(), g_intbig_consistent(), get_jsonb_path_all(), get_path_all(), ghstore_consistent(), gin_extract_hstore_query(), gin_extract_jsonb_query(), ginint4_queryextract(), hstore_delete_array(), hstore_exists_all(), hstore_exists_any(), hstore_from_array(), hstore_from_arrays(), hstore_slice_to_array(), hstore_slice_to_hstore(), icount(), idx(), int2_avg_accum(), int2_avg_accum_inv(), int2int4_sum(), int4_avg_accum(), int4_avg_accum_inv(), int4_avg_combine(), int8_avg(), intarray_push_array(), intarray_push_elem(), interval_accum(), interval_accum_inv(), interval_avg(), interval_combine(), intervaltypmodin(), intset_union_elem(), json_object(), json_object_two_arg(), jsonb_delete_array(), jsonb_delete_path(), jsonb_exists_all(), jsonb_exists_any(), jsonb_insert(), jsonb_object(), jsonb_object_two_arg(), jsonb_set(), lt_q_regex(), ltree_consistent(), numerictypmodin(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), pg_armor(), pg_get_object_address(), pg_isolation_test_session_is_blocked(), pg_logical_slot_get_changes_guts(), subarray(), text_format(), timestamptypmodin(), timestamptztypmodin(), timetypmodin(), timetztypmodin(), tsvector_delete_arr(), tsvector_filter(), tsvector_setweight_by_filter(), varbittypmodin(), varchartypmodin(), width_bucket_array(), xpath(), and xpath_exists().

#define PG_GETARG_EXPANDED_ARRAY (   n)    DatumGetExpandedArray(PG_GETARG_DATUM(n))

Definition at line 253 of file array.h.

#define PG_GETARG_EXPANDED_ARRAYX (   n,
  metacache 
)    DatumGetExpandedArrayX(PG_GETARG_DATUM(n), metacache)

Definition at line 254 of file array.h.

Referenced by fetch_array_arg_replace_nulls().

#define PG_RETURN_EXPANDED_ARRAY (   x)    PG_RETURN_DATUM(EOHPGetRWDatum(&(x)->hdr))

Definition at line 256 of file array.h.

Typedef Documentation

Definition at line 243 of file array.h.

Function Documentation

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

Definition at line 5042 of file arrayfuncs.c.

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

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

5046 {
5047  MemoryContext oldcontext;
5048 
5049  if (astate == NULL)
5050  {
5051  /* First time through --- initialize */
5052  astate = initArrayResult(element_type, rcontext, true);
5053  }
5054  else
5055  {
5056  Assert(astate->element_type == element_type);
5057  }
5058 
5059  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5060 
5061  /* enlarge dvalues[]/dnulls[] if needed */
5062  if (astate->nelems >= astate->alen)
5063  {
5064  astate->alen *= 2;
5065  astate->dvalues = (Datum *)
5066  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5067  astate->dnulls = (bool *)
5068  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5069  }
5070 
5071  /*
5072  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5073  * it's varlena. (You might think that detoasting is not needed here
5074  * because construct_md_array can detoast the array elements later.
5075  * However, we must not let construct_md_array modify the ArrayBuildState
5076  * because that would mean array_agg_finalfn damages its input, which is
5077  * verboten. Also, this way frequently saves one copying step.)
5078  */
5079  if (!disnull && !astate->typbyval)
5080  {
5081  if (astate->typlen == -1)
5082  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5083  else
5084  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5085  }
5086 
5087  astate->dvalues[astate->nelems] = dvalue;
5088  astate->dnulls[astate->nelems] = disnull;
5089  astate->nelems++;
5090 
5091  MemoryContextSwitchTo(oldcontext);
5092 
5093  return astate;
5094 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:207
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5003
#define PointerGetDatum(X)
Definition: postgres.h:562
Datum * dvalues
Definition: array.h:175
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:181
Oid element_type
Definition: array.h:179
bool * dnulls
Definition: array.h:176
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:681
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
MemoryContext mcontext
Definition: array.h:174
int16 typlen
Definition: array.h:180
ArrayBuildStateAny* accumArrayResultAny ( ArrayBuildStateAny astate,
Datum  dvalue,
bool  disnull,
Oid  input_type,
MemoryContext  rcontext 
)

Definition at line 5513 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5517 {
5518  if (astate == NULL)
5519  astate = initArrayResultAny(input_type, rcontext, true);
5520 
5521  if (astate->scalarstate)
5522  (void) accumArrayResult(astate->scalarstate,
5523  dvalue, disnull,
5524  input_type, rcontext);
5525  else
5526  (void) accumArrayResultArr(astate->arraystate,
5527  dvalue, disnull,
5528  input_type, rcontext);
5529 
5530  return astate;
5531 }
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5468
ArrayBuildState * scalarstate
Definition: array.h:214
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5236
ArrayBuildStateArr * arraystate
Definition: array.h:215
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5042
ArrayBuildStateArr* accumArrayResultArr ( ArrayBuildStateArr astate,
Datum  dvalue,
bool  disnull,
Oid  array_type,
MemoryContext  rcontext 
)

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

Referenced by accumArrayResultAny(), and array_agg_array_transfn().

5240 {
5241  ArrayType *arg;
5242  MemoryContext oldcontext;
5243  int *dims,
5244  *lbs,
5245  ndims,
5246  nitems,
5247  ndatabytes;
5248  char *data;
5249  int i;
5250 
5251  /*
5252  * We disallow accumulating null subarrays. Another plausible definition
5253  * is to ignore them, but callers that want that can just skip calling
5254  * this function.
5255  */
5256  if (disnull)
5257  ereport(ERROR,
5258  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5259  errmsg("cannot accumulate null arrays")));
5260 
5261  /* Detoast input array in caller's context */
5262  arg = DatumGetArrayTypeP(dvalue);
5263 
5264  if (astate == NULL)
5265  astate = initArrayResultArr(array_type, InvalidOid, rcontext, true);
5266  else
5267  Assert(astate->array_type == array_type);
5268 
5269  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5270 
5271  /* Collect this input's dimensions */
5272  ndims = ARR_NDIM(arg);
5273  dims = ARR_DIMS(arg);
5274  lbs = ARR_LBOUND(arg);
5275  data = ARR_DATA_PTR(arg);
5276  nitems = ArrayGetNItems(ndims, dims);
5277  ndatabytes = ARR_SIZE(arg) - ARR_DATA_OFFSET(arg);
5278 
5279  if (astate->ndims == 0)
5280  {
5281  /* First input; check/save the dimensionality info */
5282 
5283  /* Should we allow empty inputs and just produce an empty output? */
5284  if (ndims == 0)
5285  ereport(ERROR,
5286  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5287  errmsg("cannot accumulate empty arrays")));
5288  if (ndims + 1 > MAXDIM)
5289  ereport(ERROR,
5290  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5291  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5292  ndims + 1, MAXDIM)));
5293 
5294  /*
5295  * The output array will have n+1 dimensions, with the ones after the
5296  * first matching the input's dimensions.
5297  */
5298  astate->ndims = ndims + 1;
5299  astate->dims[0] = 0;
5300  memcpy(&astate->dims[1], dims, ndims * sizeof(int));
5301  astate->lbs[0] = 1;
5302  memcpy(&astate->lbs[1], lbs, ndims * sizeof(int));
5303 
5304  /* Allocate at least enough data space for this item */
5305  astate->abytes = 1024;
5306  while (astate->abytes <= ndatabytes)
5307  astate->abytes *= 2;
5308  astate->data = (char *) palloc(astate->abytes);
5309  }
5310  else
5311  {
5312  /* Second or later input: must match first input's dimensionality */
5313  if (astate->ndims != ndims + 1)
5314  ereport(ERROR,
5315  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5316  errmsg("cannot accumulate arrays of different dimensionality")));
5317  for (i = 0; i < ndims; i++)
5318  {
5319  if (astate->dims[i + 1] != dims[i] || astate->lbs[i + 1] != lbs[i])
5320  ereport(ERROR,
5321  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5322  errmsg("cannot accumulate arrays of different dimensionality")));
5323  }
5324 
5325  /* Enlarge data space if needed */
5326  if (astate->nbytes + ndatabytes > astate->abytes)
5327  {
5328  astate->abytes = Max(astate->abytes * 2,
5329  astate->nbytes + ndatabytes);
5330  astate->data = (char *) repalloc(astate->data, astate->abytes);
5331  }
5332  }
5333 
5334  /*
5335  * Copy the data portion of the sub-array. Note we assume that the
5336  * advertised data length of the sub-array is properly aligned. We do not
5337  * have to worry about detoasting elements since whatever's in the
5338  * sub-array should be OK already.
5339  */
5340  memcpy(astate->data + astate->nbytes, data, ndatabytes);
5341  astate->nbytes += ndatabytes;
5342 
5343  /* Deal with null bitmap if needed */
5344  if (astate->nullbitmap || ARR_HASNULL(arg))
5345  {
5346  int newnitems = astate->nitems + nitems;
5347 
5348  if (astate->nullbitmap == NULL)
5349  {
5350  /*
5351  * First input with nulls; we must retrospectively handle any
5352  * previous inputs by marking all their items non-null.
5353  */
5354  astate->aitems = 256;
5355  while (astate->aitems <= newnitems)
5356  astate->aitems *= 2;
5357  astate->nullbitmap = (bits8 *) palloc((astate->aitems + 7) / 8);
5358  array_bitmap_copy(astate->nullbitmap, 0,
5359  NULL, 0,
5360  astate->nitems);
5361  }
5362  else if (newnitems > astate->aitems)
5363  {
5364  astate->aitems = Max(astate->aitems * 2, newnitems);
5365  astate->nullbitmap = (bits8 *)
5366  repalloc(astate->nullbitmap, (astate->aitems + 7) / 8);
5367  }
5368  array_bitmap_copy(astate->nullbitmap, astate->nitems,
5369  ARR_NULLBITMAP(arg), 0,
5370  nitems);
5371  }
5372 
5373  astate->nitems += nitems;
5374  astate->dims[0] += 1;
5375 
5376  MemoryContextSwitchTo(oldcontext);
5377 
5378  /* Release detoasted copy if any */
5379  if ((Pointer) arg != DatumGetPointer(dvalue))
5380  pfree(arg);
5381 
5382  return astate;
5383 }
#define ARR_SIZE(a)
Definition: array.h:274
#define MAXDIM
Definition: c.h:413
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4676
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5190
#define ARR_DATA_OFFSET(a)
Definition: array.h:301
#define ARR_LBOUND(a)
Definition: array.h:281
bits8 * nullbitmap
Definition: array.h:194
void pfree(void *pointer)
Definition: mcxt.c:949
char * Pointer
Definition: c.h:235
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define ereport(elevel, rest)
Definition: elog.h:122
uint8 bits8
Definition: c.h:265
#define InvalidOid
Definition: postgres_ext.h:36
int lbs[MAXDIM]
Definition: array.h:201
#define Max(x, y)
Definition: c.h:806
#define Assert(condition)
Definition: c.h:681
#define ARR_NDIM(a)
Definition: array.h:275
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
#define DatumGetPointer(X)
Definition: postgres.h:555
int dims[MAXDIM]
Definition: array.h:200
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void * arg
#define ARR_NULLBITMAP(a)
Definition: array.h:285
MemoryContext mcontext
Definition: array.h:192
#define DatumGetArrayTypeP(X)
Definition: array.h:246
void array_bitmap_copy ( bits8 destbitmap,
int  destoffset,
const bits8 srcbitmap,
int  srcoffset,
int  nitems 
)

Definition at line 4676 of file arrayfuncs.c.

References Assert.

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

4679 {
4680  int destbitmask,
4681  destbitval,
4682  srcbitmask,
4683  srcbitval;
4684 
4685  Assert(destbitmap);
4686  if (nitems <= 0)
4687  return; /* don't risk fetch off end of memory */
4688  destbitmap += destoffset / 8;
4689  destbitmask = 1 << (destoffset % 8);
4690  destbitval = *destbitmap;
4691  if (srcbitmap)
4692  {
4693  srcbitmap += srcoffset / 8;
4694  srcbitmask = 1 << (srcoffset % 8);
4695  srcbitval = *srcbitmap;
4696  while (nitems-- > 0)
4697  {
4698  if (srcbitval & srcbitmask)
4699  destbitval |= destbitmask;
4700  else
4701  destbitval &= ~destbitmask;
4702  destbitmask <<= 1;
4703  if (destbitmask == 0x100)
4704  {
4705  *destbitmap++ = destbitval;
4706  destbitmask = 1;
4707  if (nitems > 0)
4708  destbitval = *destbitmap;
4709  }
4710  srcbitmask <<= 1;
4711  if (srcbitmask == 0x100)
4712  {
4713  srcbitmap++;
4714  srcbitmask = 1;
4715  if (nitems > 0)
4716  srcbitval = *srcbitmap;
4717  }
4718  }
4719  if (destbitmask != 1)
4720  *destbitmap = destbitval;
4721  }
4722  else
4723  {
4724  while (nitems-- > 0)
4725  {
4726  destbitval |= destbitmask;
4727  destbitmask <<= 1;
4728  if (destbitmask == 0x100)
4729  {
4730  *destbitmap++ = destbitval;
4731  destbitmask = 1;
4732  if (nitems > 0)
4733  destbitval = *destbitmap;
4734  }
4735  }
4736  if (destbitmask != 1)
4737  *destbitmap = destbitval;
4738  }
4739 }
#define Assert(condition)
Definition: c.h:681
bool array_contains_nulls ( ArrayType array)

Definition at line 3516 of file arrayfuncs.c.

References ARR_DIMS, ARR_HASNULL, ARR_NDIM, ARR_NULLBITMAP, and ArrayGetNItems().

Referenced by _arrq_cons(), _lca(), _lt_q_regex(), _ltree_compress(), array_fill_internal(), array_iterator(), array_position_common(), array_positions(), ArrayGetIntegerTypmods(), arrq_cons(), cube_a_f8(), cube_a_f8_f8(), cube_subset(), get_jsonb_path_all(), get_path_all(), getWeights(), lt_q_regex(), pg_isolation_test_session_is_blocked(), pg_logical_slot_get_changes_guts(), and width_bucket_array().

3517 {
3518  int nelems;
3519  bits8 *bitmap;
3520  int bitmask;
3521 
3522  /* Easy answer if there's no null bitmap */
3523  if (!ARR_HASNULL(array))
3524  return false;
3525 
3526  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3527 
3528  bitmap = ARR_NULLBITMAP(array);
3529 
3530  /* check whole bytes of the bitmap byte-at-a-time */
3531  while (nelems >= 8)
3532  {
3533  if (*bitmap != 0xFF)
3534  return true;
3535  bitmap++;
3536  nelems -= 8;
3537  }
3538 
3539  /* check last partial byte */
3540  bitmask = 1;
3541  while (nelems > 0)
3542  {
3543  if ((*bitmap & bitmask) == 0)
3544  return true;
3545  bitmask <<= 1;
3546  nelems--;
3547  }
3548 
3549  return false;
3550 }
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_HASNULL(a)
Definition: array.h:276
uint8 bits8
Definition: c.h:265
#define ARR_NDIM(a)
Definition: array.h:275
#define ARR_NULLBITMAP(a)
Definition: array.h:285
ArrayIterator array_create_iterator ( ArrayType arr,
int  slice_ndim,
ArrayMetaState mstate 
)

Definition at line 4307 of file arrayfuncs.c.

References ArrayIteratorData::arr, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), Assert, ArrayIteratorData::current_item, ArrayIteratorData::data_ptr, ArrayMetaState::element_type, elog, ERROR, get_typlenbyvalalign(), ArrayIteratorData::nitems, ArrayIteratorData::nullbitmap, palloc(), palloc0(), PointerIsValid, ArrayIteratorData::slice_dims, ArrayIteratorData::slice_lbound, ArrayIteratorData::slice_len, ArrayIteratorData::slice_ndim, ArrayIteratorData::slice_nulls, ArrayIteratorData::slice_values, ArrayIteratorData::typalign, ArrayMetaState::typalign, ArrayIteratorData::typbyval, ArrayMetaState::typbyval, ArrayIteratorData::typlen, and ArrayMetaState::typlen.

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

4308 {
4309  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4310 
4311  /*
4312  * Sanity-check inputs --- caller should have got this right already
4313  */
4314  Assert(PointerIsValid(arr));
4315  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4316  elog(ERROR, "invalid arguments to array_create_iterator");
4317 
4318  /*
4319  * Remember basic info about the array and its element type
4320  */
4321  iterator->arr = arr;
4322  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4323  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4324 
4325  if (mstate != NULL)
4326  {
4327  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4328 
4329  iterator->typlen = mstate->typlen;
4330  iterator->typbyval = mstate->typbyval;
4331  iterator->typalign = mstate->typalign;
4332  }
4333  else
4335  &iterator->typlen,
4336  &iterator->typbyval,
4337  &iterator->typalign);
4338 
4339  /*
4340  * Remember the slicing parameters.
4341  */
4342  iterator->slice_ndim = slice_ndim;
4343 
4344  if (slice_ndim > 0)
4345  {
4346  /*
4347  * Get pointers into the array's dims and lbound arrays to represent
4348  * the dims/lbound arrays of a slice. These are the same as the
4349  * rightmost N dimensions of the array.
4350  */
4351  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4352  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4353 
4354  /*
4355  * Compute number of elements in a slice.
4356  */
4357  iterator->slice_len = ArrayGetNItems(slice_ndim,
4358  iterator->slice_dims);
4359 
4360  /*
4361  * Create workspace for building sub-arrays.
4362  */
4363  iterator->slice_values = (Datum *)
4364  palloc(iterator->slice_len * sizeof(Datum));
4365  iterator->slice_nulls = (bool *)
4366  palloc(iterator->slice_len * sizeof(bool));
4367  }
4368 
4369  /*
4370  * Initialize our data pointer and linear element number. These will
4371  * advance through the array during array_iterate().
4372  */
4373  iterator->data_ptr = ARR_DATA_PTR(arr);
4374  iterator->current_item = 0;
4375 
4376  return iterator;
4377 }
bits8 * nullbitmap
Definition: arrayfuncs.c:71
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2021
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_LBOUND(a)
Definition: array.h:281
bool typbyval
Definition: array.h:225
bool * slice_nulls
Definition: arrayfuncs.c:83
#define ERROR
Definition: elog.h:43
Datum * slice_values
Definition: arrayfuncs.c:82
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
int16 typlen
Definition: array.h:224
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:681
#define ARR_NDIM(a)
Definition: array.h:275
char typalign
Definition: array.h:226
void * palloc(Size size)
Definition: mcxt.c:848
Oid element_type
Definition: array.h:223
#define elog
Definition: elog.h:219
#define PointerIsValid(pointer)
Definition: c.h:520
#define ARR_ELEMTYPE(a)
Definition: array.h:277
#define ARR_NULLBITMAP(a)
Definition: array.h:285
ArrayType * arr
Definition: arrayfuncs.c:70
void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4469 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4470 {
4471  if (iterator->slice_ndim > 0)
4472  {
4473  pfree(iterator->slice_values);
4474  pfree(iterator->slice_nulls);
4475  }
4476  pfree(iterator);
4477 }
bool * slice_nulls
Definition: arrayfuncs.c:83
void pfree(void *pointer)
Definition: mcxt.c:949
Datum * slice_values
Definition: arrayfuncs.c:82
Datum array_get_element ( Datum  arraydatum,
int  nSubscripts,
int *  indx,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign,
bool isNull 
)

Definition at line 1807 of file arrayfuncs.c.

References ARR_DATA_PTR, ARR_DIMS, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, array_get_element_expanded(), array_get_isnull(), array_seek(), ArrayCast(), ArrayGetOffset(), DatumGetArrayTypeP, DatumGetPointer, i, MAXDIM, and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by array_ref(), ExecEvalArrayRefFetch(), and ExecEvalArrayRefOld().

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

Definition at line 2016 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, palloc0(), PointerGetDatum, and SET_VARSIZE.

Referenced by ExecEvalArrayRefFetch(), and ExecEvalArrayRefOld().

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

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

4387 {
4388  /* Done if we have reached the end of the array */
4389  if (iterator->current_item >= iterator->nitems)
4390  return false;
4391 
4392  if (iterator->slice_ndim == 0)
4393  {
4394  /*
4395  * Scalar case: return one element.
4396  */
4397  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4398  {
4399  *isnull = true;
4400  *value = (Datum) 0;
4401  }
4402  else
4403  {
4404  /* non-NULL, so fetch the individual Datum to return */
4405  char *p = iterator->data_ptr;
4406 
4407  *isnull = false;
4408  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4409 
4410  /* Move our data pointer forward to the next element */
4411  p = att_addlength_pointer(p, iterator->typlen, p);
4412  p = (char *) att_align_nominal(p, iterator->typalign);
4413  iterator->data_ptr = p;
4414  }
4415  }
4416  else
4417  {
4418  /*
4419  * Slice case: build and return an array of the requested size.
4420  */
4421  ArrayType *result;
4422  Datum *values = iterator->slice_values;
4423  bool *nulls = iterator->slice_nulls;
4424  char *p = iterator->data_ptr;
4425  int i;
4426 
4427  for (i = 0; i < iterator->slice_len; i++)
4428  {
4429  if (array_get_isnull(iterator->nullbitmap,
4430  iterator->current_item++))
4431  {
4432  nulls[i] = true;
4433  values[i] = (Datum) 0;
4434  }
4435  else
4436  {
4437  nulls[i] = false;
4438  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4439 
4440  /* Move our data pointer forward to the next element */
4441  p = att_addlength_pointer(p, iterator->typlen, p);
4442  p = (char *) att_align_nominal(p, iterator->typalign);
4443  }
4444  }
4445 
4446  iterator->data_ptr = p;
4447 
4448  result = construct_md_array(values,
4449  nulls,
4450  iterator->slice_ndim,
4451  iterator->slice_dims,
4452  iterator->slice_lbound,
4453  ARR_ELEMTYPE(iterator->arr),
4454  iterator->typlen,
4455  iterator->typbyval,
4456  iterator->typalign);
4457 
4458  *isnull = false;
4459  *value = PointerGetDatum(result);
4460  }
4461 
4462  return true;
4463 }
bits8 * nullbitmap
Definition: arrayfuncs.c:71
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define PointerGetDatum(X)
Definition: postgres.h:562
bool * slice_nulls
Definition: arrayfuncs.c:83
Datum * slice_values
Definition: arrayfuncs.c:82
static struct @121 value
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
uintptr_t Datum
Definition: postgres.h:372
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4491
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#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:3314
#define ARR_ELEMTYPE(a)
Definition: array.h:277
ArrayType * arr
Definition: arrayfuncs.c:70
Datum array_map ( Datum  arrayd,
struct ExprState exprstate,
struct ExprContext econtext,
Oid  retType,
ArrayMapState amstate 
)

Definition at line 3119 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_LBOUND, AARR_NDIM, AllocSizeIsValid, ARR_DIMS, ARR_LBOUND, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_iter_next(), array_iter_setup(), ArrayGetNItems(), att_addlength_datum, att_align_nominal, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, DatumGetAnyArrayP(), ArrayMetaState::element_type, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, ExecEvalExpr(), get_typlenbyvalalign(), i, ExprState::innermost_casenull, ExprState::innermost_caseval, ArrayMapState::inp_extra, MaxAllocSize, ArrayType::ndim, palloc(), palloc0(), pfree(), PG_DETOAST_DATUM, PointerGetDatum, ArrayMapState::ret_extra, SET_VARSIZE, ArrayMetaState::typalign, ArrayMetaState::typbyval, ArrayMetaState::typlen, and values.

Referenced by ExecEvalArrayCoerce().

3122 {
3123  AnyArrayType *v = DatumGetAnyArrayP(arrayd);
3124  ArrayType *result;
3125  Datum *values;
3126  bool *nulls;
3127  int *dim;
3128  int ndim;
3129  int nitems;
3130  int i;
3131  int32 nbytes = 0;
3132  int32 dataoffset;
3133  bool hasnulls;
3134  Oid inpType;
3135  int inp_typlen;
3136  bool inp_typbyval;
3137  char inp_typalign;
3138  int typlen;
3139  bool typbyval;
3140  char typalign;
3141  array_iter iter;
3142  ArrayMetaState *inp_extra;
3143  ArrayMetaState *ret_extra;
3144  Datum *transform_source = exprstate->innermost_caseval;
3145  bool *transform_source_isnull = exprstate->innermost_casenull;
3146 
3147  inpType = AARR_ELEMTYPE(v);
3148  ndim = AARR_NDIM(v);
3149  dim = AARR_DIMS(v);
3150  nitems = ArrayGetNItems(ndim, dim);
3151 
3152  /* Check for empty array */
3153  if (nitems <= 0)
3154  {
3155  /* Return empty array */
3156  return PointerGetDatum(construct_empty_array(retType));
3157  }
3158 
3159  /*
3160  * We arrange to look up info about input and return element types only
3161  * once per series of calls, assuming the element type doesn't change
3162  * underneath us.
3163  */
3164  inp_extra = &amstate->inp_extra;
3165  ret_extra = &amstate->ret_extra;
3166 
3167  if (inp_extra->element_type != inpType)
3168  {
3169  get_typlenbyvalalign(inpType,
3170  &inp_extra->typlen,
3171  &inp_extra->typbyval,
3172  &inp_extra->typalign);
3173  inp_extra->element_type = inpType;
3174  }
3175  inp_typlen = inp_extra->typlen;
3176  inp_typbyval = inp_extra->typbyval;
3177  inp_typalign = inp_extra->typalign;
3178 
3179  if (ret_extra->element_type != retType)
3180  {
3181  get_typlenbyvalalign(retType,
3182  &ret_extra->typlen,
3183  &ret_extra->typbyval,
3184  &ret_extra->typalign);
3185  ret_extra->element_type = retType;
3186  }
3187  typlen = ret_extra->typlen;
3188  typbyval = ret_extra->typbyval;
3189  typalign = ret_extra->typalign;
3190 
3191  /* Allocate temporary arrays for new values */
3192  values = (Datum *) palloc(nitems * sizeof(Datum));
3193  nulls = (bool *) palloc(nitems * sizeof(bool));
3194 
3195  /* Loop over source data */
3196  array_iter_setup(&iter, v);
3197  hasnulls = false;
3198 
3199  for (i = 0; i < nitems; i++)
3200  {
3201  /* Get source element, checking for NULL */
3202  *transform_source =
3203  array_iter_next(&iter, transform_source_isnull, i,
3204  inp_typlen, inp_typbyval, inp_typalign);
3205 
3206  /* Apply the given expression to source element */
3207  values[i] = ExecEvalExpr(exprstate, econtext, &nulls[i]);
3208 
3209  if (nulls[i])
3210  hasnulls = true;
3211  else
3212  {
3213  /* Ensure data is not toasted */
3214  if (typlen == -1)
3215  values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
3216  /* Update total result size */
3217  nbytes = att_addlength_datum(nbytes, typlen, values[i]);
3218  nbytes = att_align_nominal(nbytes, typalign);
3219  /* check for overflow of total request */
3220  if (!AllocSizeIsValid(nbytes))
3221  ereport(ERROR,
3222  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3223  errmsg("array size exceeds the maximum allowed (%d)",
3224  (int) MaxAllocSize)));
3225  }
3226  }
3227 
3228  /* Allocate and fill the result array */
3229  if (hasnulls)
3230  {
3231  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3232  nbytes += dataoffset;
3233  }
3234  else
3235  {
3236  dataoffset = 0; /* marker for no null bitmap */
3237  nbytes += ARR_OVERHEAD_NONULLS(ndim);
3238  }
3239  result = (ArrayType *) palloc0(nbytes);
3240  SET_VARSIZE(result, nbytes);
3241  result->ndim = ndim;
3242  result->dataoffset = dataoffset;
3243  result->elemtype = retType;
3244  memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
3245  memcpy(ARR_LBOUND(result), AARR_LBOUND(v), ndim * sizeof(int));
3246 
3247  CopyArrayEls(result,
3248  values, nulls, nitems,
3249  typlen, typbyval, typalign,
3250  false);
3251 
3252  /*
3253  * Note: do not risk trying to pfree the results of the called expression
3254  */
3255  pfree(values);
3256  pfree(nulls);
3257 
3258  return PointerGetDatum(result);
3259 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#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:2021
#define PointerGetDatum(X)
Definition: postgres.h:562
bool * innermost_casenull
Definition: execnodes.h:93
int32 dataoffset
Definition: array.h:84
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3398
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:297
signed int int32
Definition: c.h:246
AnyArrayType * DatumGetAnyArrayP(Datum d)
#define ARR_LBOUND(a)
Definition: array.h:281
bool typbyval
Definition: array.h:225
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:279
ArrayMetaState inp_extra
Definition: array.h:238
int16 typlen
Definition: array.h:224
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:286
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
Datum * innermost_caseval
Definition: execnodes.h:92
#define ereport(elevel, rest)
Definition: elog.h:122
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
#define AARR_DIMS(a)
Definition: array.h:321
#define AARR_ELEMTYPE(a)
Definition: array.h:319
#define AARR_LBOUND(a)
Definition: array.h:323
#define AARR_NDIM(a)
Definition: array.h:313
ArrayMetaState ret_extra
Definition: array.h:239
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:957
char typalign
Definition: array.h:226
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
Oid element_type
Definition: array.h:223
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:205
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
int ndim
Definition: array.h:83
Datum array_ref ( ArrayType array,
int  nSubscripts,
int *  indx,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign,
bool isNull 
)

Definition at line 3064 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3067 {
3068  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3069  arraytyplen, elmlen, elmbyval, elmalign,
3070  isNull);
3071 }
#define PointerGetDatum(X)
Definition: postgres.h:562
Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1807
ArrayType* array_set ( ArrayType array,
int  nSubscripts,
int *  indx,
Datum  dataValue,
bool  isNull,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 3081 of file arrayfuncs.c.

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3084 {
3086  nSubscripts, indx,
3087  dataValue, isNull,
3088  arraytyplen,
3089  elmlen, elmbyval, elmalign));
3090 }
#define PointerGetDatum(X)
Definition: postgres.h:562
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:2187
#define DatumGetArrayTypeP(X)
Definition: array.h:246
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 2187 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 ExecEvalArrayRefAssign().

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

Definition at line 2747 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(), errdetail(), errmsg(), ERROR, i, Max, MAXDIM, mda_get_range(), MemSet, Min, ArrayType::ndim, palloc0(), PointerGetDatum, and SET_VARSIZE.

Referenced by ExecEvalArrayRefAssign().

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

Definition at line 200 of file arrayutils.c.

References ARR_ELEMTYPE, ARR_NDIM, array_contains_nulls(), CSTRINGOID, DatumGetCString, deconstruct_array(), ereport, errcode(), errmsg(), ERROR, i, palloc(), pfree(), and pg_atoi().

Referenced by anybit_typmodin(), anychar_typmodin(), anytime_typmodin(), anytimestamp_typmodin(), intervaltypmodin(), and numerictypmodin().

201 {
202  int32 *result;
203  Datum *elem_values;
204  int i;
205 
206  if (ARR_ELEMTYPE(arr) != CSTRINGOID)
207  ereport(ERROR,
208  (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
209  errmsg("typmod array must be type cstring[]")));
210 
211  if (ARR_NDIM(arr) != 1)
212  ereport(ERROR,
213  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
214  errmsg("typmod array must be one-dimensional")));
215 
216  if (array_contains_nulls(arr))
217  ereport(ERROR,
218  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
219  errmsg("typmod array must not contain nulls")));
220 
221  /* hardwired knowledge about cstring's representation details here */
223  -2, false, 'c',
224  &elem_values, NULL, n);
225 
226  result = (int32 *) palloc(*n * sizeof(int32));
227 
228  for (i = 0; i < *n; i++)
229  result[i] = pg_atoi(DatumGetCString(elem_values[i]),
230  sizeof(int32), '\0');
231 
232  pfree(elem_values);
233 
234  return result;
235 }
int errcode(int sqlerrcode)
Definition: elog.c:575
signed int int32
Definition: c.h:246
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:572
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
#define CSTRINGOID
Definition: pg_type.h:684
#define ARR_NDIM(a)
Definition: array.h:275
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3516
#define ARR_ELEMTYPE(a)
Definition: array.h:277
int32 pg_atoi(const char *s, int size, int c)
Definition: numutils.c:37
int ArrayGetNItems ( int  ndim,
const int *  dims 
)

Definition at line 75 of file arrayutils.c.

References Assert, ereport, errcode(), errmsg(), ERROR, i, and MaxArraySize.

Referenced by _arrq_cons(), _lca(), _lt_q_regex(), _ltree_compress(), accumArrayResultArr(), array_cardinality(), array_cat(), array_cmp(), array_contain_compare(), array_contains_nulls(), array_create_iterator(), array_eq(), array_fill_internal(), array_get_slice(), array_in(), array_insert_slice(), array_iterator(), array_map(), array_out(), array_recv(), array_replace_internal(), array_send(), array_set_element(), array_set_slice(), array_slice_size(), array_to_json_internal(), array_to_jsonb_internal(), array_to_text_internal(), array_unnest(), arrq_cons(), construct_md_array(), count_nulls(), deconstruct_array(), EA_get_flat_size(), estimate_array_length(), ExecEvalArrayExpr(), ExecEvalScalarArrayOp(), get_text_array_contents(), getWeights(), hash_array(), hash_array_extended(), is_strict_saop(), lt_q_regex(), pg_isolation_test_session_is_blocked(), predicate_classify(), width_bucket_array_fixed(), width_bucket_array_float8(), and width_bucket_array_variable().

76 {
77  int32 ret;
78  int i;
79 
80 #define MaxArraySize ((Size) (MaxAllocSize / sizeof(Datum)))
81 
82  if (ndim <= 0)
83  return 0;
84  ret = 1;
85  for (i = 0; i < ndim; i++)
86  {
87  int64 prod;
88 
89  /* A negative dimension implies that UB-LB overflowed ... */
90  if (dims[i] < 0)
91  ereport(ERROR,
92  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
93  errmsg("array size exceeds the maximum allowed (%d)",
94  (int) MaxArraySize)));
95 
96  prod = (int64) ret * (int64) dims[i];
97 
98  ret = (int32) prod;
99  if ((int64) ret != prod)
100  ereport(ERROR,
101  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
102  errmsg("array size exceeds the maximum allowed (%d)",
103  (int) MaxArraySize)));
104  }
105  Assert(ret >= 0);
106  if ((Size) ret > MaxArraySize)
107  ereport(ERROR,
108  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
109  errmsg("array size exceeds the maximum allowed (%d)",
110  (int) MaxArraySize)));
111  return (int) ret;
112 }
#define MaxArraySize
int errcode(int sqlerrcode)
Definition: elog.c:575
signed int int32
Definition: c.h:246
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define Assert(condition)
Definition: c.h:681
size_t Size
Definition: c.h:350
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
int ArrayGetOffset ( int  n,
const int *  dim,
const int *  lb,
const int *  indx 
)

Definition at line 31 of file arrayutils.c.

References i, and scale.

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

32 {
33  int i,
34  scale = 1,
35  offset = 0;
36 
37  for (i = n - 1; i >= 0; i--)
38  {
39  offset += (indx[i] - lb[i]) * scale;
40  scale *= dim[i];
41  }
42  return offset;
43 }
int scale
Definition: pgbench.c:106
int i
int ArrayGetOffset0 ( int  n,
const int *  tup,
const int *  scale 
)

Definition at line 50 of file arrayutils.c.

References i.

Referenced by ReadArrayStr().

51 {
52  int i,
53  lin = 0;
54 
55  for (i = 0; i < n; i++)
56  lin += tup[i] * scale[i];
57  return lin;
58 }
int scale
Definition: pgbench.c:106
int i
ArrayType* construct_array ( Datum elems,
int  nelems,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign 
)
ExpandedArrayHeader* construct_empty_expanded_array ( Oid  element_type,
MemoryContext  parentcontext,
ArrayMetaState metacache 
)

Definition at line 3415 of file arrayfuncs.c.

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

Referenced by fetch_array_arg_replace_nulls().

3418 {
3419  ArrayType *array = construct_empty_array(element_type);
3420  Datum d;
3421 
3422  d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3423  pfree(array);
3424  return (ExpandedArrayHeader *) DatumGetEOHP(d);
3425 }
#define PointerGetDatum(X)
Definition: postgres.h:562
Datum expand_array(Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3398
void pfree(void *pointer)
Definition: mcxt.c:949
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
uintptr_t Datum
Definition: postgres.h:372
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 3314 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_match_result(), construct_array(), ExecEvalArrayExpr(), hstore_avals(), hstore_slice_to_array(), hstore_to_array_internal(), makeMdArrayResult(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), plpgsql_exec_trigger(), PLySequence_ToArray(), and text_to_array_internal().

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

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

965 {
966  char *p = ARR_DATA_PTR(array);
967  bits8 *bitmap = ARR_NULLBITMAP(array);
968  int bitval = 0;
969  int bitmask = 1;
970  int i;
971 
972  if (typbyval)
973  freedata = false;
974 
975  for (i = 0; i < nitems; i++)
976  {
977  if (nulls && nulls[i])
978  {
979  if (!bitmap) /* shouldn't happen */
980  elog(ERROR, "null array element where not supported");
981  /* bitmap bit stays 0 */
982  }
983  else
984  {
985  bitval |= bitmask;
986  p += ArrayCastAndSet(values[i], typlen, typbyval, typalign, p);
987  if (freedata)
989  }
990  if (bitmap)
991  {
992  bitmask <<= 1;
993  if (bitmask == 0x100)
994  {
995  *bitmap++ = bitval;
996  bitval = 0;
997  bitmask = 1;
998  }
999  }
1000  }
1001 
1002  if (bitmap && bitmask != 1)
1003  *bitmap = bitval;
1004 }
static int ArrayCastAndSet(Datum src, int typlen, bool typbyval, char typalign, char *dest)
Definition: arrayfuncs.c:4537
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
uint8 bits8
Definition: c.h:265
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int i
#define elog
Definition: elog.h:219
#define ARR_NULLBITMAP(a)
Definition: array.h:285
AnyArrayType* DatumGetAnyArrayP ( Datum  d)

Definition at line 401 of file array_expanded.c.

References Assert, DatumGetEOHP(), DatumGetPointer, EA_MAGIC, ExpandedArrayHeader::ea_magic, PG_DETOAST_DATUM, and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by array_map().

402 {
403  ExpandedArrayHeader *eah;
404 
405  /*
406  * If it's an expanded array (RW or RO), return the header pointer.
407  */
409  {
410  eah = (ExpandedArrayHeader *) DatumGetEOHP(d);
411  Assert(eah->ea_magic == EA_MAGIC);
412  return (AnyArrayType *) eah;
413  }
414 
415  /* Else do regular detoasting as needed */
416  return (AnyArrayType *) PG_DETOAST_DATUM(d);
417 }
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:323
#define EA_MAGIC
Definition: array.h:101
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:681
#define DatumGetPointer(X)
Definition: postgres.h:555
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:205
ExpandedArrayHeader* DatumGetExpandedArray ( Datum  d)

Definition at line 352 of file array_expanded.c.

References Assert, CurrentMemoryContext, DatumGetEOHP(), DatumGetPointer, EA_MAGIC, ExpandedArrayHeader::ea_magic, expand_array(), and VARATT_IS_EXTERNAL_EXPANDED_RW.

Referenced by array_set_element_expanded().

353 {
354  /* If it's a writable expanded array already, just return it */
356  {
358 
359  Assert(eah->ea_magic == EA_MAGIC);
360  return eah;
361  }
362 
363  /* Else expand the hard way */
364  d = expand_array(d, CurrentMemoryContext, NULL);
365  return (ExpandedArrayHeader *) DatumGetEOHP(d);
366 }
Datum expand_array(Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
#define EA_MAGIC
Definition: array.h:101
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:681
#define DatumGetPointer(X)
Definition: postgres.h:555
#define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR)
Definition: postgres.h:321
ExpandedArrayHeader* DatumGetExpandedArrayX ( Datum  d,
ArrayMetaState metacache 
)

Definition at line 372 of file array_expanded.c.

References Assert, CurrentMemoryContext, DatumGetEOHP(), DatumGetPointer, EA_MAGIC, ExpandedArrayHeader::ea_magic, ExpandedArrayHeader::element_type, ArrayMetaState::element_type, expand_array(), ExpandedArrayHeader::typalign, ArrayMetaState::typalign, ExpandedArrayHeader::typbyval, ArrayMetaState::typbyval, ExpandedArrayHeader::typlen, ArrayMetaState::typlen, and VARATT_IS_EXTERNAL_EXPANDED_RW.

373 {
374  /* If it's a writable expanded array already, just return it */
376  {
378 
379  Assert(eah->ea_magic == EA_MAGIC);
380  /* Update cache if provided */
381  if (metacache)
382  {
383  metacache->element_type = eah->element_type;
384  metacache->typlen = eah->typlen;
385  metacache->typbyval = eah->typbyval;
386  metacache->typalign = eah->typalign;
387  }
388  return eah;
389  }
390 
391  /* Else expand using caller's cache if any */
392  d = expand_array(d, CurrentMemoryContext, metacache);
393  return (ExpandedArrayHeader *) DatumGetEOHP(d);
394 }
Datum expand_array(Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
#define EA_MAGIC
Definition: array.h:101
bool typbyval
Definition: array.h:225
int16 typlen
Definition: array.h:224
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:681
#define DatumGetPointer(X)
Definition: postgres.h:555
char typalign
Definition: array.h:226
Oid element_type
Definition: array.h:223
#define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR)
Definition: postgres.h:321
void deconstruct_array ( ArrayType array,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign,
Datum **  elemsp,
bool **  nullsp,
int *  nelemsp 
)

Definition at line 3449 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, palloc(), and palloc0().

Referenced by _bt_preprocess_array_keys(), array_contain_compare(), array_set_slice(), array_to_json_internal(), array_to_jsonb_internal(), array_to_tsvector(), 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(), flatten_reloptions(), 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(), interval_combine(), json_object(), json_object_two_arg(), jsonb_delete_array(), jsonb_delete_path(), jsonb_exists_all(), jsonb_exists_any(), jsonb_insert(), 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_stringlist(), textarray_to_strvaluelist(), TidListEval(), transformRelOptions(), tsvector_delete_arr(), tsvector_filter(), tsvector_setweight_by_filter(), and untransformRelOptions().

3453 {
3454  Datum *elems;
3455  bool *nulls;
3456  int nelems;
3457  char *p;
3458  bits8 *bitmap;
3459  int bitmask;
3460  int i;
3461 
3462  Assert(ARR_ELEMTYPE(array) == elmtype);
3463 
3464  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3465  *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
3466  if (nullsp)
3467  *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
3468  else
3469  nulls = NULL;
3470  *nelemsp = nelems;
3471 
3472  p = ARR_DATA_PTR(array);
3473  bitmap = ARR_NULLBITMAP(array);
3474  bitmask = 1;
3475 
3476  for (i = 0; i < nelems; i++)
3477  {
3478  /* Get source element, checking for NULL */
3479  if (bitmap && (*bitmap & bitmask) == 0)
3480  {
3481  elems[i] = (Datum) 0;
3482  if (nulls)
3483  nulls[i] = true;
3484  else
3485  ereport(ERROR,
3486  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3487  errmsg("null array element not allowed in this context")));
3488  }
3489  else
3490  {
3491  elems[i] = fetch_att(p, elmbyval, elmlen);
3492  p = att_addlength_pointer(p, elmlen, p);
3493  p = (char *) att_align_nominal(p, elmalign);
3494  }
3495 
3496  /* advance bitmap pointer if any */
3497  if (bitmap)
3498  {
3499  bitmask <<= 1;
3500  if (bitmask == 0x100)
3501  {
3502  bitmap++;
3503  bitmask = 1;
3504  }
3505  }
3506  }
3507 }
#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:575
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
#define ereport(elevel, rest)
Definition: elog.h:122
uint8 bits8
Definition: c.h:265
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:681
#define ARR_NDIM(a)
Definition: array.h:275
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
int i
#define ARR_ELEMTYPE(a)
Definition: array.h:277
#define ARR_NULLBITMAP(a)
Definition: array.h:285
void deconstruct_expanded_array ( ExpandedArrayHeader eah)

Definition at line 424 of file array_expanded.c.

References ARR_HASNULL, deconstruct_array(), ExpandedArrayHeader::dnulls, ExpandedArrayHeader::dvalues, ExpandedArrayHeader::dvalueslen, ExpandedArrayHeader::element_type, ExpandedObjectHeader::eoh_context, ExpandedArrayHeader::fvalue, ExpandedArrayHeader::hdr, MemoryContextSwitchTo(), ExpandedArrayHeader::nelems, ExpandedArrayHeader::typalign, ExpandedArrayHeader::typbyval, and ExpandedArrayHeader::typlen.

Referenced by array_contain_compare(), array_get_element_expanded(), and array_set_element_expanded().

425 {
426  if (eah->dvalues == NULL)
427  {
429  Datum *dvalues;
430  bool *dnulls;
431  int nelems;
432 
433  dnulls = NULL;
435  eah->element_type,
436  eah->typlen, eah->typbyval, eah->typalign,
437  &dvalues,
438  ARR_HASNULL(eah->fvalue) ? &dnulls : NULL,
439  &nelems);
440 
441  /*
442  * Update header only after successful completion of this step. If
443  * deconstruct_array fails partway through, worst consequence is some
444  * leaked memory in the object's context. If the caller fails at a
445  * later point, that's fine, since the deconstructed representation is
446  * valid anyhow.
447  */
448  eah->dvalues = dvalues;
449  eah->dnulls = dnulls;
450  eah->dvalueslen = eah->nelems = nelems;
451  MemoryContextSwitchTo(oldcxt);
452  }
453 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Datum * dvalues
Definition: array.h:134
ExpandedObjectHeader hdr
Definition: array.h:106
#define ARR_HASNULL(a)
Definition: array.h:276
ArrayType * fvalue
Definition: array.h:153
uintptr_t Datum
Definition: postgres.h:372
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
MemoryContext eoh_context
Datum expand_array ( Datum  arraydatum,
MemoryContext  parentcontext,
ArrayMetaState metacache 
)

Definition at line 50 of file array_expanded.c.

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate(), ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, ARR_SIZE, Assert, copy_byval_expanded_array(), DatumGetArrayTypePCopy, DatumGetEOHP(), DatumGetPointer, ExpandedArrayHeader::dims, ExpandedArrayHeader::dnulls, ExpandedArrayHeader::dvalues, ExpandedArrayHeader::dvalueslen, EA_MAGIC, ExpandedArrayHeader::ea_magic, ExpandedArrayHeader::element_type, ArrayMetaState::element_type, EOH_init_header(), EOHPGetRWDatum, ExpandedArrayHeader::fendptr, ExpandedArrayHeader::flat_size, ExpandedArrayHeader::fstartptr, ExpandedArrayHeader::fvalue, get_typlenbyvalalign(), ExpandedArrayHeader::hdr, ExpandedArrayHeader::lbound, MemoryContextAlloc(), MemoryContextSwitchTo(), ExpandedArrayHeader::ndims, ExpandedArrayHeader::nelems, ExpandedArrayHeader::typalign, ArrayMetaState::typalign, ExpandedArrayHeader::typbyval, ArrayMetaState::typbyval, ExpandedArrayHeader::typlen, ArrayMetaState::typlen, and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by construct_empty_expanded_array(), DatumGetExpandedArray(), DatumGetExpandedArrayX(), exec_assign_value(), and plpgsql_exec_function().

52 {
53  ArrayType *array;
55  MemoryContext objcxt;
56  MemoryContext oldcxt;
57  ArrayMetaState fakecache;
58 
59  /*
60  * Allocate private context for expanded object. We start by assuming
61  * that the array won't be very large; but if it does grow a lot, don't
62  * constrain aset.c's large-context behavior.
63  */
64  objcxt = AllocSetContextCreate(parentcontext,
65  "expanded array",
67 
68  /* Set up expanded array header */
69  eah = (ExpandedArrayHeader *)
70  MemoryContextAlloc(objcxt, sizeof(ExpandedArrayHeader));
71 
72  EOH_init_header(&eah->hdr, &EA_methods, objcxt);
73  eah->ea_magic = EA_MAGIC;
74 
75  /* If the source is an expanded array, we may be able to optimize */
77  {
78  ExpandedArrayHeader *oldeah = (ExpandedArrayHeader *) DatumGetEOHP(arraydatum);
79 
80  Assert(oldeah->ea_magic == EA_MAGIC);
81 
82  /*
83  * Update caller's cache if provided; we don't need it this time, but
84  * next call might be for a non-expanded source array. Furthermore,
85  * if the caller didn't provide a cache area, use some local storage
86  * to cache anyway, thereby avoiding a catalog lookup in the case
87  * where we fall through to the flat-copy code path.
88  */
89  if (metacache == NULL)
90  metacache = &fakecache;
91  metacache->element_type = oldeah->element_type;
92  metacache->typlen = oldeah->typlen;
93  metacache->typbyval = oldeah->typbyval;
94  metacache->typalign = oldeah->typalign;
95 
96  /*
97  * If element type is pass-by-value and we have a Datum-array
98  * representation, just copy the source's metadata and Datum/isnull
99  * arrays. The original flat array, if present at all, adds no
100  * additional information so we need not copy it.
101  */
102  if (oldeah->typbyval && oldeah->dvalues != NULL)
103  {
104  copy_byval_expanded_array(eah, oldeah);
105  /* return a R/W pointer to the expanded array */
106  return EOHPGetRWDatum(&eah->hdr);
107  }
108 
109  /*
110  * Otherwise, either we have only a flat representation or the
111  * elements are pass-by-reference. In either case, the best thing
112  * seems to be to copy the source as a flat representation and then
113  * deconstruct that later if necessary. For the pass-by-ref case, we
114  * could perhaps save some cycles with custom code that generates the
115  * deconstructed representation in parallel with copying the values,
116  * but it would be a lot of extra code for fairly marginal gain. So,
117  * fall through into the flat-source code path.
118  */
119  }
120 
121  /*
122  * Detoast and copy source array into private context, as a flat array.
123  *
124  * Note that this coding risks leaking some memory in the private context
125  * if we have to fetch data from a TOAST table; however, experimentation
126  * says that the leak is minimal. Doing it this way saves a copy step,
127  * which seems worthwhile, especially if the array is large enough to need
128  * external storage.
129  */
130  oldcxt = MemoryContextSwitchTo(objcxt);
131  array = DatumGetArrayTypePCopy(arraydatum);
132  MemoryContextSwitchTo(oldcxt);
133 
134  eah->ndims = ARR_NDIM(array);
135  /* note these pointers point into the fvalue header! */
136  eah->dims = ARR_DIMS(array);
137  eah->lbound = ARR_LBOUND(array);
138 
139  /* Save array's element-type data for possible use later */
140  eah->element_type = ARR_ELEMTYPE(array);
141  if (metacache && metacache->element_type == eah->element_type)
142  {
143  /* We have a valid cache of representational data */
144  eah->typlen = metacache->typlen;
145  eah->typbyval = metacache->typbyval;
146  eah->typalign = metacache->typalign;
147  }
148  else
149  {
150  /* No, so look it up */
152  &eah->typlen,
153  &eah->typbyval,
154  &eah->typalign);
155  /* Update cache if provided */
156  if (metacache)
157  {
158  metacache->element_type = eah->element_type;
159  metacache->typlen = eah->typlen;
160  metacache->typbyval = eah->typbyval;
161  metacache->typalign = eah->typalign;
162  }
163  }
164 
165  /* we don't make a deconstructed representation now */
166  eah->dvalues = NULL;
167  eah->dnulls = NULL;
168  eah->dvalueslen = 0;
169  eah->nelems = 0;
170  eah->flat_size = 0;
171 
172  /* remember we have a flat representation */
173  eah->fvalue = array;
174  eah->fstartptr = ARR_DATA_PTR(array);
175  eah->fendptr = ((char *) array) + ARR_SIZE(array);
176 
177  /* return a R/W pointer to the expanded array */
178  return EOHPGetRWDatum(&eah->hdr);
179 }
static const ExpandedObjectMethods EA_methods
static void copy_byval_expanded_array(ExpandedArrayHeader *eah, ExpandedArrayHeader *oldeah)
#define ARR_SIZE(a)
Definition: array.h:274
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:323
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2021
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Datum * dvalues
Definition: array.h:134
char * fendptr
Definition: array.h:155
#define EA_MAGIC
Definition: array.h:101
#define ARR_LBOUND(a)
Definition: array.h:281
bool typbyval
Definition: array.h:225
ExpandedObjectHeader hdr
Definition: array.h:106
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
int16 typlen
Definition: array.h:224
void EOH_init_header(ExpandedObjectHeader *eohptr, const ExpandedObjectMethods *methods, MemoryContext obj_context)
Definition: expandeddatum.c:48
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
ArrayType * fvalue
Definition: array.h:153
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
#define DatumGetArrayTypePCopy(X)
Definition: array.h:247
#define Assert(condition)
Definition: c.h:681
#define ARR_NDIM(a)
Definition: array.h:275
#define DatumGetPointer(X)
Definition: postgres.h:555
char typalign
Definition: array.h:226
#define EOHPGetRWDatum(eohptr)
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
char * fstartptr
Definition: array.h:154
Oid element_type
Definition: array.h:223
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:182
#define ARR_ELEMTYPE(a)
Definition: array.h:277
ArrayBuildState* initArrayResult ( Oid  element_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 5003 of file arrayfuncs.c.

References ArrayBuildState::alen, ALLOCSET_DEFAULT_SIZES, 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(), populate_array(), tuple_data_split_internal(), and xpath().

5004 {
5005  ArrayBuildState *astate;
5006  MemoryContext arr_context = rcontext;
5007 
5008  /* Make a temporary context to hold all the junk */
5009  if (subcontext)
5010  arr_context = AllocSetContextCreate(rcontext,
5011  "accumArrayResult",
5013 
5014  astate = (ArrayBuildState *)
5015  MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
5016  astate->mcontext = arr_context;
5017  astate->private_cxt = subcontext;
5018  astate->alen = (subcontext ? 64 : 8); /* arbitrary starting array size */
5019  astate->dvalues = (Datum *)
5020  MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
5021  astate->dnulls = (bool *)
5022  MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
5023  astate->nelems = 0;
5024  astate->element_type = element_type;
5025  get_typlenbyvalalign(element_type,
5026  &astate->typlen,
5027  &astate->typbyval,
5028  &astate->typalign);
5029 
5030  return astate;
5031 }
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2021
Datum * dvalues
Definition: array.h:175
bool typbyval
Definition: array.h:181
Oid element_type
Definition: array.h:179
bool private_cxt
Definition: array.h:183
bool * dnulls
Definition: array.h:176
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
char typalign
Definition: array.h:182
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
MemoryContext mcontext
Definition: array.h:174
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
int16 typlen
Definition: array.h:180
ArrayBuildStateAny* initArrayResultAny ( Oid  input_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 5468 of file arrayfuncs.c.

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

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

5469 {
5470  ArrayBuildStateAny *astate;
5471  Oid element_type = get_element_type(input_type);
5472 
5473  if (OidIsValid(element_type))
5474  {
5475  /* Array case */
5476  ArrayBuildStateArr *arraystate;
5477 
5478  arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5479  astate = (ArrayBuildStateAny *)
5480  MemoryContextAlloc(arraystate->mcontext,
5481  sizeof(ArrayBuildStateAny));
5482  astate->scalarstate = NULL;
5483  astate->arraystate = arraystate;
5484  }
5485  else
5486  {
5487  /* Scalar case */
5488  ArrayBuildState *scalarstate;
5489 
5490  /* Let's just check that we have a type that can be put into arrays */
5491  Assert(OidIsValid(get_array_type(input_type)));
5492 
5493  scalarstate = initArrayResult(input_type, rcontext, subcontext);
5494  astate = (ArrayBuildStateAny *)
5495  MemoryContextAlloc(scalarstate->mcontext,
5496  sizeof(ArrayBuildStateAny));
5497  astate->scalarstate = scalarstate;
5498  astate->arraystate = NULL;
5499  }
5500 
5501  return astate;
5502 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5003
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2484
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2512
unsigned int Oid
Definition: postgres_ext.h:31
ArrayBuildState * scalarstate
Definition: array.h:214
#define OidIsValid(objectId)
Definition: c.h:532
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5190
ArrayBuildStateArr * arraystate
Definition: array.h:215
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:681
MemoryContext mcontext
Definition: array.h:174
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
MemoryContext mcontext
Definition: array.h:192
ArrayBuildStateArr* initArrayResultArr ( Oid  array_type,
Oid  element_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 5190 of file arrayfuncs.c.

References ALLOCSET_DEFAULT_SIZES, 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().

5192 {
5193  ArrayBuildStateArr *astate;
5194  MemoryContext arr_context = rcontext; /* by default use the parent ctx */
5195 
5196  /* Lookup element type, unless element_type already provided */
5197  if (!OidIsValid(element_type))
5198  {
5199  element_type = get_element_type(array_type);
5200 
5201  if (!OidIsValid(element_type))
5202  ereport(ERROR,
5203  (errcode(ERRCODE_DATATYPE_MISMATCH),
5204  errmsg("data type %s is not an array type",
5205  format_type_be(array_type))));
5206  }
5207 
5208  /* Make a temporary context to hold all the junk */
5209  if (subcontext)
5210  arr_context = AllocSetContextCreate(rcontext,
5211  "accumArrayResultArr",
5213 
5214  /* Note we initialize all fields to zero */
5215  astate = (ArrayBuildStateArr *)
5216  MemoryContextAllocZero(arr_context, sizeof(ArrayBuildStateArr));
5217  astate->mcontext = arr_context;
5218  astate->private_cxt = subcontext;
5219 
5220  /* Save relevant datatype information */
5221  astate->array_type = array_type;
5222  astate->element_type = element_type;
5223 
5224  return astate;
5225 }
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2484
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define OidIsValid(objectId)
Definition: c.h:532
#define ERROR
Definition: elog.h:43
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
#define ereport(elevel, rest)
Definition: elog.h:122
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool private_cxt
Definition: array.h:204
MemoryContext mcontext
Definition: array.h:192
Datum makeArrayResult ( ArrayBuildState astate,
MemoryContext  rcontext 
)

Definition at line 5106 of file arrayfuncs.c.

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

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

5108 {
5109  int ndims;
5110  int dims[1];
5111  int lbs[1];
5112 
5113  /* If no elements were presented, we want to create an empty array */
5114  ndims = (astate->nelems > 0) ? 1 : 0;
5115  dims[0] = astate->nelems;
5116  lbs[0] = 1;
5117 
5118  return makeMdArrayResult(astate, ndims, dims, lbs, rcontext,
5119  astate->private_cxt);
5120 }
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5138
bool private_cxt
Definition: array.h:183
Datum makeArrayResultAny ( ArrayBuildStateAny astate,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5541 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5543 {
5544  Datum result;
5545 
5546  if (astate->scalarstate)
5547  {
5548  /* Must use makeMdArrayResult to support "release" parameter */
5549  int ndims;
5550  int dims[1];
5551  int lbs[1];
5552 
5553  /* If no elements were presented, we want to create an empty array */
5554  ndims = (astate->scalarstate->nelems > 0) ? 1 : 0;
5555  dims[0] = astate->scalarstate->nelems;
5556  lbs[0] = 1;
5557 
5558  result = makeMdArrayResult(astate->scalarstate, ndims, dims, lbs,
5559  rcontext, release);
5560  }
5561  else
5562  {
5563  result = makeArrayResultArr(astate->arraystate,
5564  rcontext, release);
5565  }
5566  return result;
5567 }
Datum makeArrayResultArr(ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5393
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5138
ArrayBuildState * scalarstate
Definition: array.h:214
ArrayBuildStateArr * arraystate
Definition: array.h:215
uintptr_t Datum
Definition: postgres.h:372
Datum makeArrayResultArr ( ArrayBuildStateArr astate,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5393 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, ArrayBuildStateArr::nullbitmap, palloc0(), PointerGetDatum, ArrayBuildStateArr::private_cxt, and SET_VARSIZE.

Referenced by array_agg_array_finalfn(), and makeArrayResultAny().

5396 {
5397  ArrayType *result;
5398  MemoryContext oldcontext;
5399 
5400  /* Build the final array result in rcontext */
5401  oldcontext = MemoryContextSwitchTo(rcontext);
5402 
5403  if (astate->ndims == 0)
5404  {
5405  /* No inputs, return empty array */
5406  result = construct_empty_array(astate->element_type);
5407  }
5408  else
5409  {
5410  int dataoffset,
5411  nbytes;
5412 
5413  /* Compute required space */
5414  nbytes = astate->nbytes;
5415  if (astate->nullbitmap != NULL)
5416  {
5417  dataoffset = ARR_OVERHEAD_WITHNULLS(astate->ndims, astate->nitems);
5418  nbytes += dataoffset;
5419  }
5420  else
5421  {
5422  dataoffset = 0;
5423  nbytes += ARR_OVERHEAD_NONULLS(astate->ndims);
5424  }
5425 
5426  result = (ArrayType *) palloc0(nbytes);
5427  SET_VARSIZE(result, nbytes);
5428  result->ndim = astate->ndims;
5429  result->dataoffset = dataoffset;
5430  result->elemtype = astate->element_type;
5431 
5432  memcpy(ARR_DIMS(result), astate->dims, astate->ndims * sizeof(int));
5433  memcpy(ARR_LBOUND(result), astate->lbs, astate->ndims * sizeof(int));
5434  memcpy(ARR_DATA_PTR(result), astate->data, astate->nbytes);
5435 
5436  if (astate->nullbitmap != NULL)
5437  array_bitmap_copy(ARR_NULLBITMAP(result), 0,
5438  astate->nullbitmap, 0,
5439  astate->nitems);
5440  }
5441 
5442  MemoryContextSwitchTo(oldcontext);
5443 
5444  /* Clean up all the junk */
5445  if (release)
5446  {
5447  Assert(astate->private_cxt);
5448  MemoryContextDelete(astate->mcontext);
5449  }
5450 
5451  return PointerGetDatum(result);
5452 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define PointerGetDatum(X)
Definition: postgres.h:562
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4676
int32 dataoffset
Definition: array.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3398
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:297
#define ARR_LBOUND(a)
Definition: array.h:281
bits8 * nullbitmap
Definition: array.h:194
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
void * palloc0(Size size)
Definition: mcxt.c:877
int lbs[MAXDIM]
Definition: array.h:201
#define Assert(condition)
Definition: c.h:681
int dims[MAXDIM]
Definition: array.h:200
bool private_cxt
Definition: array.h:204
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
#define ARR_NULLBITMAP(a)
Definition: array.h:285
MemoryContext mcontext
Definition: array.h:192
int ndim
Definition: array.h:83
Datum makeMdArrayResult ( ArrayBuildState astate,
int  ndims,
int *  dims,
int *  lbs,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5138 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(), plperl_array_to_datum(), and populate_array().

5144 {
5145  ArrayType *result;
5146  MemoryContext oldcontext;
5147 
5148  /* Build the final array result in rcontext */
5149  oldcontext = MemoryContextSwitchTo(rcontext);
5150 
5151  result = construct_md_array(astate->dvalues,
5152  astate->dnulls,
5153  ndims,
5154  dims,
5155  lbs,
5156  astate->element_type,
5157  astate->typlen,
5158  astate->typbyval,
5159  astate->typalign);
5160 
5161  MemoryContextSwitchTo(oldcontext);
5162 
5163  /* Clean up all the junk */
5164  if (release)
5165  {
5166  Assert(astate->private_cxt);
5167  MemoryContextDelete(astate->mcontext);
5168  }
5169 
5170  return PointerGetDatum(result);
5171 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
#define PointerGetDatum(X)
Definition: postgres.h:562
Datum * dvalues
Definition: array.h:175
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:181
Oid element_type
Definition: array.h:179
bool private_cxt
Definition: array.h:183
bool * dnulls
Definition: array.h:176
char typalign
Definition: array.h:182
#define Assert(condition)
Definition: c.h:681
MemoryContext mcontext
Definition: array.h:174
int16 typlen
Definition: array.h:180
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:3314
void mda_get_offset_values ( int  n,
int *  dist,
const int *  prod,
const int *  span 
)

Definition at line 150 of file arrayutils.c.

References i.

Referenced by array_extract_slice(), array_insert_slice(), and array_slice_size().

151 {
152  int i,
153  j;
154 
155  dist[n - 1] = 0;
156  for (j = n - 2; j >= 0; j--)
157  {
158  dist[j] = prod[j] - 1;
159  for (i = j + 1; i < n; i++)
160  dist[j] -= (span[i] - 1) * prod[i];
161  }
162 }
int i
void mda_get_prod ( int  n,
const int *  range,
int *  prod 
)

Definition at line 134 of file arrayutils.c.

References i.

Referenced by array_extract_slice(), array_insert_slice(), array_slice_size(), and ReadArrayStr().

135 {
136  int i;
137 
138  prod[n - 1] = 1;
139  for (i = n - 2; i >= 0; i--)
140  prod[i] = prod[i + 1] * range[i + 1];
141 }
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:416
int i
void mda_get_range ( int  n,
int *  span,
const int *  st,
const int *  endp 
)

Definition at line 120 of file arrayutils.c.

References i.

Referenced by array_extract_slice(), array_get_slice(), array_insert_slice(), array_set_slice(), and array_slice_size().

121 {
122  int i;
123 
124  for (i = 0; i < n; i++)
125  span[i] = endp[i] - st[i] + 1;
126 }
int i
int mda_next_tuple ( int  n,
int *  curr,
const int *  span 
)

Definition at line 175 of file arrayutils.c.

References i.

Referenced by array_extract_slice(), array_insert_slice(), and array_slice_size().

176 {
177  int i;
178 
179  if (n <= 0)
180  return -1;
181 
182  curr[n - 1] = (curr[n - 1] + 1) % span[n - 1];
183  for (i = n - 1; i && curr[i] == 0; i--)
184  curr[i - 1] = (curr[i - 1] + 1) % span[i - 1];
185 
186  if (i)
187  return i;
188  if (curr[0])
189  return 0;
190 
191  return -1;
192 }
int i

Variable Documentation

bool Array_nulls

Definition at line 40 of file arrayfuncs.c.

Referenced by ReadArrayStr().