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

5063 {
5064  MemoryContext oldcontext;
5065 
5066  if (astate == NULL)
5067  {
5068  /* First time through --- initialize */
5069  astate = initArrayResult(element_type, rcontext, true);
5070  }
5071  else
5072  {
5073  Assert(astate->element_type == element_type);
5074  }
5075 
5076  oldcontext = MemoryContextSwitchTo(astate->mcontext);
5077 
5078  /* enlarge dvalues[]/dnulls[] if needed */
5079  if (astate->nelems >= astate->alen)
5080  {
5081  astate->alen *= 2;
5082  astate->dvalues = (Datum *)
5083  repalloc(astate->dvalues, astate->alen * sizeof(Datum));
5084  astate->dnulls = (bool *)
5085  repalloc(astate->dnulls, astate->alen * sizeof(bool));
5086  }
5087 
5088  /*
5089  * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if
5090  * it's varlena. (You might think that detoasting is not needed here
5091  * because construct_md_array can detoast the array elements later.
5092  * However, we must not let construct_md_array modify the ArrayBuildState
5093  * because that would mean array_agg_finalfn damages its input, which is
5094  * verboten. Also, this way frequently saves one copying step.)
5095  */
5096  if (!disnull && !astate->typbyval)
5097  {
5098  if (astate->typlen == -1)
5099  dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue));
5100  else
5101  dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen);
5102  }
5103 
5104  astate->dvalues[astate->nelems] = dvalue;
5105  astate->dnulls[astate->nelems] = disnull;
5106  astate->nelems++;
5107 
5108  MemoryContextSwitchTo(oldcontext);
5109 
5110  return astate;
5111 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5020
#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:738
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 5526 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

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

◆ accumArrayResultArr()

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

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

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

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

◆ array_contains_nulls()

bool array_contains_nulls ( ArrayType array)

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

3530 {
3531  int nelems;
3532  bits8 *bitmap;
3533  int bitmask;
3534 
3535  /* Easy answer if there's no null bitmap */
3536  if (!ARR_HASNULL(array))
3537  return false;
3538 
3539  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3540 
3541  bitmap = ARR_NULLBITMAP(array);
3542 
3543  /* check whole bytes of the bitmap byte-at-a-time */
3544  while (nelems >= 8)
3545  {
3546  if (*bitmap != 0xFF)
3547  return true;
3548  bitmap++;
3549  nelems -= 8;
3550  }
3551 
3552  /* check last partial byte */
3553  bitmask = 1;
3554  while (nelems > 0)
3555  {
3556  if ((*bitmap & bitmask) == 0)
3557  return true;
3558  bitmask <<= 1;
3559  nelems--;
3560  }
3561 
3562  return false;
3563 }
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:374
#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 4324 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().

4325 {
4326  ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData));
4327 
4328  /*
4329  * Sanity-check inputs --- caller should have got this right already
4330  */
4331  Assert(PointerIsValid(arr));
4332  if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr))
4333  elog(ERROR, "invalid arguments to array_create_iterator");
4334 
4335  /*
4336  * Remember basic info about the array and its element type
4337  */
4338  iterator->arr = arr;
4339  iterator->nullbitmap = ARR_NULLBITMAP(arr);
4340  iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
4341 
4342  if (mstate != NULL)
4343  {
4344  Assert(mstate->element_type == ARR_ELEMTYPE(arr));
4345 
4346  iterator->typlen = mstate->typlen;
4347  iterator->typbyval = mstate->typbyval;
4348  iterator->typalign = mstate->typalign;
4349  }
4350  else
4352  &iterator->typlen,
4353  &iterator->typbyval,
4354  &iterator->typalign);
4355 
4356  /*
4357  * Remember the slicing parameters.
4358  */
4359  iterator->slice_ndim = slice_ndim;
4360 
4361  if (slice_ndim > 0)
4362  {
4363  /*
4364  * Get pointers into the array's dims and lbound arrays to represent
4365  * the dims/lbound arrays of a slice. These are the same as the
4366  * rightmost N dimensions of the array.
4367  */
4368  iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim;
4369  iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim;
4370 
4371  /*
4372  * Compute number of elements in a slice.
4373  */
4374  iterator->slice_len = ArrayGetNItems(slice_ndim,
4375  iterator->slice_dims);
4376 
4377  /*
4378  * Create workspace for building sub-arrays.
4379  */
4380  iterator->slice_values = (Datum *)
4381  palloc(iterator->slice_len * sizeof(Datum));
4382  iterator->slice_nulls = (bool *)
4383  palloc(iterator->slice_len * sizeof(bool));
4384  }
4385 
4386  /*
4387  * Initialize our data pointer and linear element number. These will
4388  * advance through the array during array_iterate().
4389  */
4390  iterator->data_ptr = ARR_DATA_PTR(arr);
4391  iterator->current_item = 0;
4392 
4393  return iterator;
4394 }
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:738
#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:632
#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 4486 of file arrayfuncs.c.

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

