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 MAXDIM   6
 
#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:285

Definition at line 328 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:284
#define VARATT_IS_EXPANDED_HEADER(PTR)

Definition at line 324 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:289
#define VARATT_IS_EXPANDED_HEADER(PTR)

Definition at line 334 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 287 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(), sanity_check_tid_array(), 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 285 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(), DecodeTextArrayToBitmapset(), 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(), mcv_get_match_bitmap(), multirange_constructor2(), 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 283 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(), DecodeTextArrayToBitmapset(), 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(), multirange_constructor2(), 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(), sanity_check_tid_array(), 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 254 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(), DecodeTextArrayToBitmapset(), decompile_column_index_array(), DeconstructFkConstraintRow(), estimate_array_length(), ExecEvalArrayExpr(), ExecEvalScalarArrayOp(), ExecIndexEvalArrayKeys(), extension_config_remove(), fetch_statentries_for_relation(), 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(), get_reloptions(), GetSubscription(), gincost_scalararrayopexpr(), is_strict_saop(), map_sql_value_to_xml_value(), match_clause_to_partition_key(), mcv_get_match_bitmap(), oid_array_to_list(), parseRelOptionsInternal(), 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 */

◆ MAXDIM

◆ PG_GETARG_ANY_ARRAY_P

◆ PG_GETARG_ARRAYTYPE_P

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

Definition at line 256 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(), multirange_constructor2(), 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 261 of file array.h.

◆ PG_GETARG_EXPANDED_ARRAYX

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

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

Typedef Documentation

◆ AnyArrayType

typedef union AnyArrayType AnyArrayType

◆ ArrayBuildState

◆ ArrayBuildStateAny

◆ ArrayBuildStateArr

◆ ArrayIterator

Definition at line 251 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 5085 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(), range_agg_transfn(), regexp_split_to_array(), SPI_sql_row_to_xmlelement(), split_text_accum_result(), transformRelOptions(), and tuple_data_split_internal().

5089 {
5090  MemoryContext oldcontext;
5091 
5092  if (astate == NULL)
5093  {
5094  /* First time through --- initialize */
5095  astate = initArrayResult(element_type, rcontext, true);
5096  }
5097  else
5098  {
5099  Assert(astate->element_type == element_type);
5100  }
5101 
5102  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5103 
5104  /* enlarge dvalues[]/dnulls[] if needed */
5105  if (astate->nelems >= astate->alen)
5106  {
5107  astate->alen *= 2;
5108  astate->dvalues = (Datum *)
5109  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5110  astate->dnulls = (bool *)
5111  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5112  }
5113 
5114  /*
5115  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5116  * it's varlena. (You might think that detoasting is not needed here
5117  * because construct_md_array can detoast the array elements later.
5118  * However, we must not let construct_md_array modify the ArrayBuildState
5119  * because that would mean array_agg_finalfn damages its input, which is
5120  * verboten. Also, this way frequently saves one copying step.)
5121  */
5122  if (!disnull && !astate->typbyval)
5123  {
5124  if (astate->typlen == -1)
5125  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5126  else
5127  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5128  }
5129 
5130  astate->dvalues[astate->nelems] = dvalue;
5131  astate->dnulls[astate->nelems] = disnull;
5132  astate->nelems++;
5133 
5134  MemoryContextSwitchTo(oldcontext);
5135 
5136  return astate;
5137 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5046
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum * dvalues
Definition: array.h:183
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:189
Oid element_type
Definition: array.h:187
bool * dnulls
Definition: array.h:184
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:792
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
MemoryContext mcontext
Definition: array.h:182
int16 typlen
Definition: array.h:188

◆ accumArrayResultAny()

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

Definition at line 5552 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5556 {
5557  if (astate == NULL)
5558  astate = initArrayResultAny(input_type, rcontext, true);
5559 
5560  if (astate->scalarstate)
5561  (void) accumArrayResult(astate->scalarstate,
5562  dvalue, disnull,
5563  input_type, rcontext);
5564  else
5565  (void) accumArrayResultArr(astate->arraystate,
5566  dvalue, disnull,
5567  input_type, rcontext);
5568 
5569  return astate;
5570 }
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5507
ArrayBuildState * scalarstate
Definition: array.h:222
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5279
ArrayBuildStateArr * arraystate
Definition: array.h:223
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5085

◆ accumArrayResultArr()

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

Definition at line 5279 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(), pg_nextpower2_32(), and repalloc().

Referenced by accumArrayResultAny(), and array_agg_array_transfn().

5283 {
5284  ArrayType *arg;
5285  MemoryContext oldcontext;
5286  int *dims,
5287  *lbs,
5288  ndims,
5289  nitems,
5290  ndatabytes;
5291  char *data;
5292  int i;
5293 
5294  /*
5295  * We disallow accumulating null subarrays. Another plausible definition
5296  * is to ignore them, but callers that want that can just skip calling
5297  * this function.
5298  */
5299  if (disnull)
5300  ereport(ERROR,
5301  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5302  errmsg("cannot accumulate null arrays")));
5303 
5304  /* Detoast input array in caller's context */
5305  arg = DatumGetArrayTypeP(dvalue);
5306 
5307  if (astate == NULL)
5308  astate = initArrayResultArr(array_type, InvalidOid, rcontext, true);
5309  else
5310  Assert(astate->array_type == array_type);
5311 
5312  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5313 
5314  /* Collect this input's dimensions */
5315  ndims = ARR_NDIM(arg);
5316  dims = ARR_DIMS(arg);
5317  lbs = ARR_LBOUND(arg);
5318  data = ARR_DATA_PTR(arg);
5319  nitems = ArrayGetNItems(ndims, dims);
5320  ndatabytes = ARR_SIZE(arg) - ARR_DATA_OFFSET(arg);
5321 
5322  if (astate->ndims == 0)
5323  {
5324  /* First input; check/save the dimensionality info */
5325 
5326  /* Should we allow empty inputs and just produce an empty output? */
5327  if (ndims == 0)
5328  ereport(ERROR,
5329  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5330  errmsg("cannot accumulate empty arrays")));
5331  if (ndims + 1 > MAXDIM)
5332  ereport(ERROR,
5333  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5334  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5335  ndims + 1, MAXDIM)));
5336 
5337  /*
5338  * The output array will have n+1 dimensions, with the ones after the
5339  * first matching the input's dimensions.
5340  */
5341  astate->ndims = ndims + 1;
5342  astate->dims[0] = 0;
5343  memcpy(&astate->dims[1], dims, ndims * sizeof(int));
5344  astate->lbs[0] = 1;
5345  memcpy(&astate->lbs[1], lbs, ndims * sizeof(int));
5346 
5347  /* Allocate at least enough data space for this item */
5348  astate->abytes = pg_nextpower2_32(Max(1024, ndatabytes + 1));
5349  astate->data = (char *) palloc(astate->abytes);
5350  }
5351  else
5352  {
5353  /* Second or later input: must match first input's dimensionality */
5354  if (astate->ndims != ndims + 1)
5355  ereport(ERROR,
5356  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5357  errmsg("cannot accumulate arrays of different dimensionality")));
5358  for (i = 0; i < ndims; i++)
5359  {
5360  if (astate->dims[i + 1] != dims[i] || astate->lbs[i + 1] != lbs[i])
5361  ereport(ERROR,
5362  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5363  errmsg("cannot accumulate arrays of different dimensionality")));
5364  }
5365 
5366  /* Enlarge data space if needed */
5367  if (astate->nbytes + ndatabytes > astate->abytes)
5368  {
5369  astate->abytes = Max(astate->abytes * 2,
5370  astate->nbytes + ndatabytes);
5371  astate->data = (char *) repalloc(astate->data, astate->abytes);
5372  }
5373  }
5374 
5375  /*
5376  * Copy the data portion of the sub-array. Note we assume that the
5377  * advertised data length of the sub-array is properly aligned. We do not
5378  * have to worry about detoasting elements since whatever's in the
5379  * sub-array should be OK already.
5380  */
5381  memcpy(astate->data + astate->nbytes, data, ndatabytes);
5382  astate->nbytes += ndatabytes;
5383 
5384  /* Deal with null bitmap if needed */
5385  if (astate->nullbitmap || ARR_HASNULL(arg))
5386  {
5387  int newnitems = astate->nitems + nitems;
5388 
5389  if (astate->nullbitmap == NULL)
5390  {
5391  /*
5392  * First input with nulls; we must retrospectively handle any
5393  * previous inputs by marking all their items non-null.
5394  */
5395  astate->aitems = pg_nextpower2_32(Max(256, newnitems + 1));
5396  astate->nullbitmap = (bits8 *) palloc((astate->aitems + 7) / 8);
5397  array_bitmap_copy(astate->nullbitmap, 0,
5398  NULL, 0,
5399  astate->nitems);
5400  }
5401  else if (newnitems > astate->aitems)
5402  {
5403  astate->aitems = Max(astate->aitems * 2, newnitems);
5404  astate->nullbitmap = (bits8 *)
5405  repalloc(astate->nullbitmap, (astate->aitems + 7) / 8);
5406  }
5407  array_bitmap_copy(astate->nullbitmap, astate->nitems,
5408  ARR_NULLBITMAP(arg), 0,
5409  nitems);
5410  }
5411 
5412  astate->nitems += nitems;
5413  astate->dims[0] += 1;
5414 
5415  MemoryContextSwitchTo(oldcontext);
5416 
5417  /* Release detoasted copy if any */
5418  if ((Pointer) arg != DatumGetPointer(dvalue))
5419  pfree(arg);
5420 
5421  return astate;
5422 }
#define ARR_SIZE(a)
Definition: array.h:282
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4719
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:704
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5233
#define ARR_DATA_OFFSET(a)
Definition: array.h:309
#define ARR_LBOUND(a)
Definition: array.h:289
bits8 * nullbitmap
Definition: array.h:202
void pfree(void *pointer)
Definition: mcxt.c:1057
char * Pointer
Definition: c.h:406
#define ERROR
Definition: elog.h:45
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define MAXDIM
Definition: array.h:75
static uint32 pg_nextpower2_32(uint32 num)
Definition: pg_bitutils.h:146
#define ARR_HASNULL(a)
Definition: array.h:284
uint8 bits8
Definition: c.h:436
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:155
int lbs[MAXDIM]
Definition: array.h:209
#define Max(x, y)
Definition: c.h:968
#define Assert(condition)
Definition: c.h:792
#define ARR_NDIM(a)
Definition: array.h:283
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
#define DatumGetPointer(X)
Definition: postgres.h:549
int dims[MAXDIM]
Definition: array.h:208
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:915
int i
void * arg
#define ARR_NULLBITMAP(a)
Definition: array.h:293
MemoryContext mcontext
Definition: array.h:200
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ array_bitmap_copy()

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

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

