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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Functions

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

Variables

bool Array_nulls
 

Macro Definition Documentation

◆ AARR_DIMS

#define AARR_DIMS (   a)

◆ AARR_ELEMTYPE

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

Definition at line 323 of file array.h.

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

◆ AARR_HASNULL

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

Definition at line 319 of file array.h.

Referenced by array_send().

◆ AARR_LBOUND

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

Definition at line 329 of file array.h.

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

◆ AARR_NDIM

#define AARR_NDIM (   a)

◆ ARR_DATA_OFFSET

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

◆ ARR_DATA_PTR

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

◆ ARR_DIMS

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

Definition at line 282 of file array.h.

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

◆ ARR_ELEMTYPE

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

Definition at line 280 of file array.h.

Referenced by _bt_preprocess_array_keys(), array_cat(), array_create_iterator(), array_get_slice(), array_iterate(), array_position_common(), array_positions(), array_replace_internal(), array_set_element(), array_set_slice(), array_to_json_internal(), array_to_jsonb_internal(), array_to_text_internal(), arrayconst_startup_fn(), ArrayGetIntegerTypmods(), build_function_result_tupdesc_d(), check_acl(), check_float8_array(), compute_array_stats(), 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(), new_intArrayType(), oidvectorrecv(), pg_extension_config_dump(), pg_get_functiondef(), pg_get_statisticsobj_worker(), pg_isolation_test_session_is_blocked(), pg_logical_slot_get_changes_guts(), plperl_ref_from_pg_array(), ProcedureCreate(), ProcessGUCArray(), RelationGetExclusionInfo(), satisfies_hash_partition(), scalararraysel(), SPI_sql_row_to_xmlelement(), text_format(), TryReuseForeignKey(), and width_bucket_array().

◆ ARR_HASNULL

◆ ARR_LBOUND

◆ ARR_NDIM

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

Definition at line 278 of file array.h.

Referenced by _arrq_cons(), _lca(), _lt_q_regex(), _ltree_compress(), accumArrayResultArr(), array_cat(), array_contains_nulls(), array_create_iterator(), array_fill_internal(), array_get_element(), array_get_slice(), array_insert_slice(), array_iterator(), array_position_common(), array_positions(), array_replace_internal(), array_set_element(), array_set_slice(), array_to_json_internal(), array_to_jsonb_internal(), array_to_text_internal(), ArrayGetIntegerTypmods(), arrq_cons(), build_function_result_tupdesc_d(), check_acl(), check_float8_array(), clause_is_strict_for(), count_nulls(), 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(), new_intArrayType(), oidvectorrecv(), parse_key_value_arrays(), percentile_cont_multi_final_common(), percentile_disc_multi_final(), pg_extension_config_dump(), pg_get_functiondef(), pg_get_statisticsobj_worker(), pg_isolation_test_session_is_blocked(), pg_logical_slot_get_changes_guts(), plperl_ref_from_pg_array(), PLyList_FromArray(), predicate_classify(), ProcedureCreate(), ProcessGUCArray(), RelationGetExclusionInfo(), resize_intArrayType(), SPI_sql_row_to_xmlelement(), TryReuseForeignKey(), width_bucket_array(), width_bucket_array_fixed(), width_bucket_array_float8(), and width_bucket_array_variable().

◆ ARR_NULLBITMAP

◆ ARR_OVERHEAD_NONULLS

◆ ARR_OVERHEAD_WITHNULLS

#define ARR_OVERHEAD_WITHNULLS (   ndims,
  nitems 
)

◆ ARR_SIZE

◆ DatumGetArrayTypeP

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

Definition at line 249 of file array.h.

Referenced by _bt_preprocess_array_keys(), _ltree_compress(), accumArrayResultArr(), AlterFunction(), AlterSetting(), ApplySetting(), array_get_element(), array_get_slice(), array_set(), array_set_element(), array_set_slice(), array_to_json_internal(), array_to_jsonb_internal(), arrayconst_startup_fn(), build_function_result_tupdesc_d(), calc_arraycontsel(), clause_is_strict_for(), compute_array_stats(), 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 */

◆ PG_GETARG_ANY_ARRAY_P

◆ PG_GETARG_ARRAYTYPE_P

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

Definition at line 251 of file array.h.

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

◆ PG_GETARG_ARRAYTYPE_P_COPY

◆ PG_GETARG_EXPANDED_ARRAY

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

Definition at line 256 of file array.h.

