PostgreSQL Source Code  git master
array.h File Reference
#include "fmgr.h"
#include "utils/expandeddatum.h"
Include dependency graph for array.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Functions

void CopyArrayEls (ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
 
Datum array_get_element (Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
Datum array_set_element (Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_get_slice (Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_set_slice (Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, Datum srcArrayDatum, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_ref (ArrayType *array, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
 
ArrayTypearray_set (ArrayType *array, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
 
Datum array_map (Datum arrayd, struct ExprState *exprstate, struct ExprContext *econtext, Oid retType, ArrayMapState *amstate)
 
void array_bitmap_copy (bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
 
ArrayTypeconstruct_array (Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
 
ArrayTypeconstruct_md_array (Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
 
ArrayTypeconstruct_empty_array (Oid elmtype)
 
ExpandedArrayHeaderconstruct_empty_expanded_array (Oid element_type, MemoryContext parentcontext, ArrayMetaState *metacache)
 
void deconstruct_array (ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
 
bool array_contains_nulls (ArrayType *array)
 
ArrayBuildStateinitArrayResult (Oid element_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateaccumArrayResult (ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
 
Datum makeArrayResult (ArrayBuildState *astate, MemoryContext rcontext)
 
Datum makeMdArrayResult (ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
 
ArrayBuildStateArrinitArrayResultArr (Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateArraccumArrayResultArr (ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
 
Datum makeArrayResultArr (ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
 
ArrayBuildStateAnyinitArrayResultAny (Oid input_type, MemoryContext rcontext, bool subcontext)
 
ArrayBuildStateAnyaccumArrayResultAny (ArrayBuildStateAny *astate, Datum dvalue, bool disnull, Oid input_type, MemoryContext rcontext)
 
Datum makeArrayResultAny (ArrayBuildStateAny *astate, MemoryContext rcontext, bool release)
 
ArrayIterator array_create_iterator (ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
 
bool array_iterate (ArrayIterator iterator, Datum *value, bool *isnull)
 
void array_free_iterator (ArrayIterator iterator)
 
int ArrayGetOffset (int n, const int *dim, const int *lb, const int *indx)
 
int ArrayGetOffset0 (int n, const int *tup, const int *scale)
 
int ArrayGetNItems (int ndim, const int *dims)
 
void mda_get_range (int n, int *span, const int *st, const int *endp)
 
void mda_get_prod (int n, const int *range, int *prod)
 
void mda_get_offset_values (int n, int *dist, const int *prod, const int *span)
 
int mda_next_tuple (int n, int *curr, const int *span)
 
int32ArrayGetIntegerTypmods (ArrayType *arr, int *n)
 
Datum expand_array (Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
 
ExpandedArrayHeaderDatumGetExpandedArray (Datum d)
 
ExpandedArrayHeaderDatumGetExpandedArrayX (Datum d, ArrayMetaState *metacache)
 
AnyArrayTypeDatumGetAnyArrayP (Datum d)
 
void deconstruct_expanded_array (ExpandedArrayHeader *eah)
 

Variables

bool Array_nulls
 

Macro Definition Documentation

◆ AARR_DIMS

#define AARR_DIMS (   a)

◆ AARR_ELEMTYPE

#define AARR_ELEMTYPE (   a)
Value:
(a)->xpn.element_type : ARR_ELEMTYPE((ArrayType *) (a)))
#define VARATT_IS_EXPANDED_HEADER(PTR)
#define ARR_ELEMTYPE(a)
Definition: array.h:280

Definition at line 323 of file array.h.

Referenced by array_cmp(), array_contain_compare(), array_eq(), array_map(), array_out(), array_send(), array_unnest(), hash_array(), and hash_array_extended().

◆ AARR_HASNULL

#define AARR_HASNULL (   a)
Value:
((a)->xpn.dvalues != NULL ? (a)->xpn.dnulls != NULL : ARR_HASNULL((a)->xpn.fvalue)) : \
#define ARR_HASNULL(a)
Definition: array.h:279
#define VARATT_IS_EXPANDED_HEADER(PTR)

Definition at line 319 of file array.h.

Referenced by array_send().

◆ AARR_LBOUND

#define AARR_LBOUND (   a)
Value:
(a)->xpn.lbound : ARR_LBOUND((ArrayType *) (a)))
#define ARR_LBOUND(a)
Definition: array.h:284
#define VARATT_IS_EXPANDED_HEADER(PTR)

Definition at line 329 of file array.h.

Referenced by array_cmp(), array_dims(), array_eq(), array_lower(), array_map(), array_out(), array_send(), array_upper(), and generate_subscripts().

◆ AARR_NDIM

#define AARR_NDIM (   a)

◆ ARR_DATA_OFFSET

#define ARR_DATA_OFFSET (   a)    (ARR_HASNULL(a) ? (a)->dataoffset : ARR_OVERHEAD_NONULLS(ARR_NDIM(a)))

◆ ARR_DATA_PTR

#define ARR_DATA_PTR (   a)    (((char *) (a)) + ARR_DATA_OFFSET(a))

◆ ARR_DIMS

#define ARR_DIMS (   a)    ((int *) (((char *) (a)) + sizeof(ArrayType)))

Definition at line 282 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(), clause_is_strict_for(), construct_md_array(), count_nulls(), create_array_envelope(), deconstruct_array(), DeconstructFkConstraintRow(), EA_flatten_into(), equalPolicy(), estimate_array_length(), ExecEvalArrayExpr(), ExecEvalScalarArrayOp(), expand_array(), extension_config_remove(), fetch_statentries_for_relation(), generateClonedExtStatsStmt(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_func_trftypes(), get_primary_key_attnos(), get_relation_constraint_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(), RemoveRoleFromObjectPolicy(), resize_intArrayType(), SPI_sql_row_to_xmlelement(), TryReuseForeignKey(), width_bucket_array_fixed(), width_bucket_array_float8(), and width_bucket_array_variable().

◆ ARR_ELEMTYPE

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

Definition at line 280 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(), DeconstructFkConstraintRow(), exec_stmt_foreach_a(), ExecEvalArrayCoerce(), ExecEvalArrayExpr(), ExecEvalScalarArrayOp(), ExecIndexEvalArrayKeys(), expand_array(), extension_config_remove(), extract_variadic_args(), fetch_statentries_for_relation(), generateClonedExtStatsStmt(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_func_trftypes(), get_primary_key_attnos(), get_relation_constraint_attnos(), get_text_array_contents(), ginarrayextract(), gincost_scalararrayopexpr(), ginqueryarrayextract(), GUCArrayAdd(), hstore_from_array(), hstore_from_arrays(), int2vectorrecv(), map_sql_value_to_xml_value(), match_clause_to_partition_key(), 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(), satisfies_hash_partition(), scalararraysel(), SPI_sql_row_to_xmlelement(), text_format(), TryReuseForeignKey(), and width_bucket_array().

◆ ARR_HASNULL

◆ ARR_LBOUND

◆ ARR_NDIM

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

Definition at line 278 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(), clause_is_strict_for(), count_nulls(), DecodeTextArrayToCString(), deconstruct_array(), DeconstructFkConstraintRow(), estimate_array_length(), exec_stmt_foreach_a(), ExecEvalArrayExpr(), ExecEvalScalarArrayOp(), expand_array(), extension_config_remove(), fetch_statentries_for_relation(), generateClonedExtStatsStmt(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_func_trftypes(), get_primary_key_attnos(), get_relation_constraint_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(), resize_intArrayType(), SPI_sql_row_to_xmlelement(), TryReuseForeignKey(), width_bucket_array(), width_bucket_array_fixed(), width_bucket_array_float8(), and width_bucket_array_variable().

◆ ARR_NULLBITMAP

◆ ARR_OVERHEAD_NONULLS

◆ ARR_OVERHEAD_WITHNULLS

#define ARR_OVERHEAD_WITHNULLS (   ndims,
  nitems 
)

◆ ARR_SIZE

◆ DatumGetArrayTypeP

#define DatumGetArrayTypeP (   X)    ((ArrayType *) PG_DETOAST_DATUM(X))

Definition at line 249 of file array.h.

Referenced by _bt_preprocess_array_keys(), _ltree_compress(), accumArrayResultArr(), AlterFunction(), AlterSetting(), ApplySetting(), array_get_element(), array_get_slice(), array_set(), array_set_element(), array_set_slice(), array_to_json_internal(), array_to_jsonb_internal(), arrayconst_startup_fn(), build_function_result_tupdesc_d(), calc_arraycontsel(), clause_is_strict_for(), compute_array_stats(), DecodeTextArrayToCString(), decompile_column_index_array(), DeconstructFkConstraintRow(), estimate_array_length(), ExecEvalArrayExpr(), ExecEvalScalarArrayOp(), ExecIndexEvalArrayKeys(), extension_config_remove(), fetch_statentries_for_relation(), flatten_reloptions(), g_int_compress(), g_int_decompress(), g_intbig_compress(), generateClonedExtStatsStmt(), generateClonedIndexStmt(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_func_trftypes(), get_primary_key_attnos(), get_relation_constraint_attnos(), GetSubscription(), gincost_scalararrayopexpr(), is_strict_saop(), map_sql_value_to_xml_value(), match_clause_to_partition_key(), oid_array_to_list(), parseRelOptions(), pg_extension_config_dump(), pg_get_constraintdef_worker(), pg_get_functiondef(), pg_get_statisticsobj_worker(), pg_isolation_test_session_is_blocked(), plperl_ref_from_pg_array(), PLyList_FromArray(), predicate_classify(), RelationGetExclusionInfo(), scalararraysel(), TidListEval(), transformRelOptions(), TryReuseForeignKey(), and untransformRelOptions().

◆ DatumGetArrayTypePCopy

◆ EA_MAGIC

#define EA_MAGIC   689375833 /* ID for debugging crosschecks */

◆ PG_GETARG_ANY_ARRAY_P

◆ PG_GETARG_ARRAYTYPE_P

#define PG_GETARG_ARRAYTYPE_P (   n)    DatumGetArrayTypeP(PG_GETARG_DATUM(n))

Definition at line 251 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(), extract_variadic_args(), float4_accum(), float8_accum(), float8_avg(), float8_combine(), float8_corr(), float8_covar_pop(), float8_covar_samp(), float8_regr_accum(), float8_regr_avgx(), float8_regr_avgy(), float8_regr_combine(), float8_regr_intercept(), float8_regr_r2(), float8_regr_slope(), float8_regr_sxx(), float8_regr_sxy(), float8_regr_syy(), float8_stddev_pop(), float8_stddev_samp(), float8_var_pop(), float8_var_samp(), g_int_same(), g_intbig_consistent(), get_jsonb_path_all(), get_path_all(), ghstore_consistent(), gin_extract_hstore_query(), gin_extract_jsonb_query(), ginint4_queryextract(), hstore_delete_array(), hstore_exists_all(), hstore_exists_any(), hstore_from_array(), hstore_from_arrays(), hstore_slice_to_array(), hstore_slice_to_hstore(), icount(), idx(), int2_avg_accum(), int2_avg_accum_inv(), int2int4_sum(), int4_avg_accum(), int4_avg_accum_inv(), int4_avg_combine(), int8_avg(), intarray_push_array(), intarray_push_elem(), interval_accum(), interval_accum_inv(), interval_avg(), interval_combine(), intervaltypmodin(), intset_union_elem(), json_object(), json_object_two_arg(), jsonb_delete_array(), jsonb_delete_path(), jsonb_exists_all(), jsonb_exists_any(), jsonb_insert(), jsonb_object(), jsonb_object_two_arg(), jsonb_set(), lt_q_regex(), ltree_consistent(), numerictypmodin(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), pg_armor(), pg_get_object_address(), pg_isolation_test_session_is_blocked(), pg_logical_slot_get_changes_guts(), satisfies_hash_partition(), 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().

◆ PG_GETARG_ARRAYTYPE_P_COPY

◆ PG_GETARG_EXPANDED_ARRAY

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

Definition at line 256 of file array.h.

◆ PG_GETARG_EXPANDED_ARRAYX

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

Definition at line 257 of file array.h.

Referenced by fetch_array_arg_replace_nulls().

◆ PG_RETURN_ARRAYTYPE_P

◆ PG_RETURN_EXPANDED_ARRAY

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

Definition at line 259 of file array.h.

Typedef Documentation

◆ AnyArrayType

typedef union AnyArrayType AnyArrayType

◆ ArrayBuildState

◆ ArrayBuildStateAny

◆ ArrayBuildStateArr

◆ ArrayIterator

Definition at line 246 of file array.h.

◆ ArrayMapState

typedef struct ArrayMapState ArrayMapState

◆ ArrayMetaState

◆ ArrayType

typedef struct ArrayType ArrayType

◆ ExpandedArrayHeader

Function Documentation

◆ accumArrayResult()

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

Definition at line 5053 of file arrayfuncs.c.

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

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

5057 {
5058  MemoryContext oldcontext;
5059 
5060  if (astate == NULL)
5061  {
5062  /* First time through --- initialize */
5063  astate = initArrayResult(element_type, rcontext, true);
5064  }
5065  else
5066  {
5067  Assert(astate->element_type == element_type);
5068  }
5069 
5070  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5071 
5072  /* enlarge dvalues[]/dnulls[] if needed */
5073  if (astate->nelems >= astate->alen)
5074  {
5075  astate->alen *= 2;
5076  astate->dvalues = (Datum *)
5077  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5078  astate->dnulls = (bool *)
5079  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5080  }
5081 
5082  /*
5083  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5084  * it's varlena. (You might think that detoasting is not needed here
5085  * because construct_md_array can detoast the array elements later.
5086  * However, we must not let construct_md_array modify the ArrayBuildState
5087  * because that would mean array_agg_finalfn damages its input, which is
5088  * verboten. Also, this way frequently saves one copying step.)
5089  */
5090  if (!disnull && !astate->typbyval)
5091  {
5092  if (astate->typlen == -1)
5093  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5094  else
5095  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5096  }
5097 
5098  astate->dvalues[astate->nelems] = dvalue;
5099  astate->dnulls[astate->nelems] = disnull;
5100  astate->nelems++;
5101 
5102  MemoryContextSwitchTo(oldcontext);
5103 
5104  return astate;
5105 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:237
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5014
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum * dvalues
Definition: array.h:178
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:184
Oid element_type
Definition: array.h:182
bool * dnulls
Definition: array.h:179
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:130
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:733
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
MemoryContext mcontext
Definition: array.h:177
int16 typlen
Definition: array.h:183

◆ accumArrayResultAny()

ArrayBuildStateAny* accumArrayResultAny ( ArrayBuildStateAny astate,
Datum  dvalue,
bool  disnull,
Oid  input_type,
MemoryContext  rcontext 
)

Definition at line 5524 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5528 {
5529  if (astate == NULL)
5530  astate = initArrayResultAny(input_type, rcontext, true);
5531 
5532  if (astate->scalarstate)
5533  (void) accumArrayResult(astate->scalarstate,
5534  dvalue, disnull,
5535  input_type, rcontext);
5536  else
5537  (void) accumArrayResultArr(astate->arraystate,
5538  dvalue, disnull,
5539  input_type, rcontext);
5540 
5541  return astate;
5542 }
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5479
ArrayBuildState * scalarstate
Definition: array.h:217
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5247
ArrayBuildStateArr * arraystate
Definition: array.h:218
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5053

◆ accumArrayResultArr()

ArrayBuildStateArr* accumArrayResultArr ( ArrayBuildStateArr astate,
Datum  dvalue,
bool  disnull,
Oid  array_type,
MemoryContext  rcontext 
)

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

Referenced by accumArrayResultAny(), and array_agg_array_transfn().

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

◆ array_bitmap_copy()

void array_bitmap_copy ( bits8 destbitmap,
int  destoffset,
const bits8 srcbitmap,
int  srcoffset,
int  nitems 
)

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

4690 {
4691  int destbitmask,
4692  destbitval,
4693  srcbitmask,
4694  srcbitval;
4695 
4696  Assert(destbitmap);
4697  if (nitems <= 0)
4698  return; /* don't risk fetch off end of memory */
4699  destbitmap += destoffset / 8;
4700  destbitmask = 1 << (destoffset % 8);
4701  destbitval = *destbitmap;
4702  if (srcbitmap)
4703  {
4704  srcbitmap += srcoffset / 8;
4705  srcbitmask = 1 << (srcoffset % 8);
4706  srcbitval = *srcbitmap;
4707  while (nitems-- > 0)
4708  {
4709  if (srcbitval & srcbitmask)
4710  destbitval |= destbitmask;
4711  else
4712  destbitval &= ~destbitmask;
4713  destbitmask <<= 1;
4714  if (destbitmask == 0x100)
4715  {
4716  *destbitmap++ = destbitval;
4717  destbitmask = 1;
4718  if (nitems > 0)
4719  destbitval = *destbitmap;
4720  }
4721  srcbitmask <<= 1;
4722  if (srcbitmask == 0x100)
4723  {
4724  srcbitmap++;
4725  srcbitmask = 1;
4726  if (nitems > 0)
4727  srcbitval = *srcbitmap;
4728  }
4729  }
4730  if (destbitmask != 1)
4731  *destbitmap = destbitval;
4732  }
4733  else
4734  {
4735  while (nitems-- > 0)
4736  {
4737  destbitval |= destbitmask;
4738  destbitmask <<= 1;
4739  if (destbitmask == 0x100)
4740  {
4741  *destbitmap++ = destbitval;
4742  destbitmask = 1;
4743  if (nitems > 0)
4744  destbitval = *destbitmap;
4745  }
4746  }
4747  if (destbitmask != 1)
4748  *destbitmap = destbitval;
4749  }
4750 }
#define Assert(condition)
Definition: c.h:733

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

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

3529 {
3530  int nelems;
3531  bits8 *bitmap;
3532  int bitmask;
3533 
3534  /* Easy answer if there's no null bitmap */
3535  if (!ARR_HASNULL(array))
3536  return false;
3537 
3538  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3539 
3540  bitmap = ARR_NULLBITMAP(array);
3541 
3542  /* check whole bytes of the bitmap byte-at-a-time */
3543  while (nelems >= 8)
3544  {
3545  if (*bitmap != 0xFF)
3546  return true;
3547  bitmap++;
3548  nelems -= 8;
3549  }
3550 
3551  /* check last partial byte */
3552  bitmask = 1;
3553  while (nelems > 0)
3554  {
3555  if ((*bitmap & bitmask) == 0)
3556  return true;
3557  bitmask <<= 1;
3558  nelems--;
3559  }
3560 
3561  return false;
3562 }
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_HASNULL(a)
Definition: array.h:279
uint8 bits8
Definition: c.h:366
#define ARR_NDIM(a)
Definition: array.h:278
#define ARR_NULLBITMAP(a)
Definition: array.h:288

◆ array_create_iterator()

ArrayIterator array_create_iterator ( ArrayType arr,
int  slice_ndim,
ArrayMetaState mstate 
)

Definition at line 4318 of file arrayfuncs.c.

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

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

4319 {
4320  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4321 
4322  /*
4323  * Sanity-check inputs --- caller should have got this right already
4324  */
4325  Assert(PointerIsValid(arr));
4326  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4327  elog(ERROR, "invalid arguments to array_create_iterator");
4328 
4329  /*
4330  * Remember basic info about the array and its element type
4331  */
4332  iterator->arr = arr;
4333  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4334  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4335 
4336  if (mstate != NULL)
4337  {
4338  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4339 
4340  iterator->typlen = mstate->typlen;
4341  iterator->typbyval = mstate->typbyval;
4342  iterator->typalign = mstate->typalign;
4343  }
4344  else
4346  &iterator->typlen,
4347  &iterator->typbyval,
4348  &iterator->typalign);
4349 
4350  /*
4351  * Remember the slicing parameters.
4352  */
4353  iterator->slice_ndim = slice_ndim;
4354 
4355  if (slice_ndim > 0)
4356  {
4357  /*
4358  * Get pointers into the array's dims and lbound arrays to represent
4359  * the dims/lbound arrays of a slice. These are the same as the
4360  * rightmost N dimensions of the array.
4361  */
4362  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4363  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4364 
4365  /*
4366  * Compute number of elements in a slice.
4367  */
4368  iterator->slice_len = ArrayGetNItems(slice_ndim,
4369  iterator->slice_dims);
4370 
4371  /*
4372  * Create workspace for building sub-arrays.
4373  */
4374  iterator->slice_values = (Datum *)
4375  palloc(iterator->slice_len * sizeof(Datum));
4376  iterator->slice_nulls = (bool *)
4377  palloc(iterator->slice_len * sizeof(bool));
4378  }
4379 
4380  /*
4381  * Initialize our data pointer and linear element number. These will
4382  * advance through the array during array_iterate().
4383  */
4384  iterator->data_ptr = ARR_DATA_PTR(arr);
4385  iterator->current_item = 0;
4386 
4387  return iterator;
4388 }
bits8 * nullbitmap
Definition: arrayfuncs.c:71
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2049
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_LBOUND(a)
Definition: array.h:284
bool typbyval
Definition: array.h:228
bool * slice_nulls
Definition: arrayfuncs.c:83
#define ERROR
Definition: elog.h:43
Datum * slice_values
Definition: arrayfuncs.c:82
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
int16 typlen
Definition: array.h:227
void * palloc0(Size size)
Definition: mcxt.c:980
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:733
#define ARR_NDIM(a)
Definition: array.h:278
char typalign
Definition: array.h:229
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:228
Oid element_type
Definition: array.h:226
#define PointerIsValid(pointer)
Definition: c.h:627
#define ARR_ELEMTYPE(a)
Definition: array.h:280
#define ARR_NULLBITMAP(a)
Definition: array.h:288
ArrayType * arr
Definition: arrayfuncs.c:70

◆ array_free_iterator()

void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4480 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4481 {
4482  if (iterator->slice_ndim > 0)
4483  {
4484  pfree(iterator->slice_values);
4485  pfree(iterator->slice_nulls);
4486  }
4487  pfree(iterator);
4488 }
bool * slice_nulls
Definition: arrayfuncs.c:83
void pfree(void *pointer)
Definition: mcxt.c:1056
Datum * slice_values
Definition: arrayfuncs.c:82

◆ array_get_element()

Datum array_get_element ( Datum  arraydatum,
int  nSubscripts,
int *  indx,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign,
bool isNull 
)

Definition at line 1819 of file arrayfuncs.c.

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

Referenced by array_ref(), ATExecAlterColumnType(), ExecEvalSubscriptingRefFetch(), ExecEvalSubscriptingRefOld(), and RelationBuildTupleDesc().

1827 {
1828  int i,
1829  ndim,
1830  *dim,
1831  *lb,
1832  offset,
1833  fixedDim[1],
1834  fixedLb[1];
1835  char *arraydataptr,
1836  *retptr;
1837  bits8 *arraynullsptr;
1838 
1839  if (arraytyplen > 0)
1840  {
1841  /*
1842  * fixed-length arrays -- these are assumed to be 1-d, 0-based
1843  */
1844  ndim = 1;
1845  fixedDim[0] = arraytyplen / elmlen;
1846  fixedLb[0] = 0;
1847  dim = fixedDim;
1848  lb = fixedLb;
1849  arraydataptr = (char *) DatumGetPointer(arraydatum);
1850  arraynullsptr = NULL;
1851  }
1852  else if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(arraydatum)))
1853  {
1854  /* expanded array: let's do this in a separate function */
1855  return array_get_element_expanded(arraydatum,
1856  nSubscripts,
1857  indx,
1858  arraytyplen,
1859  elmlen,
1860  elmbyval,
1861  elmalign,
1862  isNull);
1863  }
1864  else
1865  {
1866  /* detoast array if necessary, producing normal varlena input */
1867  ArrayType *array = DatumGetArrayTypeP(arraydatum);
1868 
1869  ndim = ARR_NDIM(array);
1870  dim = ARR_DIMS(array);
1871  lb = ARR_LBOUND(array);
1872  arraydataptr = ARR_DATA_PTR(array);
1873  arraynullsptr = ARR_NULLBITMAP(array);
1874  }
1875 
1876  /*
1877  * Return NULL for invalid subscript
1878  */
1879  if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
1880  {
1881  *isNull = true;
1882  return (Datum) 0;
1883  }
1884  for (i = 0; i < ndim; i++)
1885  {
1886  if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
1887  {
1888  *isNull = true;
1889  return (Datum) 0;
1890  }
1891  }
1892 
1893  /*
1894  * Calculate the element number
1895  */
1896  offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
1897 
1898  /*
1899  * Check for NULL array element
1900  */
1901  if (array_get_isnull(arraynullsptr, offset))
1902  {
1903  *isNull = true;
1904  return (Datum) 0;
1905  }
1906 
1907  /*
1908  * OK, get the element
1909  */
1910  *isNull = false;
1911  retptr = array_seek(arraydataptr, 0, arraynullsptr, offset,
1912  elmlen, elmbyval, elmalign);
1913  return ArrayCast(retptr, elmbyval, elmlen);
1914 }
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:322
#define MAXDIM
Definition: c.h:530
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
#define ARR_LBOUND(a)
Definition: array.h:284
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
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:1920
uint8 bits8
Definition: c.h:366
uintptr_t Datum
Definition: postgres.h:367
static char * array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems, int typlen, bool typbyval, char typalign)
Definition: arrayfuncs.c:4587
static Datum ArrayCast(char *value, bool byval, int len)
Definition: arrayfuncs.c:4537
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4502
#define ARR_NDIM(a)
Definition: array.h:278
#define DatumGetPointer(X)
Definition: postgres.h:549
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:288
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ array_get_slice()

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 2028 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(), generate_unaccent_rules::bytes(), construct_empty_array(), ArrayType::dataoffset, DatumGetArrayTypeP, DatumGetPointer, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, InvalidOid, MAXDIM, mda_get_range(), ArrayType::ndim, palloc0(), PointerGetDatum, and SET_VARSIZE.

Referenced by ExecEvalSubscriptingRefFetch(), and ExecEvalSubscriptingRefOld().

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

◆ array_iterate()

bool array_iterate ( ArrayIterator  iterator,
Datum value,
bool isnull 
)

Definition at line 4397 of file arrayfuncs.c.

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

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

4398 {
4399  /* Done if we have reached the end of the array */
4400  if (iterator->current_item >= iterator->nitems)
4401  return false;
4402 
4403  if (iterator->slice_ndim == 0)
4404  {
4405  /*
4406  * Scalar case: return one element.
4407  */
4408  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4409  {
4410  *isnull = true;
4411  *value = (Datum) 0;
4412  }
4413  else
4414  {
4415  /* non-NULL, so fetch the individual Datum to return */
4416  char *p = iterator->data_ptr;
4417 
4418  *isnull = false;
4419  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4420 
4421  /* Move our data pointer forward to the next element */
4422  p = att_addlength_pointer(p, iterator->typlen, p);
4423  p = (char *) att_align_nominal(p, iterator->typalign);
4424  iterator->data_ptr = p;
4425  }
4426  }
4427  else
4428  {
4429  /*
4430  * Slice case: build and return an array of the requested size.
4431  */
4432  ArrayType *result;
4433  Datum *values = iterator->slice_values;
4434  bool *nulls = iterator->slice_nulls;
4435  char *p = iterator->data_ptr;
4436  int i;
4437 
4438  for (i = 0; i < iterator->slice_len; i++)
4439  {
4440  if (array_get_isnull(iterator->nullbitmap,
4441  iterator->current_item++))
4442  {
4443  nulls[i] = true;
4444  values[i] = (Datum) 0;
4445  }
4446  else
4447  {
4448  nulls[i] = false;
4449  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4450 
4451  /* Move our data pointer forward to the next element */
4452  p = att_addlength_pointer(p, iterator->typlen, p);
4453  p = (char *) att_align_nominal(p, iterator->typalign);
4454  }
4455  }
4456 
4457  iterator->data_ptr = p;
4458 
4459  result = construct_md_array(values,
4460  nulls,
4461  iterator->slice_ndim,
4462  iterator->slice_dims,
4463  iterator->slice_lbound,
4464  ARR_ELEMTYPE(iterator->arr),
4465  iterator->typlen,
4466  iterator->typbyval,
4467  iterator->typalign);
4468 
4469  *isnull = false;
4470  *value = PointerGetDatum(result);
4471  }
4472 
4473  return true;
4474 }
bits8 * nullbitmap
Definition: arrayfuncs.c:71
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:146
#define PointerGetDatum(X)
Definition: postgres.h:556
static struct @145 value
bool * slice_nulls
Definition: arrayfuncs.c:83
Datum * slice_values
Definition: arrayfuncs.c:82
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:174
uintptr_t Datum
Definition: postgres.h:367
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4502
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:73
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:3326
#define ARR_ELEMTYPE(a)
Definition: array.h:280
ArrayType * arr
Definition: arrayfuncs.c:70

◆ array_map()

Datum array_map ( Datum  arrayd,
struct ExprState exprstate,
struct ExprContext econtext,
Oid  retType,
ArrayMapState amstate 
)

Definition at line 3131 of file arrayfuncs.c.

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

Referenced by ExecEvalArrayCoerce().

3134 {
3135  AnyArrayType *v = DatumGetAnyArrayP(arrayd);
3136  ArrayType *result;
3137  Datum *values;
3138  bool *nulls;
3139  int *dim;
3140  int ndim;
3141  int nitems;
3142  int i;
3143  int32 nbytes = 0;
3144  int32 dataoffset;
3145  bool hasnulls;
3146  Oid inpType;
3147  int inp_typlen;
3148  bool inp_typbyval;
3149  char inp_typalign;
3150  int typlen;
3151  bool typbyval;
3152  char typalign;
3153  array_iter iter;
3154  ArrayMetaState *inp_extra;
3155  ArrayMetaState *ret_extra;
3156  Datum *transform_source = exprstate->innermost_caseval;
3157  bool *transform_source_isnull = exprstate->innermost_casenull;
3158 
3159  inpType = AARR_ELEMTYPE(v);
3160  ndim = AARR_NDIM(v);
3161  dim = AARR_DIMS(v);
3162  nitems = ArrayGetNItems(ndim, dim);
3163 
3164  /* Check for empty array */
3165  if (nitems <= 0)
3166  {
3167  /* Return empty array */
3168  return PointerGetDatum(construct_empty_array(retType));
3169  }
3170 
3171  /*
3172  * We arrange to look up info about input and return element types only
3173  * once per series of calls, assuming the element type doesn't change
3174  * underneath us.
3175  */
3176  inp_extra = &amstate->inp_extra;
3177  ret_extra = &amstate->ret_extra;
3178 
3179  if (inp_extra->element_type != inpType)
3180  {
3181  get_typlenbyvalalign(inpType,
3182  &inp_extra->typlen,
3183  &inp_extra->typbyval,
3184  &inp_extra->typalign);
3185  inp_extra->element_type = inpType;
3186  }
3187  inp_typlen = inp_extra->typlen;
3188  inp_typbyval = inp_extra->typbyval;
3189  inp_typalign = inp_extra->typalign;
3190 
3191  if (ret_extra->element_type != retType)
3192  {
3193  get_typlenbyvalalign(retType,
3194  &ret_extra->typlen,
3195  &ret_extra->typbyval,
3196  &ret_extra->typalign);
3197  ret_extra->element_type = retType;
3198  }
3199  typlen = ret_extra->typlen;
3200  typbyval = ret_extra->typbyval;
3201  typalign = ret_extra->typalign;
3202 
3203  /* Allocate temporary arrays for new values */
3204  values = (Datum *) palloc(nitems * sizeof(Datum));
3205  nulls = (bool *) palloc(nitems * sizeof(bool));
3206 
3207  /* Loop over source data */
3208  array_iter_setup(&iter, v);
3209  hasnulls = false;
3210 
3211  for (i = 0; i < nitems; i++)
3212  {
3213  /* Get source element, checking for NULL */
3214  *transform_source =
3215  array_iter_next(&iter, transform_source_isnull, i,
3216  inp_typlen, inp_typbyval, inp_typalign);
3217 
3218  /* Apply the given expression to source element */
3219  values[i] = ExecEvalExpr(exprstate, econtext, &nulls[i]);
3220 
3221  if (nulls[i])
3222  hasnulls = true;
3223  else
3224  {
3225  /* Ensure data is not toasted */
3226  if (typlen == -1)
3227  values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
3228  /* Update total result size */
3229  nbytes = att_addlength_datum(nbytes, typlen, values[i]);
3230  nbytes = att_align_nominal(nbytes, typalign);
3231  /* check for overflow of total request */
3232  if (!AllocSizeIsValid(nbytes))
3233  ereport(ERROR,
3234  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3235  errmsg("array size exceeds the maximum allowed (%d)",
3236  (int) MaxAllocSize)));
3237  }
3238  }
3239 
3240  /* Allocate and fill the result array */
3241  if (hasnulls)
3242  {
3243  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3244  nbytes += dataoffset;
3245  }
3246  else
3247  {
3248  dataoffset = 0; /* marker for no null bitmap */
3249  nbytes += ARR_OVERHEAD_NONULLS(ndim);
3250  }
3251  result = (ArrayType *) palloc0(nbytes);
3252  SET_VARSIZE(result, nbytes);
3253  result->ndim = ndim;
3254  result->dataoffset = dataoffset;
3255  result->elemtype = retType;
3256  memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
3257  memcpy(ARR_LBOUND(result), AARR_LBOUND(v), ndim * sizeof(int));
3258 
3259  CopyArrayEls(result,
3260  values, nulls, nitems,
3261  typlen, typbyval, typalign,
3262  false);
3263 
3264  /*
3265  * Note: do not risk trying to pfree the results of the called expression
3266  */
3267  pfree(values);
3268  pfree(nulls);
3269 
3270  return PointerGetDatum(result);
3271 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:146
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:2049
#define PointerGetDatum(X)
Definition: postgres.h:556
bool * innermost_casenull
Definition: execnodes.h:112
int32 dataoffset
Definition: array.h:84
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:608
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3410
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:300
signed int int32
Definition: c.h:347
AnyArrayType * DatumGetAnyArrayP(Datum d)
#define ARR_LBOUND(a)
Definition: array.h:284
bool typbyval
Definition: array.h:228
void pfree(void *pointer)
Definition: mcxt.c:1056
char typalign
Definition: pg_type.h:170
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:282
ArrayMetaState inp_extra
Definition: array.h:241
int16 typlen
Definition: array.h:227
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:285
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
Datum * innermost_caseval
Definition: execnodes.h:111
#define ereport(elevel, rest)
Definition: elog.h:141
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void * palloc0(Size size)
Definition: mcxt.c:980
uintptr_t Datum
Definition: postgres.h:367
#define AARR_DIMS(a)
Definition: array.h:326
#define AARR_ELEMTYPE(a)
Definition: array.h:323
#define AARR_LBOUND(a)
Definition: array.h:329
#define AARR_NDIM(a)
Definition: array.h:316
ArrayMetaState ret_extra
Definition: array.h:242
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:957
char typalign
Definition: array.h:229
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:162
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
Oid element_type
Definition: array.h:226
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:235
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
int ndim
Definition: array.h:83

◆ array_ref()

Datum array_ref ( ArrayType array,
int  nSubscripts,
int *  indx,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign,
bool isNull 
)

Definition at line 3076 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3079 {
3080  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3081  arraytyplen, elmlen, elmbyval, elmalign,
3082  isNull);
3083 }
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1819

◆ array_set()

ArrayType* array_set ( ArrayType array,
int  nSubscripts,
int *  indx,
Datum  dataValue,
bool  isNull,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 3093 of file arrayfuncs.c.

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3096 {
3098  nSubscripts, indx,
3099  dataValue, isNull,
3100  arraytyplen,
3101  elmlen, elmbyval, elmalign));
3102 }
#define PointerGetDatum(X)
Definition: postgres.h:556
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:2199
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ array_set_element()

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 2199 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 ExecEvalSubscriptingRefAssign().

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

◆ array_set_slice()

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 2759 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, ArrayIteratorData::nitems, palloc0(), PointerGetDatum, and SET_VARSIZE.

Referenced by ExecEvalSubscriptingRefAssign().

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

◆ ArrayGetIntegerTypmods()

int32* ArrayGetIntegerTypmods ( ArrayType arr,
int *  n 
)

Definition at line 200 of file arrayutils.c.

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

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 */
222  deconstruct_array(arr, CSTRINGOID,
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_strtoint32(DatumGetCString(elem_values[i]));
230 
231  pfree(elem_values);
232 
233  return result;
234 }
int errcode(int sqlerrcode)
Definition: elog.c:608
signed int int32
Definition: c.h:347
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:566
#define ereport(elevel, rest)
Definition: elog.h:141
uintptr_t Datum
Definition: postgres.h:367
#define ARR_NDIM(a)
Definition: array.h:278
int32 pg_strtoint32(const char *s)
Definition: numutils.c:199
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3528
#define ARR_ELEMTYPE(a)
Definition: array.h:280

◆ ArrayGetNItems()

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(), clause_is_strict_for(), construct_md_array(), count_nulls(), deconstruct_array(), EA_get_flat_size(), estimate_array_length(), ExecEvalArrayExpr(), ExecEvalScalarArrayOp(), get_text_array_contents(), getWeights(), hash_array(), hash_array_extended(), is_strict_saop(), lt_q_regex(), pg_isolation_test_session_is_blocked(), predicate_classify(), width_bucket_array_fixed(), width_bucket_array_float8(), and width_bucket_array_variable().

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

◆ ArrayGetOffset()

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:153
int i

◆ ArrayGetOffset0()

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:153
int i

◆ construct_array()

ArrayType* construct_array ( Datum elems,
int  nelems,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

◆ construct_empty_array()

◆ construct_empty_expanded_array()

ExpandedArrayHeader* construct_empty_expanded_array ( Oid  element_type,
MemoryContext  parentcontext,
ArrayMetaState metacache 
)

Definition at line 3427 of file arrayfuncs.c.

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

Referenced by fetch_array_arg_replace_nulls().

3430 {
3431  ArrayType *array = construct_empty_array(element_type);
3432  Datum d;
3433 
3434  d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3435  pfree(array);
3436  return (ExpandedArrayHeader *) DatumGetEOHP(d);
3437 }
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum expand_array(Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3410
void pfree(void *pointer)
Definition: mcxt.c:1056
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
uintptr_t Datum
Definition: postgres.h:367

◆ construct_md_array()

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

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

Referenced by array_iterate(), array_set_element(), array_set_slice(), build_regexp_match_result(), construct_array(), ExecEvalArrayExpr(), hstore_avals(), hstore_slice_to_array(), hstore_to_array_internal(), makeMdArrayResult(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), plpgsql_fulfill_promise(), PLySequence_ToArray(), strlist_to_textarray(), and text_to_array_internal().

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

◆ CopyArrayEls()

void CopyArrayEls ( ArrayType array,
Datum values,
bool nulls,
int  nitems,
int  typlen,
bool  typbyval,
char  typalign,
bool  freedata 
)

Definition at line 957 of file arrayfuncs.c.

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

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

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

◆ DatumGetAnyArrayP()

AnyArrayType* DatumGetAnyArrayP ( Datum  d)

Definition at line 401 of file array_expanded.c.

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

Referenced by array_map().

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

◆ DatumGetExpandedArray()

ExpandedArrayHeader* DatumGetExpandedArray ( Datum  d)

Definition at line 352 of file array_expanded.c.

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

Referenced by array_set_element_expanded().

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

◆ DatumGetExpandedArrayX()

ExpandedArrayHeader* DatumGetExpandedArrayX ( Datum  d,
ArrayMetaState metacache 
)

Definition at line 372 of file array_expanded.c.

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

373 {
374  /* If it's a writable expanded array already, just return it */
376  {
378 
379  Assert(eah->ea_magic == EA_MAGIC);
380  /* Update cache if provided */
381  if (metacache)
382  {
383  metacache->element_type = eah->element_type;
384  metacache->typlen = eah->typlen;
385  metacache->typbyval = eah->typbyval;
386  metacache->typalign = eah->typalign;
387  }
388  return eah;
389  }
390 
391  /* Else expand using caller's cache if any */
392  d = expand_array(d, CurrentMemoryContext, metacache);
393  return (ExpandedArrayHeader *) DatumGetEOHP(d);
394 }
Datum expand_array(Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
#define EA_MAGIC
Definition: array.h:101
bool typbyval
Definition: array.h:228
int16 typlen
Definition: array.h:227
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:733
#define DatumGetPointer(X)
Definition: postgres.h:549
char typalign
Definition: array.h:229
Oid element_type
Definition: array.h:226
#define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR)
Definition: postgres.h:320

◆ deconstruct_array()

void deconstruct_array ( ArrayType array,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign,
Datum **  elemsp,
bool **  nullsp,
int *  nelemsp 
)

Definition at line 3461 of file arrayfuncs.c.

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

Referenced by _bt_preprocess_array_keys(), array_contain_compare(), array_set_slice(), array_to_json_internal(), array_to_jsonb_internal(), array_to_tsvector(), arrayconst_startup_fn(), ArrayGetIntegerTypmods(), binary_upgrade_create_empty_extension(), build_function_result_tupdesc_d(), compute_array_stats(), DecodeTextArrayToCString(), decompile_column_index_array(), deconstruct_expanded_array(), ExecIndexEvalArrayKeys(), extension_config_remove(), extract_variadic_args(), 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(), match_clause_to_partition_key(), 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(), satisfies_hash_partition(), scalararraysel(), SPI_sql_row_to_xmlelement(), text_format(), textarray_to_stringlist(), textarray_to_strvaluelist(), TidListEval(), transformRelOptions(), tsvector_delete_arr(), tsvector_filter(), tsvector_setweight_by_filter(), and untransformRelOptions().

3465 {
3466  Datum *elems;
3467  bool *nulls;
3468  int nelems;
3469  char *p;
3470  bits8 *bitmap;
3471  int bitmask;
3472  int i;
3473 
3474  Assert(ARR_ELEMTYPE(array) == elmtype);
3475 
3476  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3477  *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
3478  if (nullsp)
3479  *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
3480  else
3481  nulls = NULL;
3482  *nelemsp = nelems;
3483 
3484  p = ARR_DATA_PTR(array);
3485  bitmap = ARR_NULLBITMAP(array);
3486  bitmask = 1;
3487 
3488  for (i = 0; i < nelems; i++)
3489  {
3490  /* Get source element, checking for NULL */
3491  if (bitmap && (*bitmap & bitmask) == 0)
3492  {
3493  elems[i] = (Datum) 0;
3494  if (nulls)
3495  nulls[i] = true;
3496  else
3497  ereport(ERROR,
3498  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3499  errmsg("null array element not allowed in this context")));
3500  }
3501  else
3502  {
3503  elems[i] = fetch_att(p, elmbyval, elmlen);
3504  p = att_addlength_pointer(p, elmlen, p);
3505  p = (char *) att_align_nominal(p, elmalign);
3506  }
3507 
3508  /* advance bitmap pointer if any */
3509  if (bitmap)
3510  {
3511  bitmask <<= 1;
3512  if (bitmask == 0x100)
3513  {
3514  bitmap++;
3515  bitmask = 1;
3516  }
3517  }
3518  }
3519 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:146
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:174
#define ereport(elevel, rest)
Definition: elog.h:141
uint8 bits8
Definition: c.h:366
void * palloc0(Size size)
Definition: mcxt.c:980
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:733
#define ARR_NDIM(a)
Definition: array.h:278
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:73
int i
#define ARR_ELEMTYPE(a)
Definition: array.h:280
#define ARR_NULLBITMAP(a)
Definition: array.h:288

◆ deconstruct_expanded_array()

void deconstruct_expanded_array ( ExpandedArrayHeader eah)

Definition at line 424 of file array_expanded.c.

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

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

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

◆ expand_array()

Datum expand_array ( Datum  arraydatum,
MemoryContext  parentcontext,
ArrayMetaState metacache 
)

Definition at line 50 of file array_expanded.c.

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

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

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

◆ initArrayResult()

ArrayBuildState* initArrayResult ( Oid  element_type,
MemoryContext  rcontext,
bool  subcontext 
)

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

5015 {
5016  ArrayBuildState *astate;
5017  MemoryContext arr_context = rcontext;
5018 
5019  /* Make a temporary context to hold all the junk */
5020  if (subcontext)
5021  arr_context = AllocSetContextCreate(rcontext,
5022  "accumArrayResult",
5024 
5025  astate = (ArrayBuildState *)
5026  MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
5027  astate->mcontext = arr_context;
5028  astate->private_cxt = subcontext;
5029  astate->alen = (subcontext ? 64 : 8); /* arbitrary starting array size */
5030  astate->dvalues = (Datum *)
5031  MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
5032  astate->dnulls = (bool *)
5033  MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
5034  astate->nelems = 0;
5035  astate->element_type = element_type;
5036  get_typlenbyvalalign(element_type,
5037  &astate->typlen,
5038  &astate->typbyval,
5039  &astate->typalign);
5040 
5041  return astate;
5042 }
#define AllocSetContextCreate
Definition: memutils.h:170
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2049
Datum * dvalues
Definition: array.h:178
bool typbyval
Definition: array.h:184
Oid element_type
Definition: array.h:182
bool private_cxt
Definition: array.h:186
bool * dnulls
Definition: array.h:179
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
char typalign
Definition: array.h:185
uintptr_t Datum
Definition: postgres.h:367
MemoryContext mcontext
Definition: array.h:177
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
int16 typlen
Definition: array.h:183

◆ initArrayResultAny()

ArrayBuildStateAny* initArrayResultAny ( Oid  input_type,
MemoryContext  rcontext,
bool  subcontext 
)

Definition at line 5479 of file arrayfuncs.c.

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

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

5480 {
5481  ArrayBuildStateAny *astate;
5482  Oid element_type = get_element_type(input_type);
5483 
5484  if (OidIsValid(element_type))
5485  {
5486  /* Array case */
5487  ArrayBuildStateArr *arraystate;
5488 
5489  arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5490  astate = (ArrayBuildStateAny *)
5491  MemoryContextAlloc(arraystate->mcontext,
5492  sizeof(ArrayBuildStateAny));
5493  astate->scalarstate = NULL;
5494  astate->arraystate = arraystate;
5495  }
5496  else
5497  {
5498  /* Scalar case */
5499  ArrayBuildState *scalarstate;
5500 
5501  /* Let's just check that we have a type that can be put into arrays */
5502  Assert(OidIsValid(get_array_type(input_type)));
5503 
5504  scalarstate = initArrayResult(input_type, rcontext, subcontext);
5505  astate = (ArrayBuildStateAny *)
5506  MemoryContextAlloc(scalarstate->mcontext,
5507  sizeof(ArrayBuildStateAny));
5508  astate->scalarstate = scalarstate;
5509  astate->arraystate = NULL;
5510  }
5511 
5512  return astate;
5513 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5014
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2526
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2554
unsigned int Oid
Definition: postgres_ext.h:31
ArrayBuildState * scalarstate
Definition: array.h:217
#define OidIsValid(objectId)
Definition: c.h:639
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5201
ArrayBuildStateArr * arraystate
Definition: array.h:218
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:733
MemoryContext mcontext
Definition: array.h:177
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
MemoryContext mcontext
Definition: array.h:195

◆ initArrayResultArr()

ArrayBuildStateArr* initArrayResultArr ( Oid  array_type,
Oid  element_type,
MemoryContext  rcontext,
bool  subcontext 
)

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

5203 {
5204  ArrayBuildStateArr *astate;
5205  MemoryContext arr_context = rcontext; /* by default use the parent ctx */
5206 
5207  /* Lookup element type, unless element_type already provided */
5208  if (!OidIsValid(element_type))
5209  {
5210  element_type = get_element_type(array_type);
5211 
5212  if (!OidIsValid(element_type))
5213  ereport(ERROR,
5214  (errcode(ERRCODE_DATATYPE_MISMATCH),
5215  errmsg("data type %s is not an array type",
5216  format_type_be(array_type))));
5217  }
5218 
5219  /* Make a temporary context to hold all the junk */
5220  if (subcontext)
5221  arr_context = AllocSetContextCreate(rcontext,
5222  "accumArrayResultArr",
5224 
5225  /* Note we initialize all fields to zero */
5226  astate = (ArrayBuildStateArr *)
5227  MemoryContextAllocZero(arr_context, sizeof(ArrayBuildStateArr));
5228  astate->mcontext = arr_context;
5229  astate->private_cxt = subcontext;
5230 
5231  /* Save relevant datatype information */
5232  astate->array_type = array_type;
5233  astate->element_type = element_type;
5234 
5235  return astate;
5236 }
#define AllocSetContextCreate
Definition: memutils.h:170
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2526
int errcode(int sqlerrcode)
Definition: elog.c:608
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
#define OidIsValid(objectId)
Definition: c.h:639
#define ERROR
Definition: elog.h:43
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
#define ereport(elevel, rest)
Definition: elog.h:141
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
int errmsg(const char *fmt,...)
Definition: elog.c:822
bool private_cxt
Definition: array.h:207
MemoryContext mcontext
Definition: array.h:195

◆ makeArrayResult()

Datum makeArrayResult ( ArrayBuildState astate,
MemoryContext  rcontext 
)

Definition at line 5117 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(), pg_stats_ext_mcvlist_items(), regexp_split_to_array(), text_to_array_internal(), transformRelOptions(), tuple_data_split_internal(), and xpath().

5119 {
5120  int ndims;
5121  int dims[1];
5122  int lbs[1];
5123 
5124  /* If no elements were presented, we want to create an empty array */
5125  ndims = (astate->nelems > 0) ? 1 : 0;
5126  dims[0] = astate->nelems;
5127  lbs[0] = 1;
5128 
5129  return makeMdArrayResult(astate, ndims, dims, lbs, rcontext,
5130  astate->private_cxt);
5131 }
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5149
bool private_cxt
Definition: array.h:186

◆ makeArrayResultAny()

Datum makeArrayResultAny ( ArrayBuildStateAny astate,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5552 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5554 {
5555  Datum result;
5556 
5557  if (astate->scalarstate)
5558  {
5559  /* Must use makeMdArrayResult to support "release" parameter */
5560  int ndims;
5561  int dims[1];
5562  int lbs[1];
5563 
5564  /* If no elements were presented, we want to create an empty array */
5565  ndims = (astate->scalarstate->nelems > 0) ? 1 : 0;
5566  dims[0] = astate->scalarstate->nelems;
5567  lbs[0] = 1;
5568 
5569  result = makeMdArrayResult(astate->scalarstate, ndims, dims, lbs,
5570  rcontext, release);
5571  }
5572  else
5573  {
5574  result = makeArrayResultArr(astate->arraystate,
5575  rcontext, release);
5576  }
5577  return result;
5578 }
Datum makeArrayResultArr(ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5404
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5149
ArrayBuildState * scalarstate
Definition: array.h:217
ArrayBuildStateArr * arraystate
Definition: array.h:218
uintptr_t Datum
Definition: postgres.h:367

◆ makeArrayResultArr()

Datum makeArrayResultArr ( ArrayBuildStateArr astate,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5404 of file arrayfuncs.c.

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

Referenced by array_agg_array_finalfn(), and makeArrayResultAny().

5407 {
5408  ArrayType *result;
5409  MemoryContext oldcontext;
5410 
5411  /* Build the final array result in rcontext */
5412  oldcontext = MemoryContextSwitchTo(rcontext);
5413 
5414  if (astate->ndims == 0)
5415  {
5416  /* No inputs, return empty array */
5417  result = construct_empty_array(astate->element_type);
5418  }
5419  else
5420  {
5421  int dataoffset,
5422  nbytes;
5423 
5424  /* Compute required space */
5425  nbytes = astate->nbytes;
5426  if (astate->nullbitmap != NULL)
5427  {
5428  dataoffset = ARR_OVERHEAD_WITHNULLS(astate->ndims, astate->nitems);
5429  nbytes += dataoffset;
5430  }
5431  else
5432  {
5433  dataoffset = 0;
5434  nbytes += ARR_OVERHEAD_NONULLS(astate->ndims);
5435  }
5436 
5437  result = (ArrayType *) palloc0(nbytes);
5438  SET_VARSIZE(result, nbytes);
5439  result->ndim = astate->ndims;
5440  result->dataoffset = dataoffset;
5441  result->elemtype = astate->element_type;
5442 
5443  memcpy(ARR_DIMS(result), astate->dims, astate->ndims * sizeof(int));
5444  memcpy(ARR_LBOUND(result), astate->lbs, astate->ndims * sizeof(int));
5445  memcpy(ARR_DATA_PTR(result), astate->data, astate->nbytes);
5446 
5447  if (astate->nullbitmap != NULL)
5448  array_bitmap_copy(ARR_NULLBITMAP(result), 0,
5449  astate->nullbitmap, 0,
5450  astate->nitems);
5451  }
5452 
5453  MemoryContextSwitchTo(oldcontext);
5454 
5455  /* Clean up all the junk */
5456  if (release)
5457  {
5458  Assert(astate->private_cxt);
5459  MemoryContextDelete(astate->mcontext);
5460  }
5461 
5462  return PointerGetDatum(result);
5463 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define PointerGetDatum(X)
Definition: postgres.h:556
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4687
int32 dataoffset
Definition: array.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3410
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:300
#define ARR_LBOUND(a)
Definition: array.h:284
bits8 * nullbitmap
Definition: array.h:197
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
void * palloc0(Size size)
Definition: mcxt.c:980
int lbs[MAXDIM]
Definition: array.h:204
#define Assert(condition)
Definition: c.h:733
int dims[MAXDIM]
Definition: array.h:203
bool private_cxt
Definition: array.h:207
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
#define ARR_NULLBITMAP(a)
Definition: array.h:288
MemoryContext mcontext
Definition: array.h:195
int ndim
Definition: array.h:83

◆ makeMdArrayResult()

Datum makeMdArrayResult ( ArrayBuildState astate,
int  ndims,
int *  dims,
int *  lbs,
MemoryContext  rcontext,
bool  release 
)

Definition at line 5149 of file arrayfuncs.c.

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

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

5155 {
5156  ArrayType *result;
5157  MemoryContext oldcontext;
5158 
5159  /* Build the final array result in rcontext */
5160  oldcontext = MemoryContextSwitchTo(rcontext);
5161 
5162  result = construct_md_array(astate->dvalues,
5163  astate->dnulls,
5164  ndims,
5165  dims,
5166  lbs,
5167  astate->element_type,
5168  astate->typlen,
5169  astate->typbyval,
5170  astate->typalign);
5171 
5172  MemoryContextSwitchTo(oldcontext);
5173 
5174  /* Clean up all the junk */
5175  if (release)
5176  {
5177  Assert(astate->private_cxt);
5178  MemoryContextDelete(astate->mcontext);
5179  }
5180 
5181  return PointerGetDatum(result);
5182 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum * dvalues
Definition: array.h:178
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:184
Oid element_type
Definition: array.h:182
bool private_cxt
Definition: array.h:186
bool * dnulls
Definition: array.h:179
char typalign
Definition: array.h:185
#define Assert(condition)
Definition: c.h:733
MemoryContext mcontext
Definition: array.h:177
int16 typlen
Definition: array.h:183
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:3326

◆ mda_get_offset_values()

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

◆ mda_get_prod()

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

◆ mda_get_range()

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

◆ mda_next_tuple()

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

◆ Array_nulls

bool Array_nulls

Definition at line 40 of file arrayfuncs.c.

Referenced by ReadArrayStr().