4722 {
4723  int destbitmask,
4724  destbitval,
4725  srcbitmask,
4726  srcbitval;
4727 
4728  Assert(destbitmap);
4729  if (nitems <= 0)
4730  return; /* don't risk fetch off end of memory */
4731  destbitmap += destoffset / 8;
4732  destbitmask = 1 << (destoffset % 8);
4733  destbitval = *destbitmap;
4734  if (srcbitmap)
4735  {
4736  srcbitmap += srcoffset / 8;
4737  srcbitmask = 1 << (srcoffset % 8);
4738  srcbitval = *srcbitmap;
4739  while (nitems-- > 0)
4740  {
4741  if (srcbitval & srcbitmask)
4742  destbitval |= destbitmask;
4743  else
4744  destbitval &= ~destbitmask;
4745  destbitmask <<= 1;
4746  if (destbitmask == 0x100)
4747  {
4748  *destbitmap++ = destbitval;
4749  destbitmask = 1;
4750  if (nitems > 0)
4751  destbitval = *destbitmap;
4752  }
4753  srcbitmask <<= 1;
4754  if (srcbitmask == 0x100)
4755  {
4756  srcbitmap++;
4757  srcbitmask = 1;
4758  if (nitems > 0)
4759  srcbitval = *srcbitmap;
4760  }
4761  }
4762  if (destbitmask != 1)
4763  *destbitmap = destbitval;
4764  }
4765  else
4766  {
4767  while (nitems-- > 0)
4768  {
4769  destbitval |= destbitmask;
4770  destbitmask <<= 1;
4771  if (destbitmask == 0x100)
4772  {
4773  *destbitmap++ = destbitval;
4774  destbitmask = 1;
4775  if (nitems > 0)
4776  destbitval = *destbitmap;
4777  }
4778  }
4779  if (destbitmask != 1)
4780  *destbitmap = destbitval;
4781  }
4782 }
#define Assert(condition)
Definition: c.h:792

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

Definition at line 3555 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(), sanity_check_tid_array(), and width_bucket_array().

3556 {
3557  int nelems;
3558  bits8 *bitmap;
3559  int bitmask;
3560 
3561  /* Easy answer if there's no null bitmap */
3562  if (!ARR_HASNULL(array))
3563  return false;
3564 
3565  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3566 
3567  bitmap = ARR_NULLBITMAP(array);
3568 
3569  /* check whole bytes of the bitmap byte-at-a-time */
3570  while (nelems >= 8)
3571  {
3572  if (*bitmap != 0xFF)
3573  return true;
3574  bitmap++;
3575  nelems -= 8;
3576  }
3577 
3578  /* check last partial byte */
3579  bitmask = 1;
3580  while (nelems > 0)
3581  {
3582  if ((*bitmap & bitmask) == 0)
3583  return true;
3584  bitmask <<= 1;
3585  nelems--;
3586  }
3587 
3588  return false;
3589 }
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_HASNULL(a)
Definition: array.h:284
uint8 bits8
Definition: c.h:436
#define ARR_NDIM(a)
Definition: array.h:283
#define ARR_NULLBITMAP(a)
Definition: array.h:293

◆ array_create_iterator()

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

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