Referenced by array_position_common(), and array_positions().

4487 {
4488  if (iterator->slice_ndim > 0)
4489  {
4490  pfree(iterator->slice_values);
4491  pfree(iterator->slice_nulls);
4492  }
4493  pfree(iterator);
4494 }
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 1820 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().

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

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

4404 {
4405  /* Done if we have reached the end of the array */
4406  if (iterator->current_item >= iterator->nitems)
4407  return false;
4408 
4409  if (iterator->slice_ndim == 0)
4410  {
4411  /*
4412  * Scalar case: return one element.
4413  */
4414  if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
4415  {
4416  *isnull = true;
4417  *value = (Datum) 0;
4418  }
4419  else
4420  {
4421  /* non-NULL, so fetch the individual Datum to return */
4422  char *p = iterator->data_ptr;
4423 
4424  *isnull = false;
4425  *value = fetch_att(p, iterator->typbyval, iterator->typlen);
4426 
4427  /* Move our data pointer forward to the next element */
4428  p = att_addlength_pointer(p, iterator->typlen, p);
4429  p = (char *) att_align_nominal(p, iterator->typalign);
4430  iterator->data_ptr = p;
4431  }
4432  }
4433  else
4434  {
4435  /*
4436  * Slice case: build and return an array of the requested size.
4437  */
4438  ArrayType *result;
4439  Datum *values = iterator->slice_values;
4440  bool *nulls = iterator->slice_nulls;
4441  char *p = iterator->data_ptr;
4442  int i;
4443 
4444  for (i = 0; i < iterator->slice_len; i++)
4445  {
4446  if (array_get_isnull(iterator->nullbitmap,
4447  iterator->current_item++))
4448  {
4449  nulls[i] = true;
4450  values[i] = (Datum) 0;
4451  }
4452  else
4453  {
4454  nulls[i] = false;
4455  values[i] = fetch_att(p, iterator->typbyval, iterator->typlen);
4456 
4457  /* Move our data pointer forward to the next element */
4458  p = att_addlength_pointer(p, iterator->typlen, p);
4459  p = (char *) att_align_nominal(p, iterator->typalign);
4460  }
4461  }
4462 
4463  iterator->data_ptr = p;
4464 
4465  result = construct_md_array(values,
4466  nulls,
4467  iterator->slice_ndim,
4468  iterator->slice_dims,
4469  iterator->slice_lbound,
4470  ARR_ELEMTYPE(iterator->arr),
4471  iterator->typlen,
4472  iterator->typbyval,
4473  iterator->typalign);
4474 
4475  *isnull = false;
4476  *value = PointerGetDatum(result);
4477  }
4478 
4479  return true;
4480 }
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:4508
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:3327
#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 3132 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().