◆ PG_GETARG_EXPANDED_ARRAYX

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

Definition at line 257 of file array.h.

Referenced by fetch_array_arg_replace_nulls().

◆ PG_RETURN_ARRAYTYPE_P

◆ PG_RETURN_EXPANDED_ARRAY

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

Definition at line 259 of file array.h.

Typedef Documentation

◆ AnyArrayType

typedef union AnyArrayType AnyArrayType

◆ ArrayBuildState

◆ ArrayBuildStateAny

◆ ArrayBuildStateArr

◆ ArrayIterator

Definition at line 246 of file array.h.

◆ ArrayMapState

typedef struct ArrayMapState ArrayMapState

◆ ArrayMetaState

◆ ArrayType

typedef struct ArrayType ArrayType

◆ ExpandedArrayHeader

Function Documentation

◆ accumArrayResult()

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

Definition at line 5080 of file arrayfuncs.c.

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

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

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

◆ accumArrayResultAny()

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

Definition at line 5547 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

5551 {
5552  if (astate == NULL)
5553  astate = initArrayResultAny(input_type, rcontext, true);
5554 
5555  if (astate->scalarstate)
5556  (void) accumArrayResult(astate->scalarstate,
5557  dvalue, disnull,
5558  input_type, rcontext);
5559  else
5560  (void) accumArrayResultArr(astate->arraystate,
5561  dvalue, disnull,
5562  input_type, rcontext);
5563 
5564  return astate;
5565 }
ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5502
ArrayBuildState * scalarstate
Definition: array.h:217
ArrayBuildStateArr * accumArrayResultArr(ArrayBuildStateArr *astate, Datum dvalue, bool disnull, Oid array_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5274
ArrayBuildStateArr * arraystate
Definition: array.h:218
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5080

◆ accumArrayResultArr()

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

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

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

◆ array_bitmap_copy()

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

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

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

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

Definition at line 3550 of file arrayfuncs.c.

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

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

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

◆ array_create_iterator()

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

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

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

◆ array_free_iterator()

void array_free_iterator ( ArrayIterator  iterator)

Definition at line 4507 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4508 {
4509  if (iterator->slice_ndim > 0)
4510  {
4511  pfree(iterator->slice_values);
4512  pfree(iterator->slice_nulls);
4513  }
4514  pfree(iterator);
4515 }
bool * slice_nulls
Definition: arrayfuncs.c:84
void pfree(void *pointer)
Definition: mcxt.c:1056
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(), ATExecAlterColumnType(), ExecEvalSubscriptingRefFetch(), ExecEvalSubscriptingRefOld(), 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
#define MAXDIM
Definition: c.h:542
int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx)
Definition: arrayutils.c:31
#define ARR_LBOUND(a)
Definition: array.h:284
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
static Datum array_get_element_expanded(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1942
uint8 bits8
Definition: c.h:381
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:4614
static Datum ArrayCast(char *value, bool byval, int len)
Definition: arrayfuncs.c:4564
static bool array_get_isnull(const bits8 *nullbitmap, int offset)
Definition: arrayfuncs.c:4529
#define ARR_NDIM(a)
Definition: array.h:278
#define DatumGetPointer(X)
Definition: postgres.h:549
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:288
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ array_get_slice()

Datum array_get_slice ( Datum  arraydatum,
int  nSubscripts,
int *  upperIndx,
int *  lowerIndx,
bool upperProvided,
bool lowerProvided,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 2050 of file arrayfuncs.c.

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

Referenced by ExecEvalSubscriptingRefFetch(), and ExecEvalSubscriptingRefOld().

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

◆ array_iterate()

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

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

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

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

◆ array_ref()

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

Definition at line 3098 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3101 {
3102  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3103  arraytyplen, elmlen, elmbyval, elmalign,
3104  isNull);
3105 }
#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 3115 of file arrayfuncs.c.

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3118 {
3120  nSubscripts, indx,
3121  dataValue, isNull,
3122  arraytyplen,
3123  elmlen, elmbyval, elmalign));
3124 }
#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:2221
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ array_set_element()

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

Definition at line 2221 of file arrayfuncs.c.

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

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

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

◆ array_set_slice()