4351 {
4352  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4353 
4354  /*
4355  * Sanity-check inputs --- caller should have got this right already
4356  */
4357  Assert(PointerIsValid(arr));
4358  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4359  elog(ERROR, "invalid arguments to array_create_iterator");
4360 
4361  /*
4362  * Remember basic info about the array and its element type
4363  */
4364  iterator->arr = arr;
4365  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4366  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4367 
4368  if (mstate != NULL)
4369  {
4370  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4371 
4372  iterator->typlen = mstate->typlen;
4373  iterator->typbyval = mstate->typbyval;
4374  iterator->typalign = mstate->typalign;
4375  }
4376  else
4378  &iterator->typlen,
4379  &iterator->typbyval,
4380  &iterator->typalign);
4381 
4382  /*
4383  * Remember the slicing parameters.
4384  */
4385  iterator->slice_ndim = slice_ndim;
4386 
4387  if (slice_ndim > 0)
4388  {
4389  /*
4390  * Get pointers into the array's dims and lbound arrays to represent
4391  * the dims/lbound arrays of a slice. These are the same as the
4392  * rightmost N dimensions of the array.
4393  */
4394  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4395  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4396 
4397  /*
4398  * Compute number of elements in a slice.
4399  */
4400  iterator->slice_len = ArrayGetNItems(slice_ndim,
4401  iterator->slice_dims);
4402 
4403  /*
4404  * Create workspace for building sub-arrays.
4405  */
4406  iterator->slice_values = (Datum *)
4407  palloc(iterator->slice_len * sizeof(Datum));
4408  iterator->slice_nulls = (bool *)
4409  palloc(iterator->slice_len * sizeof(bool));
4410  }
4411 
4412  /*
4413  * Initialize our data pointer and linear element number. These will
4414  * advance through the array during array_iterate().
4415  */
4416  iterator->data_ptr = ARR_DATA_PTR(arr);
4417  iterator->current_item = 0;
4418 
4419  return iterator;
4420 }
bits8 * nullbitmap
Definition: arrayfuncs.c:72
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2191
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
#define ARR_LBOUND(a)
Definition: array.h:289
bool typbyval
Definition: array.h:233
bool * slice_nulls
Definition: arrayfuncs.c:84
#define ERROR
Definition: elog.h:45
Datum * slice_values
Definition: arrayfuncs.c:83
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
int16 typlen
Definition: array.h:232
void * palloc0(Size size)
Definition: mcxt.c:981
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:792
#define ARR_NDIM(a)
Definition: array.h:283
char typalign
Definition: array.h:234
void * palloc(Size size)
Definition: mcxt.c:950
#define elog(elevel,...)
Definition: elog.h:228
Oid element_type
Definition: array.h:231
#define PointerIsValid(pointer)
Definition: c.h:686
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_NULLBITMAP(a)
Definition: array.h:293
ArrayType * arr
Definition: arrayfuncs.c:71

◆ array_free_iterator()

void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4512 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4513 {
4514  if (iterator->slice_ndim > 0)
4515  {
4516  pfree(iterator->slice_values);
4517  pfree(iterator->slice_nulls);
4518  }
4519  pfree(iterator);
4520 }
bool * slice_nulls
Definition: arrayfuncs.c:84
void pfree(void *pointer)
Definition: mcxt.c:1057
Datum * slice_values
Definition: arrayfuncs.c:83

◆ 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 1841 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(), array_subscript_fetch(), array_subscript_fetch_old(), ATExecAlterColumnType(), and RelationBuildTupleDesc().

1849 {
1850  int i,
1851  ndim,
1852  *dim,
1853  *lb,
1854  offset,
1855  fixedDim[1],
1856  fixedLb[1];
1857  char *arraydataptr,
1858  *retptr;
1859  bits8 *arraynullsptr;
1860 
1861  if (arraytyplen > 0)
1862  {
1863  /*
1864  * fixed-length arrays -- these are assumed to be 1-d, 0-based
1865  */
1866  ndim = 1;
1867  fixedDim[0] = arraytyplen / elmlen;
1868  fixedLb[0] = 0;
1869  dim = fixedDim;
1870  lb = fixedLb;
1871  arraydataptr = (char *) DatumGetPointer(arraydatum);
1872  arraynullsptr = NULL;
1873  }
1874  else if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(arraydatum)))
1875  {
1876  /* expanded array: let's do this in a separate function */
1877  return array_get_element_expanded(arraydatum,
1878  nSubscripts,
1879  indx,
1880  arraytyplen,
1881  elmlen,
1882  elmbyval,
1883  elmalign,
1884  isNull);
1885  }
1886  else
1887  {
1888  /* detoast array if necessary, producing normal varlena input */
1889  ArrayType *array = DatumGetArrayTypeP(arraydatum);
1890 
1891  ndim = ARR_NDIM(array);
1892  dim = ARR_DIMS(array);
1893  lb = ARR_LBOUND(array);
1894  arraydataptr = ARR_DATA_PTR(array);
1895  arraynullsptr = ARR_NULLBITMAP(array);
1896  }
1897 
1898  /*
1899  * Return NULL for invalid subscript
1900  */
1901  if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
1902  {
1903  *isNull = true;
1904  return (Datum) 0;
1905  }
1906  for (i = 0; i < ndim; i++)
1907  {
1908  if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
1909  {
1910  *isNull = true;
1911  return (Datum) 0;
1912  }
1913  }
1914 
1915  /*
1916  * Calculate the element number
1917  */
1918  offset = ArrayGetOffset(nSubscripts, dim, lb, indx);
1919 
1920  /*
1921  * Check for NULL array element
1922  */
1923  if (array_get_isnull(arraynullsptr, offset))
1924  {
1925  *isNull = true;
1926  return (Datum) 0;
1927  }
1928 
1929  /*
1930  * OK, get the element
1931  */
1932  *isNull = false;
1933  retptr = array_seek(arraydataptr, 0, arraynullsptr, offset,
1934  elmlen, elmbyval, elmalign);
1935  return ArrayCast(retptr, elmbyval, elmlen);
1936 }
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:322
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
#define ARR_LBOUND(a)
Definition: array.h:289
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
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:1942
#define MAXDIM
Definition: array.h:75
uint8 bits8
Definition: c.h:436
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:4619
static Datum ArrayCast(char *value, bool byval, int len)
Definition: arrayfuncs.c:4569
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4534
#define ARR_NDIM(a)
Definition: array.h:283
#define DatumGetPointer(X)
Definition: postgres.h:549
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:293
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ 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 2051 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 array_subscript_fetch_old_slice(), and array_subscript_fetch_slice().

