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(n)   DatumGetAnyArray(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 (FunctionCallInfo fcinfo, 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)
 
AnyArrayTypeDatumGetAnyArray (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:272
#define NULL
Definition: c.h:229
#define VARATT_IS_EXPANDED_HEADER(PTR)

Definition at line 311 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 275 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(), TQRemapArray(), TryReuseForeignKey(), width_bucket_array_fixed(), width_bucket_array_float8(), and width_bucket_array_variable().

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

Definition at line 273 of file array.h.

Referenced by _bt_preprocess_array_keys(), array_cat(), array_create_iterator(), array_get_slice(), array_iterate(), 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(), arrayconst_startup_fn(), ArrayGetIntegerTypmods(), build_function_result_tupdesc_d(), check_acl(), check_float8_array(), compute_array_stats(), DecodeTextArrayToCString(), deconstruct_array(), exec_stmt_foreach_a(), ExecEvalArrayCoerce(), ExecEvalArrayExpr(), ExecEvalScalarArrayOp(), ExecIndexEvalArrayKeys(), 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(), ginarrayextract(), gincost_scalararrayopexpr(), ginqueryarrayextract(), GUCArrayAdd(), hstore_from_array(), hstore_from_arrays(), int2vectorrecv(), map_sql_value_to_xml_value(), new_intArrayType(), oidvectorrecv(), 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(), ProcedureCreate(), ProcessGUCArray(), RelationGetExclusionInfo(), RelationGetFKeyList(), ri_LoadConstraintInfo(), scalararraysel(), text_format(), TQExamineArray(), TQRemapArray(), TryReuseForeignKey(), and width_bucket_array().

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

Definition at line 271 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(), TQRemapArray(), TryReuseForeignKey(), width_bucket_array(), width_bucket_array_fixed(), width_bucket_array_float8(), and width_bucket_array_variable().

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

Definition at line 244 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(), 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 249 of file array.h.

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

Definition at line 250 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 252 of file array.h.

Typedef Documentation

Definition at line 239 of file array.h.

Function Documentation

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

Definition at line 4990 of file arrayfuncs.c.

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

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

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

Definition at line 5461 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

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

Definition at line 5184 of file arrayfuncs.c.

References ArrayBuildStateArr::abytes, ArrayBuildStateArr::aitems, arg, ARR_DATA_OFFSET, ARR_DATA_PTR, ARR_DIMS, ARR_HASNULL, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_SIZE, array_bitmap_copy(), ArrayBuildStateArr::array_type, ArrayGetNItems(), Assert, ArrayBuildStateArr::data, DatumGetArrayTypeP, DatumGetPointer, ArrayBuildStateArr::dims, ereport, errcode(), errmsg(), ERROR, i, initArrayResultArr(), InvalidOid, ArrayBuildStateArr::lbs, Max, MAXDIM, ArrayBuildStateArr::mcontext, MemoryContextSwitchTo(), ArrayBuildStateArr::nbytes, ArrayBuildStateArr::ndims, ArrayBuildStateArr::nitems, NULL, ArrayBuildStateArr::nullbitmap, palloc(), pfree(), and repalloc().

Referenced by accumArrayResultAny(), and array_agg_array_transfn().

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

Definition at line 4624 of file arrayfuncs.c.

References Assert.

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

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

Definition at line 3542 of file arrayfuncs.c.

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

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

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

Definition at line 4255 of file arrayfuncs.c.

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

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

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

Definition at line 4417 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4418 {
4419  if (iterator->slice_ndim > 0)
4420  {
4421  pfree(iterator->slice_values);
4422  pfree(iterator->slice_nulls);
4423  }
4424  pfree(iterator);
4425 }
bool * slice_nulls
Definition: arrayfuncs.c:82
void pfree(void *pointer)
Definition: mcxt.c:950
Datum * slice_values
Definition: arrayfuncs.c:81
Datum array_get_element ( Datum  arraydatum,
int  nSubscripts,
int *  indx,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign,
bool isNull 
)

Definition at line 1806 of file arrayfuncs.c.

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

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

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

Definition at line 2015 of file arrayfuncs.c.

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

Referenced by ExecEvalArrayRefFetch(), and ExecEvalArrayRefOld().

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

Definition at line 4334 of file arrayfuncs.c.

References ArrayIteratorData::arr, ARR_ELEMTYPE, array_get_isnull(), att_addlength_pointer, att_align_nominal, construct_md_array(), ArrayIteratorData::current_item, ArrayIteratorData::data_ptr, fetch_att, i, ArrayIteratorData::nitems, ArrayIteratorData::nullbitmap, PointerGetDatum, result, ArrayIteratorData::slice_dims, ArrayIteratorData::slice_lbound, ArrayIteratorData::slice_len, ArrayIteratorData::slice_ndim, ArrayIteratorData::slice_nulls, ArrayIteratorData::slice_values, ArrayIteratorData::typalign, ArrayIteratorData::typbyval, ArrayIteratorData::typlen, and values.

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

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

Definition at line 3120 of file arrayfuncs.c.

References AARR_DIMS, AARR_ELEMTYPE, AARR_LBOUND, AARR_NDIM, AllocSizeIsValid, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, ARR_DIMS, ARR_LBOUND, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_iter_next(), array_iter_setup(), ArrayGetNItems(), att_addlength_datum, att_align_nominal, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, ArrayMetaState::element_type, ArrayType::elemtype, elog, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoData::flinfo, FmgrInfo::fn_strict, FunctionCallInvoke, get_typlenbyvalalign(), i, ArrayMapState::inp_extra, FunctionCallInfoData::isnull, MaxAllocSize, FunctionCallInfoData::nargs, ArrayType::ndim, palloc(), palloc0(), pfree(), PG_ARGISNULL, PG_DETOAST_DATUM, PG_GETARG_ANY_ARRAY, PG_RETURN_ARRAYTYPE_P, PointerGetDatum, result, ArrayMapState::ret_extra, SET_VARSIZE, ArrayMetaState::typalign, ArrayMetaState::typbyval, ArrayMetaState::typlen, and values.

Referenced by ExecEvalArrayCoerce().

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

Definition at line 3063 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

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

Definition at line 3080 of file arrayfuncs.c.

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3083 {
3085  nSubscripts, indx,
3086  dataValue, isNull,
3087  arraytyplen,
3088  elmlen, elmbyval, elmalign));
3089 }
#define PointerGetDatum(X)
Definition: postgres.h: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:2186
#define DatumGetArrayTypeP(X)
Definition: array.h:242
Datum array_set_element ( Datum  arraydatum,
int  nSubscripts,
int *  indx,
Datum  dataValue,
bool  isNull,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 2186 of file arrayfuncs.c.

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

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

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

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

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
return result
Definition: formatting.c:1633
signed int int32
Definition: c.h:256
void pfree(void *pointer)
Definition: mcxt.c:950
#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 NULL
Definition: c.h:229
#define CSTRINGOID
Definition: pg_type.h:684
#define ARR_NDIM(a)
Definition: array.h:271
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3542
#define ARR_ELEMTYPE(a)
Definition: array.h:273
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(), 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:256
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define Assert(condition)
Definition: c.h:675
size_t Size
Definition: c.h:356
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 3441 of file arrayfuncs.c.

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

Referenced by fetch_array_arg_replace_nulls().

3444 {
3445  ArrayType *array = construct_empty_array(element_type);
3446  Datum d;
3447 
3448  d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3449  pfree(array);
3450  return (ExpandedArrayHeader *) DatumGetEOHP(d);
3451 }
#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:3424
void pfree(void *pointer)
Definition: mcxt.c:950
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 3340 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, result, 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(), text_to_array_internal(), and TQRemapArray().

3346 {
3347  ArrayType *result;
3348  bool hasnulls;
3349  int32 nbytes;
3350  int32 dataoffset;
3351  int i;
3352  int nelems;
3353 
3354  if (ndims < 0) /* we do allow zero-dimension arrays */
3355  ereport(ERROR,
3356  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3357  errmsg("invalid number of dimensions: %d", ndims)));
3358  if (ndims > MAXDIM)
3359  ereport(ERROR,
3360  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3361  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
3362  ndims, MAXDIM)));
3363 
3364  /* fast track for empty array */
3365  if (ndims == 0)
3366  return construct_empty_array(elmtype);
3367 
3368  nelems = ArrayGetNItems(ndims, dims);
3369 
3370  /* compute required space */
3371  nbytes = 0;
3372  hasnulls = false;
3373  for (i = 0; i < nelems; i++)
3374  {
3375  if (nulls && nulls[i])
3376  {
3377  hasnulls = true;
3378  continue;
3379  }
3380  /* make sure data is not toasted */
3381  if (elmlen == -1)
3382  elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i]));
3383  nbytes = att_addlength_datum(nbytes, elmlen, elems[i]);
3384  nbytes = att_align_nominal(nbytes, elmalign);
3385  /* check for overflow of total request */
3386  if (!AllocSizeIsValid(nbytes))
3387  ereport(ERROR,
3388  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3389  errmsg("array size exceeds the maximum allowed (%d)",
3390  (int) MaxAllocSize)));
3391  }
3392 
3393  /* Allocate and initialize result array */
3394  if (hasnulls)
3395  {
3396  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nelems);
3397  nbytes += dataoffset;
3398  }
3399  else
3400  {
3401  dataoffset = 0; /* marker for no null bitmap */
3402  nbytes += ARR_OVERHEAD_NONULLS(ndims);
3403  }
3404  result = (ArrayType *) palloc0(nbytes);
3405  SET_VARSIZE(result, nbytes);
3406  result->ndim = ndims;
3407  result->dataoffset = dataoffset;
3408  result->elemtype = elmtype;
3409  memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
3410  memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
3411 
3412  CopyArrayEls(result,
3413  elems, nulls, nelems,
3414  elmlen, elmbyval, elmalign,
3415  false);
3416 
3417  return result;
3418 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
#define MAXDIM
Definition: c.h:419
#define PointerGetDatum(X)
Definition: postgres.h:562
int32 dataoffset
Definition: array.h:80
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
return result
Definition: formatting.c:1633
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3424
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
signed int int32
Definition: c.h:256
#define ARR_LBOUND(a)
Definition: array.h:277
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:81
#define ARR_DIMS(a)
Definition: array.h:275
#define 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:878
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:956
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:160
int errmsg(const char *fmt,...)
Definition: elog.c: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:79
void CopyArrayEls ( ArrayType array,
Datum values,
bool nulls,
int  nitems,
int  typlen,
bool  typbyval,
char  typalign,
bool  freedata 
)