Datum array_set_slice ( Datum  arraydatum,
int  nSubscripts,
int *  upperIndx,
int *  lowerIndx,
bool upperProvided,
bool lowerProvided,
Datum  srcArrayDatum,
bool  isNull,
int  arraytyplen,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 2781 of file arrayfuncs.c.

References ARR_DATA_OFFSET, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ARR_SIZE, array_bitmap_copy(), array_insert_slice(), array_nelems_size(), array_slice_size(), ArrayGetNItems(), Assert, construct_md_array(), ArrayType::dataoffset, DatumGetArrayTypeP, deconstruct_array(), ArrayType::elemtype, ereport, errcode(), errdetail(), errmsg(), ERROR, i, Max, MAXDIM, mda_get_range(), MemSet, Min, ArrayType::ndim, ArrayIteratorData::nitems, palloc0(), PointerGetDatum, and SET_VARSIZE.

Referenced by ExecEvalSubscriptingRefAssign().

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

◆ ArrayGetIntegerTypmods()

int32* ArrayGetIntegerTypmods ( ArrayType arr,
int *  n 
)

Definition at line 200 of file arrayutils.c.

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

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

201 {
202  int32 *result;
203  Datum *elem_values;
204  int i;
205 
206  if (ARR_ELEMTYPE(arr) != CSTRINGOID)
207  ereport(ERROR,
208  (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
209  errmsg("typmod array must be type cstring[]")));
210 
211  if (ARR_NDIM(arr) != 1)
212  ereport(ERROR,
213  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
214  errmsg("typmod array must be one-dimensional")));
215 
216  if (array_contains_nulls(arr))
217  ereport(ERROR,
218  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
219  errmsg("typmod array must not contain nulls")));
220 
221  /* hardwired knowledge about cstring's representation details here */
222  deconstruct_array(arr, CSTRINGOID,
223  -2, false, 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:610
signed int int32
Definition: c.h:362
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:566
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:144
#define ARR_NDIM(a)
Definition: array.h:278
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:3483
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3550
#define ARR_ELEMTYPE(a)
Definition: array.h:280

◆ ArrayGetNItems()

int ArrayGetNItems ( int  ndim,
const int *  dims 
)

Definition at line 75 of file arrayutils.c.

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

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

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

◆ ArrayGetOffset()

int ArrayGetOffset ( int  n,
const int *  dim,
const int *  lb,
const int *  indx 
)

Definition at line 31 of file arrayutils.c.

References i, and scale.

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

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

◆ ArrayGetOffset0()

int ArrayGetOffset0 ( int  n,
const int *  tup,
const int *  scale 
)

Definition at line 50 of file arrayutils.c.

References i.

Referenced by ReadArrayStr().

51 {
52  int i,
53  lin = 0;
54 
55  for (i = 0; i < n; i++)
56  lin += tup[i] * scale[i];
57  return lin;
58 }
int scale
Definition: pgbench.c:153
int i

◆ construct_array()

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

◆ construct_empty_array()

◆ construct_empty_expanded_array()

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

Definition at line 3449 of file arrayfuncs.c.

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

Referenced by fetch_array_arg_replace_nulls().

3452 {
3453  ArrayType *array = construct_empty_array(element_type);
3454  Datum d;
3455 
3456  d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3457  pfree(array);
3458  return (ExpandedArrayHeader *) DatumGetEOHP(d);
3459 }
#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:3432
void pfree(void *pointer)
Definition: mcxt.c:1056
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
uintptr_t Datum
Definition: postgres.h:367

◆ construct_md_array()

ArrayType* construct_md_array ( Datum elems,
bool nulls,
int  ndims,
int *  dims,
int *  lbs,
Oid  elmtype,
int  elmlen,
bool  elmbyval,
char  elmalign 
)

Definition at line 3348 of file arrayfuncs.c.

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

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

3354 {
3355  ArrayType *result;
3356  bool hasnulls;
3357  int32 nbytes;
3358  int32 dataoffset;
3359  int i;
3360  int nelems;
3361 
3362  if (ndims < 0) /* we do allow zero-dimension arrays */
3363  ereport(ERROR,
3364  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3365  errmsg("invalid number of dimensions: %d", ndims)));
3366  if (ndims > MAXDIM)
3367  ereport(ERROR,
3368  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3369  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
3370  ndims, MAXDIM)));
3371 
3372  nelems = ArrayGetNItems(ndims, dims);
3373 
3374  /* if ndims <= 0 or any dims[i] == 0, return empty array */
3375  if (nelems <= 0)
3376  return construct_empty_array(elmtype);
3377 
3378  /* compute required space */
3379  nbytes = 0;
3380  hasnulls = false;
3381  for (i = 0; i < nelems; i++)
3382  {
3383  if (nulls && nulls[i])
3384  {
3385  hasnulls = true;
3386  continue;
3387  }
3388  /* make sure data is not toasted */
3389  if (elmlen == -1)
3390  elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i]));
3391  nbytes = att_addlength_datum(nbytes, elmlen, elems[i]);
3392  nbytes = att_align_nominal(nbytes, elmalign);
3393  /* check for overflow of total request */
3394  if (!AllocSizeIsValid(nbytes))
3395  ereport(ERROR,
3396  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3397  errmsg("array size exceeds the maximum allowed (%d)",
3398  (int) MaxAllocSize)));
3399  }
3400 
3401  /* Allocate and initialize result array */
3402  if (hasnulls)
3403  {
3404  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nelems);
3405  nbytes += dataoffset;
3406  }
3407  else
3408  {
3409  dataoffset = 0; /* marker for no null bitmap */
3410  nbytes += ARR_OVERHEAD_NONULLS(ndims);
3411  }
3412  result = (ArrayType *) palloc0(nbytes);
3413  SET_VARSIZE(result, nbytes);
3414  result->ndim = ndims;
3415  result->dataoffset = dataoffset;
3416  result->elemtype = elmtype;
3417  memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
3418  memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
3419 
3420  CopyArrayEls(result,
3421  elems, nulls, nelems,
3422  elmlen, elmbyval, elmalign,
3423  false);
3424 
3425  return result;
3426 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
#define MAXDIM
Definition: c.h:542
#define PointerGetDatum(X)
Definition: postgres.h:556
int32 dataoffset
Definition: array.h:84
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:610
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3432
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:300
signed int int32
Definition: c.h:362
#define ARR_LBOUND(a)
Definition: array.h:284
#define ERROR
Definition: elog.h:43
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:282
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define MaxAllocSize
Definition: memutils.h:40
void * palloc0(Size size)
Definition: mcxt.c:980
#define ereport(elevel,...)
Definition: elog.h:144
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:824
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:83