2061 {
2062  ArrayType *array;
2063  ArrayType *newarray;
2064  int i,
2065  ndim,
2066  *dim,
2067  *lb,
2068  *newlb;
2069  int fixedDim[1],
2070  fixedLb[1];
2071  Oid elemtype;
2072  char *arraydataptr;
2073  bits8 *arraynullsptr;
2074  int32 dataoffset;
2075  int bytes,
2076  span[MAXDIM];
2077 
2078  if (arraytyplen > 0)
2079  {
2080  /*
2081  * fixed-length arrays -- currently, cannot slice these because parser
2082  * labels output as being of the fixed-length array type! Code below
2083  * shows how we could support it if the parser were changed to label
2084  * output as a suitable varlena array type.
2085  */
2086  ereport(ERROR,
2087  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2088  errmsg("slices of fixed-length arrays not implemented")));
2089 
2090  /*
2091  * fixed-length arrays -- these are assumed to be 1-d, 0-based
2092  *
2093  * XXX where would we get the correct ELEMTYPE from?
2094  */
2095  ndim = 1;
2096  fixedDim[0] = arraytyplen / elmlen;
2097  fixedLb[0] = 0;
2098  dim = fixedDim;
2099  lb = fixedLb;
2100  elemtype = InvalidOid; /* XXX */
2101  arraydataptr = (char *) DatumGetPointer(arraydatum);
2102  arraynullsptr = NULL;
2103  }
2104  else
2105  {
2106  /* detoast input array if necessary */
2107  array = DatumGetArrayTypeP(arraydatum);
2108 
2109  ndim = ARR_NDIM(array);
2110  dim = ARR_DIMS(array);
2111  lb = ARR_LBOUND(array);
2112  elemtype = ARR_ELEMTYPE(array);
2113  arraydataptr = ARR_DATA_PTR(array);
2114  arraynullsptr = ARR_NULLBITMAP(array);
2115  }
2116 
2117  /*
2118  * Check provided subscripts. A slice exceeding the current array limits
2119  * is silently truncated to the array limits. If we end up with an empty
2120  * slice, return an empty array.
2121  */
2122  if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
2123  return PointerGetDatum(construct_empty_array(elemtype));
2124 
2125  for (i = 0; i < nSubscripts; i++)
2126  {
2127  if (!lowerProvided[i] || lowerIndx[i] < lb[i])
2128  lowerIndx[i] = lb[i];
2129  if (!upperProvided[i] || upperIndx[i] >= (dim[i] + lb[i]))
2130  upperIndx[i] = dim[i] + lb[i] - 1;
2131  if (lowerIndx[i] > upperIndx[i])
2132  return PointerGetDatum(construct_empty_array(elemtype));
2133  }
2134  /* fill any missing subscript positions with full array range */
2135  for (; i < ndim; i++)
2136  {
2137  lowerIndx[i] = lb[i];
2138  upperIndx[i] = dim[i] + lb[i] - 1;
2139  if (lowerIndx[i] > upperIndx[i])
2140  return PointerGetDatum(construct_empty_array(elemtype));
2141  }
2142 
2143  mda_get_range(ndim, span, lowerIndx, upperIndx);
2144 
2145  bytes = array_slice_size(arraydataptr, arraynullsptr,
2146  ndim, dim, lb,
2147  lowerIndx, upperIndx,
2148  elmlen, elmbyval, elmalign);
2149 
2150  /*
2151  * Currently, we put a null bitmap in the result if the source has one;
2152  * could be smarter ...
2153  */
2154  if (arraynullsptr)
2155  {
2156  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, ArrayGetNItems(ndim, span));
2157  bytes += dataoffset;
2158  }
2159  else
2160  {
2161  dataoffset = 0; /* marker for no null bitmap */
2162  bytes += ARR_OVERHEAD_NONULLS(ndim);
2163  }
2164 
2165  newarray = (ArrayType *) palloc0(bytes);
2166  SET_VARSIZE(newarray, bytes);
2167  newarray->ndim = ndim;
2168  newarray->dataoffset = dataoffset;
2169  newarray->elemtype = elemtype;
2170  memcpy(ARR_DIMS(newarray), span, ndim * sizeof(int));
2171 
2172  /*
2173  * Lower bounds of the new array are set to 1. Formerly (before 7.3) we
2174  * copied the given lowerIndx values ... but that seems confusing.
2175  */
2176  newlb = ARR_LBOUND(newarray);
2177  for (i = 0; i < ndim; i++)
2178  newlb[i] = 1;
2179 
2180  array_extract_slice(newarray,
2181  ndim, dim, lb,
2182  arraydataptr, arraynullsptr,
2183  lowerIndx, upperIndx,
2184  elmlen, elmbyval, elmalign);
2185 
2186  return PointerGetDatum(newarray);
2187 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
#define PointerGetDatum(X)
Definition: postgres.h:556
def bytes(source, encoding='ascii', errors='strict')
int32 dataoffset
Definition: array.h:89
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:4790
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:704
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:4850
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3437
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
signed int int32
Definition: c.h:417
#define ARR_LBOUND(a)
Definition: array.h:289
#define ERROR
Definition: elog.h:45
Oid elemtype
Definition: array.h:90
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define MAXDIM
Definition: array.h:75
uint8 bits8
Definition: c.h:436
void * palloc0(Size size)
Definition: mcxt.c:981
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 ereport(elevel,...)
Definition: elog.h:155
#define ARR_NDIM(a)
Definition: array.h:283
#define DatumGetPointer(X)
Definition: postgres.h:549
int errmsg(const char *fmt,...)
Definition: elog.c:915
int i
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_NULLBITMAP(a)
Definition: array.h:293
int ndim
Definition: array.h:88
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ array_iterate()

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

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

4430 {
4431  /* Done if we have reached the end of the array */
4432  if (iterator->current_item >= iterator->nitems)
4433  return false;
4434 
4435  if (iterator->slice_ndim == 0)
4436  {
4437  /*
4438  * Scalar case: return one element.
4439  */
4440  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4441  {
4442  *isnull = true;
4443  *value = (Datum) 0;
4444  }
4445  else
4446  {
4447  /* non-NULL, so fetch the individual Datum to return */
4448  char *p = iterator->data_ptr;
4449 
4450  *isnull = false;
4451  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4452 
4453  /* Move our data pointer forward to the next element */
4454  p = att_addlength_pointer(p, iterator->typlen, p);
4455  p = (char *) att_align_nominal(p, iterator->typalign);
4456  iterator->data_ptr = p;
4457  }
4458  }
4459  else
4460  {
4461  /*
4462  * Slice case: build and return an array of the requested size.
4463  */
4464  ArrayType *result;
4465  Datum *values = iterator->slice_values;
4466  bool *nulls = iterator->slice_nulls;
4467  char *p = iterator->data_ptr;
4468  int i;
4469 
4470  for (i = 0; i < iterator->slice_len; i++)
4471  {
4472  if (array_get_isnull(iterator->nullbitmap,
4473  iterator->current_item++))
4474  {
4475  nulls[i] = true;
4476  values[i] = (Datum) 0;
4477  }
4478  else
4479  {
4480  nulls[i] = false;
4481  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4482 
4483  /* Move our data pointer forward to the next element */
4484  p = att_addlength_pointer(p, iterator->typlen, p);
4485  p = (char *) att_align_nominal(p, iterator->typalign);
4486  }
4487  }
4488 
4489  iterator->data_ptr = p;
4490 
4491  result = construct_md_array(values,
4492  nulls,
4493  iterator->slice_ndim,
4494  iterator->slice_dims,
4495  iterator->slice_lbound,
4496  ARR_ELEMTYPE(iterator->arr),
4497  iterator->typlen,
4498  iterator->typbyval,
4499  iterator->typalign);
4500 
4501  *isnull = false;
4502  *value = PointerGetDatum(result);
4503  }
4504 
4505  return true;
4506 }
bits8 * nullbitmap
Definition: arrayfuncs.c:72
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
#define PointerGetDatum(X)
Definition: postgres.h:556
static struct @144 value
bool * slice_nulls
Definition: arrayfuncs.c:84
Datum * slice_values
Definition: arrayfuncs.c:83
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:176
uintptr_t Datum
Definition: postgres.h:367
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4534
static Datum values[MAXATTR]
Definition: bootstrap.c:165
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:75
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:3353
#define ARR_ELEMTYPE(a)
Definition: array.h:285
ArrayType * arr
Definition: arrayfuncs.c:71