3135 {
3136  AnyArrayType *v = DatumGetAnyArrayP(arrayd);
3137  ArrayType *result;
3138  Datum *values;
3139  bool *nulls;
3140  int *dim;
3141  int ndim;
3142  int nitems;
3143  int i;
3144  int32 nbytes = 0;
3145  int32 dataoffset;
3146  bool hasnulls;
3147  Oid inpType;
3148  int inp_typlen;
3149  bool inp_typbyval;
3150  char inp_typalign;
3151  int typlen;
3152  bool typbyval;
3153  char typalign;
3154  array_iter iter;
3155  ArrayMetaState *inp_extra;
3156  ArrayMetaState *ret_extra;
3157  Datum *transform_source = exprstate->innermost_caseval;
3158  bool *transform_source_isnull = exprstate->innermost_casenull;
3159 
3160  inpType = AARR_ELEMTYPE(v);
3161  ndim = AARR_NDIM(v);
3162  dim = AARR_DIMS(v);
3163  nitems = ArrayGetNItems(ndim, dim);
3164 
3165  /* Check for empty array */
3166  if (nitems <= 0)
3167  {
3168  /* Return empty array */
3169  return PointerGetDatum(construct_empty_array(retType));
3170  }
3171 
3172  /*
3173  * We arrange to look up info about input and return element types only
3174  * once per series of calls, assuming the element type doesn't change
3175  * underneath us.
3176  */
3177  inp_extra = &amstate->inp_extra;
3178  ret_extra = &amstate->ret_extra;
3179 
3180  if (inp_extra->element_type != inpType)
3181  {
3182  get_typlenbyvalalign(inpType,
3183  &inp_extra->typlen,
3184  &inp_extra->typbyval,
3185  &inp_extra->typalign);
3186  inp_extra->element_type = inpType;
3187  }
3188  inp_typlen = inp_extra->typlen;
3189  inp_typbyval = inp_extra->typbyval;
3190  inp_typalign = inp_extra->typalign;
3191 
3192  if (ret_extra->element_type != retType)
3193  {
3194  get_typlenbyvalalign(retType,
3195  &ret_extra->typlen,
3196  &ret_extra->typbyval,
3197  &ret_extra->typalign);
3198  ret_extra->element_type = retType;
3199  }
3200  typlen = ret_extra->typlen;
3201  typbyval = ret_extra->typbyval;
3202  typalign = ret_extra->typalign;
3203 
3204  /* Allocate temporary arrays for new values */
3205  values = (Datum *) palloc(nitems * sizeof(Datum));
3206  nulls = (bool *) palloc(nitems * sizeof(bool));
3207 
3208  /* Loop over source data */
3209  array_iter_setup(&iter, v);
3210  hasnulls = false;
3211 
3212  for (i = 0; i < nitems; i++)
3213  {
3214  /* Get source element, checking for NULL */
3215  *transform_source =
3216  array_iter_next(&iter, transform_source_isnull, i,
3217  inp_typlen, inp_typbyval, inp_typalign);
3218 
3219  /* Apply the given expression to source element */
3220  values[i] = ExecEvalExpr(exprstate, econtext, &nulls[i]);
3221 
3222  if (nulls[i])
3223  hasnulls = true;
3224  else
3225  {
3226  /* Ensure data is not toasted */
3227  if (typlen == -1)
3228  values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
3229  /* Update total result size */
3230  nbytes = att_addlength_datum(nbytes, typlen, values[i]);
3231  nbytes = att_align_nominal(nbytes, typalign);
3232  /* check for overflow of total request */
3233  if (!AllocSizeIsValid(nbytes))
3234  ereport(ERROR,
3235  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3236  errmsg("array size exceeds the maximum allowed (%d)",
3237  (int) MaxAllocSize)));
3238  }
3239  }
3240 
3241  /* Allocate and fill the result array */
3242  if (hasnulls)
3243  {
3244  dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
3245  nbytes += dataoffset;
3246  }
3247  else
3248  {
3249  dataoffset = 0; /* marker for no null bitmap */
3250  nbytes += ARR_OVERHEAD_NONULLS(ndim);
3251  }
3252  result = (ArrayType *) palloc0(nbytes);
3253  SET_VARSIZE(result, nbytes);
3254  result->ndim = ndim;
3255  result->dataoffset = dataoffset;
3256  result->elemtype = retType;
3257  memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
3258  memcpy(ARR_LBOUND(result), AARR_LBOUND(v), ndim * sizeof(int));
3259 
3260  CopyArrayEls(result,
3261  values, nulls, nitems,
3262  typlen, typbyval, typalign,
3263  false);
3264 
3265  /*
3266  * Note: do not risk trying to pfree the results of the called expression
3267  */
3268  pfree(values);
3269  pfree(nulls);
3270 
3271  return PointerGetDatum(result);
3272 }
#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:3411
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:300
signed int int32
Definition: c.h:355
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 3077 of file arrayfuncs.c.