◆ 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:4575
void pfree(void *pointer)
Definition: mcxt.c:1056
char typalign
Definition: pg_type.h:170
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:310
uint8 bits8
Definition: c.h:381
#define DatumGetPointer(X)
Definition: postgres.h:549
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define elog(elevel,...)
Definition: elog.h:214
int i
#define ARR_NULLBITMAP(a)
Definition: array.h:288

◆ DatumGetAnyArrayP()

AnyArrayType* DatumGetAnyArrayP ( Datum  d)

Definition at line 401 of file array_expanded.c.

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

Referenced by array_map().

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

◆ DatumGetExpandedArrayX()

ExpandedArrayHeader* DatumGetExpandedArrayX ( Datum  d,
ArrayMetaState metacache 
)

Definition at line 372 of file array_expanded.c.

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

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

◆ deconstruct_array()

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

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

3487 {
3488  Datum *elems;
3489  bool *nulls;
3490  int nelems;
3491  char *p;
3492  bits8 *bitmap;
3493  int bitmask;
3494  int i;
3495 
3496  Assert(ARR_ELEMTYPE(array) == elmtype);
3497 
3498  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3499  *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
3500  if (nullsp)
3501  *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
3502  else
3503  nulls = NULL;
3504  *nelemsp = nelems;
3505 
3506  p = ARR_DATA_PTR(array);
3507  bitmap = ARR_NULLBITMAP(array);
3508  bitmask = 1;
3509 
3510  for (i = 0; i < nelems; i++)
3511  {
3512  /* Get source element, checking for NULL */
3513  if (bitmap && (*bitmap & bitmask) == 0)
3514  {
3515  elems[i] = (Datum) 0;
3516  if (nulls)
3517  nulls[i] = true;
3518  else
3519  ereport(ERROR,
3520  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3521  errmsg("null array element not allowed in this context")));
3522  }
3523  else
3524  {
3525  elems[i] = fetch_att(p, elmbyval, elmlen);
3526  p = att_addlength_pointer(p, elmlen, p);
3527  p = (char *) att_align_nominal(p, elmalign);
3528  }
3529 
3530  /* advance bitmap pointer if any */
3531  if (bitmap)
3532  {
3533  bitmask <<= 1;
3534  if (bitmask == 0x100)
3535  {
3536  bitmap++;
3537  bitmask = 1;
3538  }
3539  }
3540  }
3541 }
#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:610
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:176
uint8 bits8
Definition: c.h:381
void * palloc0(Size size)
Definition: mcxt.c:980
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:745
#define ARR_NDIM(a)
Definition: array.h:278
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:75
int i
#define ARR_ELEMTYPE(a)
Definition: array.h:280
#define ARR_NULLBITMAP(a)
Definition: array.h:288