◆ array_map()

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

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

3161 {
3162  AnyArrayType *v = DatumGetAnyArrayP(arrayd);
3163  ArrayType *result;
3164  Datum *values;
3165  bool *nulls;
3166  int *dim;
3167  int ndim;
3168  int nitems;
3169  int i;
3170  int32 nbytes = 0;
3171  int32 dataoffset;
3172  bool hasnulls;
3173  Oid inpType;
3174  int inp_typlen;
3175  bool inp_typbyval;
3176  char inp_typalign;
3177  int typlen;
3178  bool typbyval;
3179  char typalign;
3180  array_iter iter;
3181  ArrayMetaState *inp_extra;
3182  ArrayMetaState *ret_extra;
3183  Datum *transform_source = exprstate->innermost_caseval;
3184  bool *transform_source_isnull = exprstate->innermost_casenull;
3185 
3186  inpType = AARR_ELEMTYPE(v);
3187  ndim = AARR_NDIM(v);
3188  dim = AARR_DIMS(v);
3189  nitems = ArrayGetNItems(ndim, dim);
3190 
3191  /* Check for empty array */
3192  if (nitems <= 0)
3193  {
3194  /* Return empty array */
3195  return PointerGetDatum(construct_empty_array(retType));
3196  }
3197 
3198  /*
3199  * We arrange to look up info about input and return element types only
3200  * once per series of calls, assuming the element type doesn't change
3201  * underneath us.
3202  */
3203  inp_extra = &amstate->inp_extra;
3204  ret_extra = &amstate->ret_extra;
3205 
3206  if (inp_extra->element_type != inpType)
3207  {
3208  get_typlenbyvalalign(inpType,
3209  &inp_extra->typlen,
3210  &inp_extra->typbyval,
3211  &inp_extra->typalign);
3212  inp_extra->element_type = inpType;
3213  }
3214  inp_typlen = inp_extra->typlen;
3215  inp_typbyval = inp_extra->typbyval;
3216  inp_typalign = inp_extra->typalign;
3217 
3218  if (ret_extra->element_type != retType)
3219  {
3220  get_typlenbyvalalign(retType,
3221  &ret_extra->typlen,
3222  &ret_extra->typbyval,
3223  &ret_extra->typalign);
3224  ret_extra->element_type = retType;
3225  }
3226  typlen = ret_extra->typlen;
3227  typbyval = ret_extra->typbyval;
3228  typalign = ret_extra->typalign;
3229 
3230  /* Allocate temporary arrays for new values */
3231  values = (Datum *) palloc(nitems * sizeof(Datum));
3232  nulls = (bool *) palloc(nitems * sizeof(bool));
3233 
3234  /* Loop over source data */
3235  array_iter_setup(&iter, v);
3236  hasnulls = false;
3237 
3238  for (i = 0; i < nitems; i++)
3239  {
3240  /* Get source element, checking for NULL */
3241  *transform_source =
3242  array_iter_next(&iter, transform_source_isnull, i,
3243  inp_typlen, inp_typbyval, inp_typalign);
3244 
3245  /* Apply the given expression to source element */
3246  values[i] = ExecEvalExpr(exprstate, econtext, &nulls[i]);
3247 
3248  if (nulls[i])
3249  hasnulls = true;
3250  else
3251  {
3252  /* Ensure data is not toasted */
3253  if (typlen == -1)
3254  values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
3255  /* Update total result size */
3256  nbytes = att_addlength_datum(nbytes, typlen, values[i]);
3257  nbytes = att_align_nominal(nbytes, typalign);
3258  /* check for overflow of total request */
3259  if (!AllocSizeIsValid(nbytes))
3260  ereport(ERROR,
3261  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3262  errmsg("array size exceeds the maximum allowed (%d)",
3263  (int) MaxAllocSize)));
3264  }
3265  }
3266 
3267  /* Allocate and fill the result array */
3268  if (hasnulls)
3269  {
3270  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3271  nbytes += dataoffset;
3272  }
3273  else
3274  {
3275  dataoffset = 0; /* marker for no null bitmap */
3276  nbytes += ARR_OVERHEAD_NONULLS(ndim);
3277  }
3278  result = (ArrayType *) palloc0(nbytes);
3279  SET_VARSIZE(result, nbytes);
3280  result->ndim = ndim;
3281  result->dataoffset = dataoffset;
3282  result->elemtype = retType;
3283  memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
3284  memcpy(ARR_LBOUND(result), AARR_LBOUND(v), ndim * sizeof(int));
3285 
3286  CopyArrayEls(result,
3287  values, nulls, nitems,
3288  typlen, typbyval, typalign,
3289  false);
3290 
3291  /*
3292  * Note: do not risk trying to pfree the results of the called expression
3293  */
3294  pfree(values);
3295  pfree(nulls);
3296 
3297  return PointerGetDatum(result);
3298 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
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:2191
#define PointerGetDatum(X)
Definition: postgres.h:556
bool * innermost_casenull
Definition: execnodes.h:111
int32 dataoffset
Definition: array.h:89
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:704
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3437
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
signed int int32
Definition: c.h:417
AnyArrayType * DatumGetAnyArrayP(Datum d)
#define ARR_LBOUND(a)
Definition: array.h:289
bool typbyval
Definition: array.h:233
void pfree(void *pointer)
Definition: mcxt.c:1057
char typalign
Definition: pg_type.h:176
#define ERROR
Definition: elog.h:45
Oid elemtype
Definition: array.h:90
#define ARR_DIMS(a)
Definition: array.h:287
ArrayMetaState inp_extra
Definition: array.h:246
int16 typlen
Definition: array.h:232
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:292
static void array_iter_setup(array_iter *it, AnyArrayType *a)
Definition: arrayaccess.h:49
Datum * innermost_caseval
Definition: execnodes.h:110
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void * palloc0(Size size)
Definition: mcxt.c:981
uintptr_t Datum
Definition: postgres.h:367
#define AARR_DIMS(a)
Definition: array.h:331
#define AARR_ELEMTYPE(a)
Definition: array.h:328
#define ereport(elevel,...)
Definition: elog.h:155
#define AARR_LBOUND(a)
Definition: array.h:334
#define AARR_NDIM(a)
Definition: array.h:321
ArrayMetaState ret_extra
Definition: array.h:247
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:958
char typalign
Definition: array.h:234
static Datum values[MAXATTR]
Definition: bootstrap.c:165
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:164
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:915
int i
Oid element_type
Definition: array.h:231
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
int ndim
Definition: array.h:88