Definition at line 956 of file arrayfuncs.c.

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

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

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

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:97
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:675
#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(), NULL, 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 */
365  return (ExpandedArrayHeader *) DatumGetEOHP(d);
366 }
Datum expand_array(Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
#define EA_MAGIC
Definition: array.h:97
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#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:97
bool typbyval
Definition: array.h:221
int16 typlen
Definition: array.h:220
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:675
#define DatumGetPointer(X)
Definition: postgres.h:555
char typalign
Definition: array.h:222
Oid element_type
Definition: array.h:219
#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 3475 of file arrayfuncs.c.

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

Referenced by _bt_preprocess_array_keys(), array_contain_compare(), array_set_slice(), array_to_json_internal(), array_to_jsonb_internal(), 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(), TQExamineArray(), TQRemapArray(), transformRelOptions(), tsvector_delete_arr(), tsvector_filter(), tsvector_setweight_by_filter(), and untransformRelOptions().

3479 {
3480  Datum *elems;
3481  bool *nulls;
3482  int nelems;
3483  char *p;
3484  bits8 *bitmap;
3485  int bitmask;
3486  int i;
3487 
3488  Assert(ARR_ELEMTYPE(array) == elmtype);
3489 
3490  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3491  *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
3492  if (nullsp)
3493  *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
3494  else
3495  nulls = NULL;
3496  *nelemsp = nelems;
3497 
3498  p = ARR_DATA_PTR(array);
3499  bitmap = ARR_NULLBITMAP(array);
3500  bitmask = 1;
3501 
3502  for (i = 0; i < nelems; i++)
3503  {
3504  /* Get source element, checking for NULL */
3505  if (bitmap && (*bitmap & bitmask) == 0)
3506  {
3507  elems[i] = (Datum) 0;
3508  if (nulls)
3509  nulls[i] = true;
3510  else
3511  ereport(ERROR,
3512  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3513  errmsg("null array element not allowed in this context")));
3514  }
3515  else
3516  {
3517  elems[i] = fetch_att(p, elmbyval, elmlen);
3518  p = att_addlength_pointer(p, elmlen, p);
3519  p = (char *) att_align_nominal(p, elmalign);
3520  }
3521 
3522  /* advance bitmap pointer if any */
3523  if (bitmap)
3524  {
3525  bitmask <<= 1;
3526  if (bitmask == 0x100)
3527  {
3528  bitmap++;
3529  bitmask = 1;
3530  }
3531  }
3532  }
3533 }
#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:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
#define ereport(elevel, rest)
Definition: elog.h:122
uint8 bits8
Definition: c.h:275
void * palloc0(Size size)
Definition: mcxt.c:878
uintptr_t Datum
Definition: postgres.h:372
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define ARR_NDIM(a)
Definition: array.h:271
void * palloc(Size size)
Definition: mcxt.c:849
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:273
#define ARR_NULLBITMAP(a)
Definition: array.h:281
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, NULL, 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:130
ExpandedObjectHeader hdr
Definition: array.h:102
#define ARR_HASNULL(a)
Definition: array.h:272
ArrayType * fvalue
Definition: array.h:149
uintptr_t Datum
Definition: postgres.h:372
#define NULL
Definition: c.h:229
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
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, NULL, 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:270
#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:130
char * fendptr
Definition: array.h:151
#define EA_MAGIC
Definition: array.h:97
#define ARR_LBOUND(a)
Definition: array.h:277
bool typbyval
Definition: array.h:221
ExpandedObjectHeader hdr
Definition: array.h:102
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
int16 typlen
Definition: array.h:220
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:149
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
#define DatumGetArrayTypePCopy(X)
Definition: array.h:243
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define ARR_NDIM(a)
Definition: array.h:271
#define DatumGetPointer(X)
Definition: postgres.h:555
char typalign
Definition: array.h:222
#define EOHPGetRWDatum(eohptr)
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
char * fstartptr
Definition: array.h:150
Oid element_type
Definition: array.h:219
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:182
#define ARR_ELEMTYPE(a)
Definition: array.h:273
ArrayBuildState* initArrayResult ( Oid  element_type,
MemoryContext  rcontext,
bool  subcontext 
)

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