References array_get_element(), and PointerGetDatum.

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

3080 {
3081  return array_get_element(PointerGetDatum(array), nSubscripts, indx,
3082  arraytyplen, elmlen, elmbyval, elmalign,
3083  isNull);
3084 }
#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:1820

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

References array_set_element(), DatumGetArrayTypeP, and PointerGetDatum.

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

3097 {
3099  nSubscripts, indx,
3100  dataValue, isNull,
3101  arraytyplen,
3102  elmlen, elmbyval, elmalign));
3103 }
#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:2200
#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 2200 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().

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

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

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

Referenced by fetch_array_arg_replace_nulls().

3431 {
3432  ArrayType *array = construct_empty_array(element_type);
3433  Datum d;
3434 
3435  d = expand_array(PointerGetDatum(array), parentcontext, metacache);
3436  pfree(array);
3437  return (ExpandedArrayHeader *) DatumGetEOHP(d);
3438 }
#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:3411
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 3327 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().

3333 {
3334  ArrayType *result;
3335  bool hasnulls;
3336  int32 nbytes;
3337  int32 dataoffset;
3338  int i;
3339  int nelems;
3340 
3341  if (ndims < 0) /* we do allow zero-dimension arrays */
3342  ereport(ERROR,
3343  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3344  errmsg("invalid number of dimensions: %d", ndims)));
3345  if (ndims > MAXDIM)
3346  ereport(ERROR,
3347  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3348  errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
3349  ndims, MAXDIM)));
3350 
3351  nelems = ArrayGetNItems(ndims, dims);
3352 
3353  /* if ndims <= 0 or any dims[i] == 0, return empty array */
3354  if (nelems <= 0)
3355  return construct_empty_array(elmtype);
3356 
3357  /* compute required space */
3358  nbytes = 0;
3359  hasnulls = false;
3360  for (i = 0; i < nelems; i++)
3361  {
3362  if (nulls && nulls[i])
3363  {
3364  hasnulls = true;
3365  continue;
3366  }
3367  /* make sure data is not toasted */
3368  if (elmlen == -1)
3369  elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i]));
3370  nbytes = att_addlength_datum(nbytes, elmlen, elems[i]);
3371  nbytes = att_align_nominal(nbytes, elmalign);
3372  /* check for overflow of total request */
3373  if (!AllocSizeIsValid(nbytes))
3374  ereport(ERROR,
3375  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3376  errmsg("array size exceeds the maximum allowed (%d)",
3377  (int) MaxAllocSize)));
3378  }
3379 
3380  /* Allocate and initialize result array */
3381  if (hasnulls)
3382  {
3383  dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nelems);
3384  nbytes += dataoffset;
3385  }
3386  else
3387  {
3388  dataoffset = 0; /* marker for no null bitmap */
3389  nbytes += ARR_OVERHEAD_NONULLS(ndims);
3390  }
3391  result = (ArrayType *) palloc0(nbytes);
3392  SET_VARSIZE(result, nbytes);
3393  result->ndim = ndims;
3394  result->dataoffset = dataoffset;
3395  result->elemtype = elmtype;
3396  memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
3397  memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
3398 
3399  CopyArrayEls(result,
3400  elems, nulls, nelems,
3401  elmlen, elmbyval, elmalign,
3402  false);
3403 
3404  return result;
3405 }
#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:535
#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:3411
#define ARR_OVERHEAD_WITHNULLS(ndims, nitems)
Definition: array.h:300
signed int int32
Definition: c.h:355
#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:4554
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:374
#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:738
#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:738
#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:738
#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 3462 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().