◆ array_ref()

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

Definition at line 3103 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3106 {
3107  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3108  arraytyplen, elmlen, elmbyval, elmalign,
3109  isNull);
3110 }
#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:1841

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

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3123 {
3125  nSubscripts, indx,
3126  dataValue, isNull,
3127  arraytyplen,
3128  elmlen, elmbyval, elmalign));
3129 }
#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:2222
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ 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 2222 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(), and array_subscript_assign().

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

◆ 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 2786 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 array_subscript_assign_slice().

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

◆ 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, TYPALIGN_CHAR,
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:704
signed int int32
Definition: c.h:417
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:45
#define DatumGetCString(X)
Definition: postgres.h:566
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:155
#define ARR_NDIM(a)
Definition: array.h:283
int32 pg_strtoint32(const char *s)
Definition: numutils.c:263
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3488
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:915
int i
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3555
#define ARR_ELEMTYPE(a)
Definition: array.h:285

◆ 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(), sanity_check_tid_array(), 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:704
signed int int32
Definition: c.h:417
#define ERROR
Definition: elog.h:45
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:792
size_t Size
Definition: c.h:528
int errmsg(const char *fmt,...)
Definition: elog.c:915
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:154
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:154
int i

◆ construct_array()

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

Definition at line 3318 of file arrayfuncs.c.

References construct_md_array().

Referenced by AlterPolicy(), ATExecAlterColumnType(), bt_page_print_tuples(), build_regtype_array(), convert_requires_to_datum(), CreateConstraintEntry(), CreateFunction(), CreatePolicy(), CreateStatistics(), current_schemas(), enum_range_internal(), extension_config_remove(), filter_list_to_array(), float4_accum(), float8_accum(), float8_combine(), float8_regr_accum(), float8_regr_combine(), gethba_options(), gin_leafpage_items(), gin_page_opaque_info(), gist_page_opaque_info(), GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), hash_metapage_info(), heap_tuple_infomask_flags(), hstore_akeys(), interpret_function_parameter_list(), interval_accum(), interval_accum_inv(), interval_combine(), makeMultirangeConstructors(), pg_blocking_pids(), pg_extension_config_dump(), pg_safe_snapshot_blocking_pids(), publicationListToArray(), RemoveRoleFromObjectPolicy(), show_trgm(), StoreAttrDefault(), test_rls_hooks_permissive(), test_rls_hooks_restrictive(), ts_lexize(), tsvector_to_array(), tsvector_unnest(), typenameTypeMod(), and update_attstats().

3321 {
3322  int dims[1];
3323  int lbs[1];
3324 
3325  dims[0] = nelems;
3326  lbs[0] = 1;
3327 
3328  return construct_md_array(elems, NULL, 1, dims, lbs,
3329  elmtype, elmlen, elmbyval, elmalign);
3330 }
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:3353

◆ construct_empty_array()

◆ construct_empty_expanded_array()

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

Definition at line 3454 of file arrayfuncs.c.

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

Referenced by fetch_array_arg_replace_nulls().

3457 {
3458  ArrayType *array = construct_empty_array(element_type);
3459  Datum d;
3460 
3461  d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3462  pfree(array);
3463  return (ExpandedArrayHeader *) DatumGetEOHP(d);
3464 }
#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:3437
void pfree(void *pointer)
Definition: mcxt.c:1057
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 3353 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(), build_test_info_result(), build_test_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(), and strlist_to_textarray().

3359 {
3360  ArrayType *result;
3361  bool hasnulls;
3362  int32 nbytes;
3363  int32 dataoffset;
3364  int i;
3365  int nelems;
3366 
3367  if (ndims < 0) /* we do allow zero-dimension arrays */
3368  ereport(ERROR,
3369  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3370  errmsg("invalid number of dimensions: %d", ndims)));
3371  if (ndims > MAXDIM)
3372  ereport(ERROR,
3373  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3374  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
3375  ndims, MAXDIM)));
3376 
3377  nelems = ArrayGetNItems(ndims, dims);
3378 
3379  /* if ndims <= 0 or any dims[i] == 0, return empty array */
3380  if (nelems <= 0)
3381  return construct_empty_array(elmtype);
3382 
3383  /* compute required space */
3384  nbytes = 0;
3385  hasnulls = false;
3386  for (i = 0; i < nelems; i++)
3387  {
3388  if (nulls && nulls[i])
3389  {
3390  hasnulls = true;
3391  continue;
3392  }
3393  /* make sure data is not toasted */
3394  if (elmlen == -1)
3395  elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i]));
3396  nbytes = att_addlength_datum(nbytes, elmlen, elems[i]);
3397  nbytes = att_align_nominal(nbytes, elmalign);
3398  /* check for overflow of total request */
3399  if (!AllocSizeIsValid(nbytes))
3400  ereport(ERROR,
3401  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3402  errmsg("array size exceeds the maximum allowed (%d)",
3403  (int) MaxAllocSize)));
3404  }
3405 
3406  /* Allocate and initialize result array */
3407  if (hasnulls)
3408  {
3409  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nelems);
3410  nbytes += dataoffset;
3411  }
3412  else
3413  {
3414  dataoffset = 0; /* marker for no null bitmap */
3415  nbytes += ARR_OVERHEAD_NONULLS(ndims);
3416  }
3417  result = (ArrayType *) palloc0(nbytes);
3418  SET_VARSIZE(result, nbytes);
3419  result->ndim = ndims;
3420  result->dataoffset = dataoffset;
3421  result->elemtype = elmtype;
3422  memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
3423  memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
3424 
3425  CopyArrayEls(result,
3426  elems, nulls, nelems,
3427  elmlen, elmbyval, elmalign,
3428  false);
3429 
3430  return result;
3431 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
#define PointerGetDatum(X)
Definition: postgres.h:556
int32 dataoffset
Definition: array.h:89
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:704
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3437
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
signed int int32
Definition: c.h:417
#define ARR_LBOUND(a)
Definition: array.h:289
#define ERROR
Definition: elog.h:45
Oid elemtype
Definition: array.h:90
#define ARR_DIMS(a)
Definition: array.h:287
#define MAXDIM
Definition: array.h:75
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void * palloc0(Size size)
Definition: mcxt.c:981
#define ereport(elevel,...)
Definition: elog.h:155
void CopyArrayEls(ArrayType *array, Datum *values, bool *nulls, int nitems, int typlen, bool typbyval, char typalign, bool freedata)
Definition: arrayfuncs.c:958
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:164
int errmsg(const char *fmt,...)
Definition: elog.c:915
int i
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
int ndim
Definition: array.h:88

◆ CopyArrayEls()

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

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

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

◆ 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:106
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:792
#define DatumGetPointer(X)
Definition: postgres.h:549
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240