4952 {
4953  ArrayBuildState *astate;
4954  MemoryContext arr_context = rcontext;
4955 
4956  /* Make a temporary context to hold all the junk */
4957  if (subcontext)
4958  arr_context = AllocSetContextCreate(rcontext,
4959  "accumArrayResult",
4961 
4962  astate = (ArrayBuildState *)
4963  MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
4964  astate->mcontext = arr_context;
4965  astate->private_cxt = subcontext;
4966  astate->alen = (subcontext ? 64 : 8); /* arbitrary starting array size */
4967  astate->dvalues = (Datum *)
4968  MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
4969  astate->dnulls = (bool *)
4970  MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
4971  astate->nelems = 0;
4972  astate->element_type = element_type;
4973  get_typlenbyvalalign(element_type,
4974  &astate->typlen,
4975  &astate->typbyval,
4976  &astate->typalign);
4977 
4978  return astate;
4979 }
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2021
Datum * dvalues
Definition: array.h:171
bool typbyval
Definition: array.h:177
Oid element_type
Definition: array.h:175
bool private_cxt
Definition: array.h:179
bool * dnulls
Definition: array.h:172
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
char typalign
Definition: array.h:178
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:170
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
int16 typlen
Definition: array.h:176
ArrayBuildStateAny* initArrayResultAny ( Oid  input_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 5416 of file arrayfuncs.c.

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

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

5417 {
5418  ArrayBuildStateAny *astate;
5419  Oid element_type = get_element_type(input_type);
5420 
5421  if (OidIsValid(element_type))
5422  {
5423  /* Array case */
5424  ArrayBuildStateArr *arraystate;
5425 
5426  arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5427  astate = (ArrayBuildStateAny *)
5428  MemoryContextAlloc(arraystate->mcontext,
5429  sizeof(ArrayBuildStateAny));
5430  astate->scalarstate = NULL;
5431  astate->arraystate = arraystate;
5432  }
5433  else
5434  {
5435  /* Scalar case */
5436  ArrayBuildState *scalarstate;
5437 
5438  /* Let's just check that we have a type that can be put into arrays */
5439  Assert(OidIsValid(get_array_type(input_type)));
5440 
5441  scalarstate = initArrayResult(input_type, rcontext, subcontext);
5442  astate = (ArrayBuildStateAny *)
5443  MemoryContextAlloc(scalarstate->mcontext,
5444  sizeof(ArrayBuildStateAny));
5445  astate->scalarstate = scalarstate;
5446  astate->arraystate = NULL;
5447  }
5448 
5449  return astate;
5450 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:4951
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:210
#define OidIsValid(objectId)
Definition: c.h:538
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5138
ArrayBuildStateArr * arraystate
Definition: array.h:211
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
MemoryContext mcontext
Definition: array.h:170
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
MemoryContext mcontext
Definition: array.h:188
ArrayBuildStateArr* initArrayResultArr ( Oid  array_type,
Oid  element_type,
MemoryContext  rcontext,
bool  subcontext 
)

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

5140 {
5141  ArrayBuildStateArr *astate;
5142  MemoryContext arr_context = rcontext; /* by default use the parent ctx */
5143 
5144  /* Lookup element type, unless element_type already provided */
5145  if (!OidIsValid(element_type))
5146  {
5147  element_type = get_element_type(array_type);
5148 
5149  if (!OidIsValid(element_type))
5150  ereport(ERROR,
5151  (errcode(ERRCODE_DATATYPE_MISMATCH),
5152  errmsg("data type %s is not an array type",
5153  format_type_be(array_type))));
5154  }
5155 
5156  /* Make a temporary context to hold all the junk */
5157  if (subcontext)
5158  arr_context = AllocSetContextCreate(rcontext,
5159  "accumArrayResultArr",
5161 
5162  /* Note we initialize all fields to zero */
5163  astate = (ArrayBuildStateArr *)
5164  MemoryContextAllocZero(arr_context, sizeof(ArrayBuildStateArr));
5165  astate->mcontext = arr_context;
5166  astate->private_cxt = subcontext;
5167 
5168  /* Save relevant datatype information */
5169  astate->array_type = array_type;
5170  astate->element_type = element_type;
5171 
5172  return astate;
5173 }
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:538
#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:742
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool private_cxt
Definition: array.h:200
MemoryContext mcontext
Definition: array.h:188
Datum makeArrayResult ( ArrayBuildState astate,
MemoryContext  rcontext 
)

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

5056 {
5057  int ndims;
5058  int dims[1];
5059  int lbs[1];
5060 
5061  /* If no elements were presented, we want to create an empty array */
5062  ndims = (astate->nelems > 0) ? 1 : 0;
5063  dims[0] = astate->nelems;
5064  lbs[0] = 1;
5065 
5066  return makeMdArrayResult(astate, ndims, dims, lbs, rcontext,
5067  astate->private_cxt);
5068 }
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5086
bool private_cxt
Definition: array.h:179
Datum makeArrayResultAny ( ArrayBuildStateAny astate,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5489 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5491 {
5492  Datum result;
5493 
5494  if (astate->scalarstate)
5495  {
5496  /* Must use makeMdArrayResult to support "release" parameter */
5497  int ndims;
5498  int dims[1];
5499  int lbs[1];
5500 
5501  /* If no elements were presented, we want to create an empty array */
5502  ndims = (astate->scalarstate->nelems > 0) ? 1 : 0;
5503  dims[0] = astate->scalarstate->nelems;
5504  lbs[0] = 1;
5505 
5506  result = makeMdArrayResult(astate->scalarstate, ndims, dims, lbs,
5507  rcontext, release);
5508  }
5509  else
5510  {
5511  result = makeArrayResultArr(astate->arraystate,
5512  rcontext, release);
5513  }
5514  return result;
5515 }
Datum makeArrayResultArr(ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5341
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5086
return result
Definition: formatting.c:1633
ArrayBuildState * scalarstate
Definition: array.h:210
ArrayBuildStateArr * arraystate
Definition: array.h:211
uintptr_t Datum
Definition: postgres.h:372
Datum makeArrayResultArr ( ArrayBuildStateArr astate,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5341 of file arrayfuncs.c.

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

Referenced by array_agg_array_finalfn(), and makeArrayResultAny().

5344 {
5345  ArrayType *result;
5346  MemoryContext oldcontext;
5347 
5348  /* Build the final array result in rcontext */
5349  oldcontext = MemoryContextSwitchTo(rcontext);
5350 
5351  if (astate->ndims == 0)
5352  {
5353  /* No inputs, return empty array */
5354  result = construct_empty_array(astate->element_type);
5355  }
5356  else
5357  {
5358  int dataoffset,
5359  nbytes;
5360 
5361  /* Compute required space */
5362  nbytes = astate->nbytes;
5363  if (astate->nullbitmap != NULL)
5364  {
5365  dataoffset = ARR_OVERHEAD_WITHNULLS(astate->ndims, astate->nitems);
5366  nbytes += dataoffset;
5367  }
5368  else
5369  {
5370  dataoffset = 0;
5371  nbytes += ARR_OVERHEAD_NONULLS(astate->ndims);
5372  }
5373 
5374  result = (ArrayType *) palloc0(nbytes);
5375  SET_VARSIZE(result, nbytes);
5376  result->ndim = astate->ndims;
5377  result->dataoffset = dataoffset;
5378  result->elemtype = astate->element_type;
5379 
5380  memcpy(ARR_DIMS(result), astate->dims, astate->ndims * sizeof(int));
5381  memcpy(ARR_LBOUND(result), astate->lbs, astate->ndims * sizeof(int));
5382  memcpy(ARR_DATA_PTR(result), astate->data, astate->nbytes);
5383 
5384  if (astate->nullbitmap != NULL)
5385  array_bitmap_copy(ARR_NULLBITMAP(result), 0,
5386  astate->nullbitmap, 0,
5387  astate->nitems);
5388  }
5389 
5390  MemoryContextSwitchTo(oldcontext);
5391 
5392  /* Clean up all the junk */
5393  if (release)
5394  {
5395  Assert(astate->private_cxt);
5396  MemoryContextDelete(astate->mcontext);
5397  }
5398 
5399  return PointerGetDatum(result);
5400 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#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:4624
int32 dataoffset
Definition: array.h:80
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
return result
Definition: formatting.c:1633
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3424
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:293
#define ARR_LBOUND(a)
Definition: array.h:277
bits8 * nullbitmap
Definition: array.h:190
Oid elemtype
Definition: array.h:81
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
void * palloc0(Size size)
Definition: mcxt.c:878
int lbs[MAXDIM]
Definition: array.h:197
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
int dims[MAXDIM]
Definition: array.h:196
bool private_cxt
Definition: array.h:200
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
#define ARR_NULLBITMAP(a)
Definition: array.h:281
MemoryContext mcontext
Definition: array.h:188
int ndim
Definition: array.h:79
Datum makeMdArrayResult ( ArrayBuildState astate,
int  ndims,
int *  dims,
int *  lbs,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5086 of file arrayfuncs.c.

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

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

5092 {
5093  ArrayType *result;
5094  MemoryContext oldcontext;
5095 
5096  /* Build the final array result in rcontext */
5097  oldcontext = MemoryContextSwitchTo(rcontext);
5098 
5099  result = construct_md_array(astate->dvalues,
5100  astate->dnulls,
5101  ndims,
5102  dims,
5103  lbs,
5104  astate->element_type,
5105  astate->typlen,
5106  astate->typbyval,
5107  astate->typalign);
5108 
5109  MemoryContextSwitchTo(oldcontext);
5110 
5111  /* Clean up all the junk */
5112  if (release)
5113  {
5114  Assert(astate->private_cxt);
5115  MemoryContextDelete(astate->mcontext);
5116  }
5117 
5118  return PointerGetDatum(result);
5119 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
#define PointerGetDatum(X)
Definition: postgres.h:562
Datum * dvalues
Definition: array.h:171
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:177
Oid element_type
Definition: array.h:175
bool private_cxt
Definition: array.h:179
return result
Definition: formatting.c:1633
bool * dnulls
Definition: array.h:172
char typalign
Definition: array.h:178
#define Assert(condition)
Definition: c.h:675
MemoryContext mcontext
Definition: array.h:170
int16 typlen
Definition: array.h:176
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3340
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 39 of file arrayfuncs.c.

Referenced by ReadArrayStr().