3466 {
3467  Datum *elems;
3468  bool *nulls;
3469  int nelems;
3470  char *p;
3471  bits8 *bitmap;
3472  int bitmask;
3473  int i;
3474 
3475  Assert(ARR_ELEMTYPE(array) == elmtype);
3476 
3477  nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
3478  *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
3479  if (nullsp)
3480  *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
3481  else
3482  nulls = NULL;
3483  *nelemsp = nelems;
3484 
3485  p = ARR_DATA_PTR(array);
3486  bitmap = ARR_NULLBITMAP(array);
3487  bitmask = 1;
3488 
3489  for (i = 0; i < nelems; i++)
3490  {
3491  /* Get source element, checking for NULL */
3492  if (bitmap && (*bitmap & bitmask) == 0)
3493  {
3494  elems[i] = (Datum) 0;
3495  if (nulls)
3496  nulls[i] = true;
3497  else
3498  ereport(ERROR,
3499  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3500  errmsg("null array element not allowed in this context")));
3501  }
3502  else
3503  {
3504  elems[i] = fetch_att(p, elmbyval, elmlen);
3505  p = att_addlength_pointer(p, elmlen, p);
3506  p = (char *) att_align_nominal(p, elmalign);
3507  }
3508 
3509  /* advance bitmap pointer if any */
3510  if (bitmap)
3511  {
3512  bitmask <<= 1;
3513  if (bitmask == 0x100)
3514  {
3515  bitmap++;
3516  bitmask = 1;
3517  }
3518  }
3519  }
3520 }
#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:374
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:738
#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:3462
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:738
#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 5020 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().