◆ 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:106
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:792
#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:106
bool typbyval
Definition: array.h:233
int16 typlen
Definition: array.h:232
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
#define Assert(condition)
Definition: c.h:792
#define DatumGetPointer(X)
Definition: postgres.h:549
char typalign
Definition: array.h:234
Oid element_type
Definition: array.h:231
#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 3488 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(), DecodeTextArrayToBitmapset(), decompile_column_index_array(), deconstruct_expanded_array(), ExecIndexEvalArrayKeys(), extension_config_remove(), extract_variadic_args(), generateClonedIndexStmt(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_jsonb_path_all(), get_path_all(), get_reloptions(), 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(), mcv_get_match_bitmap(), multirange_constructor2(), oid_array_to_list(), parse_key_value_arrays(), parseRelOptionsInternal(), 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().

3492 {
3493  Datum *elems;
3494  bool *nulls;
3495  int nelems;
3496  char *p;
3497  bits8 *bitmap;
3498  int bitmask;
3499  int i;
3500 
3501  Assert(ARR_ELEMTYPE(array) == elmtype);
3502 
3503  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3504  *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
3505  if (nullsp)
3506  *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
3507  else
3508  nulls = NULL;
3509  *nelemsp = nelems;
3510 
3511  p = ARR_DATA_PTR(array);
3512  bitmap = ARR_NULLBITMAP(array);
3513  bitmask = 1;
3514 
3515  for (i = 0; i < nelems; i++)
3516  {
3517  /* Get source element, checking for NULL */
3518  if (bitmap && (*bitmap & bitmask) == 0)
3519  {
3520  elems[i] = (Datum) 0;
3521  if (nulls)
3522  nulls[i] = true;
3523  else
3524  ereport(ERROR,
3525  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3526  errmsg("null array element not allowed in this context")));
3527  }
3528  else
3529  {
3530  elems[i] = fetch_att(p, elmbyval, elmlen);
3531  p = att_addlength_pointer(p, elmlen, p);
3532  p = (char *) att_align_nominal(p, elmalign);
3533  }
3534 
3535  /* advance bitmap pointer if any */
3536  if (bitmap)
3537  {
3538  bitmask <<= 1;
3539  if (bitmask == 0x100)
3540  {
3541  bitmap++;
3542  bitmask = 1;
3543  }
3544  }
3545  }
3546 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:704
#define ERROR
Definition: elog.h:45
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:176
uint8 bits8
Definition: c.h:436
void * palloc0(Size size)
Definition: mcxt.c:981
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:792
#define ARR_NDIM(a)
Definition: array.h:283
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:915
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:75
int i
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_NULLBITMAP(a)
Definition: array.h:293

◆ 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:139
ExpandedObjectHeader hdr
Definition: array.h:111
#define ARR_HASNULL(a)
Definition: array.h:284
ArrayType * fvalue
Definition: array.h:158
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:3488
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:282
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:322
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2191
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Datum * dvalues
Definition: array.h:139
char * fendptr
Definition: array.h:160
#define EA_MAGIC
Definition: array.h:106
#define ARR_LBOUND(a)
Definition: array.h:289
bool typbyval
Definition: array.h:233
ExpandedObjectHeader hdr
Definition: array.h:111
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
int16 typlen
Definition: array.h:232
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:158
#define DatumGetArrayTypePCopy(X)
Definition: array.h:255
#define Assert(condition)
Definition: c.h:792
#define ARR_NDIM(a)
Definition: array.h:283
#define DatumGetPointer(X)
Definition: postgres.h:549
char typalign
Definition: array.h:234
#define EOHPGetRWDatum(eohptr)
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
char * fstartptr
Definition: array.h:159
Oid element_type
Definition: array.h:231
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:209
#define ARR_ELEMTYPE(a)
Definition: array.h:285

◆ initArrayResult()

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

Definition at line 5046 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(), range_agg_transfn(), tuple_data_split_internal(), and xpath().