◆ deconstruct_expanded_array()

void deconstruct_expanded_array ( ExpandedArrayHeader eah)

Definition at line 424 of file array_expanded.c.

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

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

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

◆ expand_array()

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

Definition at line 50 of file array_expanded.c.

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

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

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

◆ initArrayResult()

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

Definition at line 5041 of file arrayfuncs.c.

References ArrayBuildState::alen, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ArrayBuildState::dnulls, ArrayBuildState::dvalues, ArrayBuildState::element_type, get_typlenbyvalalign(), ArrayBuildState::mcontext, MemoryContextAlloc(), ArrayBuildState::nelems, ArrayBuildState::private_cxt, ArrayBuildState::typalign, ArrayBuildState::typbyval, and ArrayBuildState::typlen.

Referenced by accumArrayResult(), array_agg_transfn(), array_positions(), initArrayResultAny(), plperl_array_to_datum(), populate_array(), tuple_data_split_internal(), and xpath().

5042 {
5043  ArrayBuildState *astate;
5044  MemoryContext arr_context = rcontext;
5045 
5046  /* Make a temporary context to hold all the junk */
5047  if (subcontext)
5048  arr_context = AllocSetContextCreate(rcontext,
5049  "accumArrayResult",
5051 
5052  astate = (ArrayBuildState *)
5053  MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
5054  astate->mcontext = arr_context;
5055  astate->private_cxt = subcontext;
5056  astate->alen = (subcontext ? 64 : 8); /* arbitrary starting array size */
5057  astate->dvalues = (Datum *)
5058  MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
5059  astate->dnulls = (bool *)
5060  MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
5061  astate->nelems = 0;
5062  astate->element_type = element_type;
5063  get_typlenbyvalalign(element_type,
5064  &astate->typlen,
5065  &astate->typbyval,
5066  &astate->typalign);
5067 
5068  return astate;
5069 }
#define AllocSetContextCreate
Definition: memutils.h:170
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2159
Datum * dvalues
Definition: array.h:178
bool typbyval
Definition: array.h:184
Oid element_type
Definition: array.h:182
bool private_cxt
Definition: array.h:186
bool * dnulls
Definition: array.h:179
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
char typalign
Definition: array.h:185
uintptr_t Datum
Definition: postgres.h:367
MemoryContext mcontext
Definition: array.h:177
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
int16 typlen
Definition: array.h:183

◆ initArrayResultAny()

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

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

5503 {
5504  ArrayBuildStateAny *astate;
5505  Oid element_type = get_element_type(input_type);
5506 
5507  if (OidIsValid(element_type))
5508  {
5509  /* Array case */
5510  ArrayBuildStateArr *arraystate;
5511 
5512  arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5513  astate = (ArrayBuildStateAny *)
5514  MemoryContextAlloc(arraystate->mcontext,
5515  sizeof(ArrayBuildStateAny));
5516  astate->scalarstate = NULL;
5517  astate->arraystate = arraystate;
5518  }
5519  else
5520  {
5521  /* Scalar case */
5522  ArrayBuildState *scalarstate;
5523 
5524  /* Let's just check that we have a type that can be put into arrays */
5525  Assert(OidIsValid(get_array_type(input_type)));
5526 
5527  scalarstate = initArrayResult(input_type, rcontext, subcontext);
5528  astate = (ArrayBuildStateAny *)
5529  MemoryContextAlloc(scalarstate->mcontext,
5530  sizeof(ArrayBuildStateAny));
5531  astate->scalarstate = scalarstate;
5532  astate->arraystate = NULL;
5533  }
5534 
5535  return astate;
5536 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5041
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2636
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2664
unsigned int Oid
Definition: postgres_ext.h:31
ArrayBuildState * scalarstate
Definition: array.h:217
#define OidIsValid(objectId)
Definition: c.h:651
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5228
ArrayBuildStateArr * arraystate
Definition: array.h:218
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:745
MemoryContext mcontext
Definition: array.h:177
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
MemoryContext mcontext
Definition: array.h:195

◆ initArrayResultArr()

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

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

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

◆ makeArrayResult()

Datum makeArrayResult ( ArrayBuildState astate,
MemoryContext  rcontext 
)

Definition at line 5144 of file arrayfuncs.c.

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

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

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

◆ makeArrayResultAny()

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

Definition at line 5575 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

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

◆ makeArrayResultArr()

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

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

5430 {
5431  ArrayType *result;
5432  MemoryContext oldcontext;
5433 
5434  /* Build the final array result in rcontext */
5435  oldcontext = MemoryContextSwitchTo(rcontext);
5436 
5437  if (astate->ndims == 0)
5438  {
5439  /* No inputs, return empty array */
5440  result = construct_empty_array(astate->element_type);
5441  }
5442  else
5443  {
5444  int dataoffset,
5445  nbytes;
5446 
5447  /* Compute required space */
5448  nbytes = astate->nbytes;
5449  if (astate->nullbitmap != NULL)
5450  {
5451  dataoffset = ARR_OVERHEAD_WITHNULLS(astate->ndims, astate->nitems);
5452  nbytes += dataoffset;
5453  }
5454  else
5455  {
5456  dataoffset = 0;
5457  nbytes += ARR_OVERHEAD_NONULLS(astate->ndims);
5458  }
5459 
5460  result = (ArrayType *) palloc0(nbytes);
5461  SET_VARSIZE(result, nbytes);
5462  result->ndim = astate->ndims;
5463  result->dataoffset = dataoffset;
5464  result->elemtype = astate->element_type;
5465 
5466  memcpy(ARR_DIMS(result), astate->dims, astate->ndims * sizeof(int));
5467  memcpy(ARR_LBOUND(result), astate->lbs, astate->ndims * sizeof(int));
5468  memcpy(ARR_DATA_PTR(result), astate->data, astate->nbytes);
5469 
5470  if (astate->nullbitmap != NULL)
5471  array_bitmap_copy(ARR_NULLBITMAP(result), 0,
5472  astate->nullbitmap, 0,
5473  astate->nitems);
5474  }
5475 
5476  MemoryContextSwitchTo(oldcontext);
5477 
5478  /* Clean up all the junk */
5479  if (release)
5480  {
5481  Assert(astate->private_cxt);
5482  MemoryContextDelete(astate->mcontext);
5483  }
5484 
5485  return PointerGetDatum(result);
5486 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define PointerGetDatum(X)
Definition: postgres.h:556
void array_bitmap_copy(bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems)
Definition: arrayfuncs.c:4714
int32 dataoffset
Definition: array.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3432
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:300
#define ARR_LBOUND(a)
Definition: array.h:284
bits8 * nullbitmap
Definition: array.h:197
Oid elemtype
Definition: array.h:85
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
void * palloc0(Size size)
Definition: mcxt.c:980
int lbs[MAXDIM]
Definition: array.h:204
#define Assert(condition)
Definition: c.h:745
int dims[MAXDIM]
Definition: array.h:203
bool private_cxt
Definition: array.h:207
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
#define ARR_NULLBITMAP(a)
Definition: array.h:288
MemoryContext mcontext
Definition: array.h:195
int ndim
Definition: array.h:83

◆ makeMdArrayResult()

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

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

5182 {
5183  ArrayType *result;
5184  MemoryContext oldcontext;
5185 
5186  /* Build the final array result in rcontext */
5187  oldcontext = MemoryContextSwitchTo(rcontext);
5188 
5189  result = construct_md_array(astate->dvalues,
5190  astate->dnulls,
5191  ndims,
5192  dims,
5193  lbs,
5194  astate->element_type,
5195  astate->typlen,
5196  astate->typbyval,
5197  astate->typalign);
5198 
5199  MemoryContextSwitchTo(oldcontext);
5200 
5201  /* Clean up all the junk */
5202  if (release)
5203  {
5204  Assert(astate->private_cxt);
5205  MemoryContextDelete(astate->mcontext);
5206  }
5207 
5208  return PointerGetDatum(result);
5209 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum * dvalues
Definition: array.h:178
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool typbyval
Definition: array.h:184
Oid element_type
Definition: array.h:182
bool private_cxt
Definition: array.h:186
bool * dnulls
Definition: array.h:179
char typalign
Definition: array.h:185
#define Assert(condition)
Definition: c.h:745
MemoryContext mcontext
Definition: array.h:177
int16 typlen
Definition: array.h:183
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3348

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