5021 {
5022  ArrayBuildState *astate;
5023  MemoryContext arr_context = rcontext;
5024 
5025  /* Make a temporary context to hold all the junk */
5026  if (subcontext)
5027  arr_context = AllocSetContextCreate(rcontext,
5028  "accumArrayResult",
5030 
5031  astate = (ArrayBuildState *)
5032  MemoryContextAlloc(arr_context, sizeof(ArrayBuildState));
5033  astate->mcontext = arr_context;
5034  astate->private_cxt = subcontext;
5035  astate->alen = (subcontext ? 64 : 8); /* arbitrary starting array size */
5036  astate->dvalues = (Datum *)
5037  MemoryContextAlloc(arr_context, astate->alen * sizeof(Datum));
5038  astate->dnulls = (bool *)
5039  MemoryContextAlloc(arr_context, astate->alen * sizeof(bool));
5040  astate->nelems = 0;
5041  astate->element_type = element_type;
5042  get_typlenbyvalalign(element_type,
5043  &astate->typlen,
5044  &astate->typbyval,
5045  &astate->typalign);
5046 
5047  return astate;
5048 }
#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 5481 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().

5482 {
5483  ArrayBuildStateAny *astate;
5484  Oid element_type = get_element_type(input_type);
5485 
5486  if (OidIsValid(element_type))
5487  {
5488  /* Array case */
5489  ArrayBuildStateArr *arraystate;
5490 
5491  arraystate = initArrayResultArr(input_type, InvalidOid, rcontext, subcontext);
5492  astate = (ArrayBuildStateAny *)
5493  MemoryContextAlloc(arraystate->mcontext,
5494  sizeof(ArrayBuildStateAny));
5495  astate->scalarstate = NULL;
5496  astate->arraystate = arraystate;
5497  }
5498  else
5499  {
5500  /* Scalar case */
5501  ArrayBuildState *scalarstate;
5502 
5503  /* Let's just check that we have a type that can be put into arrays */
5504  Assert(OidIsValid(get_array_type(input_type)));
5505 
5506  scalarstate = initArrayResult(input_type, rcontext, subcontext);
5507  astate = (ArrayBuildStateAny *)
5508  MemoryContextAlloc(scalarstate->mcontext,
5509  sizeof(ArrayBuildStateAny));
5510  astate->scalarstate = scalarstate;
5511  astate->arraystate = NULL;
5512  }
5513 
5514  return astate;
5515 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5020
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:644
ArrayBuildStateArr * initArrayResultArr(Oid array_type, Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5207
ArrayBuildStateArr * arraystate
Definition: array.h:218
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:738
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 5207 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().

5209 {
5210  ArrayBuildStateArr *astate;
5211  MemoryContext arr_context = rcontext; /* by default use the parent ctx */
5212 
5213  /* Lookup element type, unless element_type already provided */
5214  if (!OidIsValid(element_type))
5215  {
5216  element_type = get_element_type(array_type);
5217 
5218  if (!OidIsValid(element_type))
5219  ereport(ERROR,
5220  (errcode(ERRCODE_DATATYPE_MISMATCH),
5221  errmsg("data type %s is not an array type",
5222  format_type_be(array_type))));
5223  }
5224 
5225  /* Make a temporary context to hold all the junk */
5226  if (subcontext)
5227  arr_context = AllocSetContextCreate(rcontext,
5228  "accumArrayResultArr",
5230 
5231  /* Note we initialize all fields to zero */
5232  astate = (ArrayBuildStateArr *)
5233  MemoryContextAllocZero(arr_context, sizeof(ArrayBuildStateArr));
5234  astate->mcontext = arr_context;
5235  astate->private_cxt = subcontext;
5236 
5237  /* Save relevant datatype information */
5238  astate->array_type = array_type;
5239  astate->element_type = element_type;
5240 
5241  return astate;
5242 }
#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:327
#define OidIsValid(objectId)
Definition: c.h:644
#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 5123 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().

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

◆ makeArrayResultAny()

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

Definition at line 5554 of file arrayfuncs.c.

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

Referenced by ExecScanSubPlan(), and ExecSetParamPlan().

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

5409 {
5410  ArrayType *result;
5411  MemoryContext oldcontext;
5412 
5413  /* Build the final array result in rcontext */
5414  oldcontext = MemoryContextSwitchTo(rcontext);
5415 
5416  if (astate->ndims == 0)
5417  {
5418  /* No inputs, return empty array */
5419  result = construct_empty_array(astate->element_type);
5420  }
5421  else
5422  {
5423  int dataoffset,
5424  nbytes;
5425 
5426  /* Compute required space */
5427  nbytes = astate->nbytes;
5428  if (astate->nullbitmap != NULL)
5429  {
5430  dataoffset = ARR_OVERHEAD_WITHNULLS(astate->ndims, astate->nitems);
5431  nbytes += dataoffset;
5432  }
5433  else
5434  {
5435  dataoffset = 0;
5436  nbytes += ARR_OVERHEAD_NONULLS(astate->ndims);
5437  }
5438 
5439  result = (ArrayType *) palloc0(nbytes);
5440  SET_VARSIZE(result, nbytes);
5441  result->ndim = astate->ndims;
5442  result->dataoffset = dataoffset;
5443  result->elemtype = astate->element_type;
5444 
5445  memcpy(ARR_DIMS(result), astate->dims, astate->ndims * sizeof(int));
5446  memcpy(ARR_LBOUND(result), astate->lbs, astate->ndims * sizeof(int));
5447  memcpy(ARR_DATA_PTR(result), astate->data, astate->nbytes);
5448 
5449  if (astate->nullbitmap != NULL)
5450  array_bitmap_copy(ARR_NULLBITMAP(result), 0,
5451  astate->nullbitmap, 0,
5452  astate->nitems);
5453  }
5454 
5455  MemoryContextSwitchTo(oldcontext);
5456 
5457  /* Clean up all the junk */
5458  if (release)
5459  {
5460  Assert(astate->private_cxt);
5461  MemoryContextDelete(astate->mcontext);
5462  }
5463 
5464  return PointerGetDatum(result);
5465 }
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:4693
int32 dataoffset
Definition: array.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3411
#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:738
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 5155 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().

5161 {
5162  ArrayType *result;
5163  MemoryContext oldcontext;
5164 
5165  /* Build the final array result in rcontext */
5166  oldcontext = MemoryContextSwitchTo(rcontext);
5167 
5168  result = construct_md_array(astate->dvalues,
5169  astate->dnulls,
5170  ndims,
5171  dims,
5172  lbs,
5173  astate->element_type,
5174  astate->typlen,
5175  astate->typbyval,
5176  astate->typalign);
5177 
5178  MemoryContextSwitchTo(oldcontext);
5179 
5180  /* Clean up all the junk */
5181  if (release)
5182  {
5183  Assert(astate->private_cxt);
5184  MemoryContextDelete(astate->mcontext);
5185  }
5186 
5187  return PointerGetDatum(result);
5188 }
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:738
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:3327

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