5047 {
5048  ArrayBuildState *astate;
5049  MemoryContext arr_context = rcontext;
5050 
5051  /* Make a temporary context to hold all the junk */
5052  if (subcontext)
5053  arr_context = AllocSetContextCreate(rcontext,
5054  "accumArrayResult",
5056 
5057  astate = (ArrayBuildState *)
5058  MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
5059  astate->mcontext = arr_context;
5060  astate->private_cxt = subcontext;
5061  astate->alen = (subcontext ? 64 : 8); /* arbitrary starting array size */
5062  astate->dvalues = (Datum *)
5063  MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
5064  astate->dnulls = (bool *)
5065  MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
5066  astate->nelems = 0;
5067  astate->element_type = element_type;
5068  get_typlenbyvalalign(element_type,
5069  &astate->typlen,
5070  &astate->typbyval,
5071  &astate->typalign);
5072 
5073  return astate;
5074 }
#define AllocSetContextCreate
Definition: memutils.h:170
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2191
Datum * dvalues
Definition: array.h:183
bool typbyval
Definition: array.h:189
Oid element_type
Definition: array.h:187
bool private_cxt
Definition: array.h:191
bool * dnulls
Definition: array.h:184
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
char typalign
Definition: array.h:190
uintptr_t Datum
Definition: postgres.h:367
MemoryContext mcontext
Definition: array.h:182
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
int16 typlen
Definition: array.h:188

◆ initArrayResultAny()

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

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

5508 {
5509  ArrayBuildStateAny *astate;
5510  Oid element_type = get_element_type(input_type);
5511 
5512  if (OidIsValid(element_type))
5513  {
5514  /* Array case */
5515  ArrayBuildStateArr *arraystate;
5516 
5517  arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5518  astate = (ArrayBuildStateAny *)
5519  MemoryContextAlloc(arraystate->mcontext,
5520  sizeof(ArrayBuildStateAny));
5521  astate->scalarstate = NULL;
5522  astate->arraystate = arraystate;
5523  }
5524  else
5525  {
5526  /* Scalar case */
5527  ArrayBuildState *scalarstate;
5528 
5529  /* Let's just check that we have a type that can be put into arrays */
5530  Assert(OidIsValid(get_array_type(input_type)));
5531 
5532  scalarstate = initArrayResult(input_type, rcontext, subcontext);
5533  astate = (ArrayBuildStateAny *)
5534  MemoryContextAlloc(scalarstate->mcontext,
5535  sizeof(ArrayBuildStateAny));
5536  astate->scalarstate = scalarstate;
5537  astate->arraystate = NULL;
5538  }
5539 
5540  return astate;
5541 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5046
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2679
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2707
unsigned int Oid
Definition: postgres_ext.h:31
ArrayBuildState * scalarstate
Definition: array.h:222
#define OidIsValid(objectId)
Definition: c.h:698
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5233
ArrayBuildStateArr * arraystate
Definition: array.h:223
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:792
MemoryContext mcontext
Definition: array.h:182
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
MemoryContext mcontext
Definition: array.h:200

◆ initArrayResultArr()

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

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

5235 {
5236  ArrayBuildStateArr *astate;
5237  MemoryContext arr_context = rcontext; /* by default use the parent ctx */
5238 
5239  /* Lookup element type, unless element_type already provided */
5240  if (!OidIsValid(element_type))
5241  {
5242  element_type = get_element_type(array_type);
5243 
5244  if (!OidIsValid(element_type))
5245  ereport(ERROR,
5246  (errcode(ERRCODE_DATATYPE_MISMATCH),
5247  errmsg("data type %s is not an array type",
5248  format_type_be(array_type))));
5249  }
5250 
5251  /* Make a temporary context to hold all the junk */
5252  if (subcontext)
5253  arr_context = AllocSetContextCreate(rcontext,
5254  "accumArrayResultArr",
5256 
5257  /* Note we initialize all fields to zero */
5258  astate = (ArrayBuildStateArr *)
5259  MemoryContextAllocZero(arr_context, sizeof(ArrayBuildStateArr));
5260  astate->mcontext = arr_context;
5261  astate->private_cxt = subcontext;
5262 
5263  /* Save relevant datatype information */
5264  astate->array_type = array_type;
5265  astate->element_type = element_type;
5266 
5267  return astate;
5268 }
#define AllocSetContextCreate
Definition: memutils.h:170
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2679
int errcode(int sqlerrcode)
Definition: elog.c:704
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define OidIsValid(objectId)
Definition: c.h:698
#define ERROR
Definition: elog.h:45
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:915
bool private_cxt
Definition: array.h:212
MemoryContext mcontext
Definition: array.h:200

◆ makeArrayResult()

Datum makeArrayResult ( ArrayBuildState astate,
MemoryContext  rcontext 
)

Definition at line 5149 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(), transformRelOptions(), tuple_data_split_internal(), and xpath().

5151 {
5152  int ndims;
5153  int dims[1];
5154  int lbs[1];
5155 
5156  /* If no elements were presented, we want to create an empty array */
5157  ndims = (astate->nelems > 0) ? 1 : 0;
5158  dims[0] = astate->nelems;
5159  lbs[0] = 1;
5160 
5161  return makeMdArrayResult(astate, ndims, dims, lbs, rcontext,
5162  astate->private_cxt);
5163 }
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5181
bool private_cxt
Definition: array.h:191

◆ makeArrayResultAny()

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

Definition at line 5580 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5582 {
5583  Datum result;
5584 
5585  if (astate->scalarstate)
5586  {
5587  /* Must use makeMdArrayResult to support "release" parameter */
5588  int ndims;
5589  int dims[1];
5590  int lbs[1];
5591 
5592  /* If no elements were presented, we want to create an empty array */
5593  ndims = (astate->scalarstate->nelems > 0) ? 1 : 0;
5594  dims[0] = astate->scalarstate->nelems;
5595  lbs[0] = 1;
5596 
5597  result = makeMdArrayResult(astate->scalarstate, ndims, dims, lbs,
5598  rcontext, release);
5599  }
5600  else
5601  {
5602  result = makeArrayResultArr(astate->arraystate,
5603  rcontext, release);
5604  }
5605  return result;
5606 }
Datum makeArrayResultArr(ArrayBuildStateArr *astate, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5432
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5181
ArrayBuildState * scalarstate
Definition: array.h:222
ArrayBuildStateArr * arraystate
Definition: array.h:223
uintptr_t Datum
Definition: postgres.h:367

◆ makeArrayResultArr()

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

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

5435 {
5436  ArrayType *result;
5437  MemoryContext oldcontext;
5438 
5439  /* Build the final array result in rcontext */
5440  oldcontext = MemoryContextSwitchTo(rcontext);
5441 
5442  if (astate->ndims == 0)
5443  {
5444  /* No inputs, return empty array */
5445  result = construct_empty_array(astate->element_type);
5446  }
5447  else
5448  {
5449  int dataoffset,
5450  nbytes;
5451 
5452  /* Compute required space */
5453  nbytes = astate->nbytes;
5454  if (astate->nullbitmap != NULL)
5455  {
5456  dataoffset = ARR_OVERHEAD_WITHNULLS(astate->ndims, astate->nitems);
5457  nbytes += dataoffset;
5458  }
5459  else
5460  {
5461  dataoffset = 0;
5462  nbytes += ARR_OVERHEAD_NONULLS(astate->ndims);
5463  }
5464 
5465  result = (ArrayType *) palloc0(nbytes);
5466  SET_VARSIZE(result, nbytes);
5467  result->ndim = astate->ndims;
5468  result->dataoffset = dataoffset;
5469  result->elemtype = astate->element_type;
5470 
5471  memcpy(ARR_DIMS(result), astate->dims, astate->ndims * sizeof(int));
5472  memcpy(ARR_LBOUND(result), astate->lbs, astate->ndims * sizeof(int));
5473  memcpy(ARR_DATA_PTR(result), astate->data, astate->nbytes);
5474 
5475  if (astate->nullbitmap != NULL)
5476  array_bitmap_copy(ARR_NULLBITMAP(result), 0,
5477  astate->nullbitmap, 0,
5478  astate->nitems);
5479  }
5480 
5481  MemoryContextSwitchTo(oldcontext);
5482 
5483  /* Clean up all the junk */
5484  if (release)
5485  {
5486  Assert(astate->private_cxt);
5487  MemoryContextDelete(astate->mcontext);
5488  }
5489 
5490  return PointerGetDatum(result);
5491 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:212
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
#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:4719
int32 dataoffset
Definition: array.h:89
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3437
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:305
#define ARR_LBOUND(a)
Definition: array.h:289
bits8 * nullbitmap
Definition: array.h:202
Oid elemtype
Definition: array.h:90
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
void * palloc0(Size size)
Definition: mcxt.c:981
int lbs[MAXDIM]
Definition: array.h:209
#define Assert(condition)
Definition: c.h:792
int dims[MAXDIM]
Definition: array.h:208
bool private_cxt
Definition: array.h:212
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
#define ARR_NULLBITMAP(a)
Definition: array.h:293
MemoryContext mcontext
Definition: array.h:200
int ndim
Definition: array.h:88

◆ makeMdArrayResult()

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

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

5187 {
5188  ArrayType *result;
5189  MemoryContext oldcontext;
5190 
5191  /* Build the final array result in rcontext */
5192  oldcontext = MemoryContextSwitchTo(rcontext);
5193 
5194  result = construct_md_array(astate->dvalues,
5195  astate->dnulls,
5196  ndims,
5197  dims,
5198  lbs,
5199  astate->element_type,
5200  astate->typlen,
5201  astate->typbyval,
5202  astate->typalign);
5203 
5204  MemoryContextSwitchTo(oldcontext);
5205 
5206  /* Clean up all the junk */
5207  if (release)
5208  {
5209  Assert(astate->private_cxt);
5210  MemoryContextDelete(astate->mcontext);
5211  }
5212 
5213  return PointerGetDatum(result);
5214 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:212
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum * dvalues
Definition: array.h:183
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:189
Oid element_type
Definition: array.h:187
bool private_cxt
Definition: array.h:191
bool * dnulls
Definition: array.h:184
char typalign
Definition: array.h:190
#define Assert(condition)
Definition: c.h:792
MemoryContext mcontext
Definition: array.h:182
int16 typlen
Definition: array.h:188
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:3353

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

Referenced by ReadArrayStr().