#include "fmgr.h"
Go to the source code of this file.
Data Structures | |
struct | ArrayType |
struct | ArrayBuildState |
struct | ArrayMetaState |
struct | ArrayMapState |
Defines | |
#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 | 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)) |
Typedefs | |
typedef struct ArrayBuildState | ArrayBuildState |
typedef struct ArrayMetaState | ArrayMetaState |
typedef struct ArrayMapState | ArrayMapState |
typedef struct ArrayIteratorData * | ArrayIterator |
Functions | |
Datum | array_in (PG_FUNCTION_ARGS) |
Datum | array_out (PG_FUNCTION_ARGS) |
Datum | array_recv (PG_FUNCTION_ARGS) |
Datum | array_send (PG_FUNCTION_ARGS) |
Datum | array_eq (PG_FUNCTION_ARGS) |
Datum | array_ne (PG_FUNCTION_ARGS) |
Datum | array_lt (PG_FUNCTION_ARGS) |
Datum | array_gt (PG_FUNCTION_ARGS) |
Datum | array_le (PG_FUNCTION_ARGS) |
Datum | array_ge (PG_FUNCTION_ARGS) |
Datum | btarraycmp (PG_FUNCTION_ARGS) |
Datum | hash_array (PG_FUNCTION_ARGS) |
Datum | arrayoverlap (PG_FUNCTION_ARGS) |
Datum | arraycontains (PG_FUNCTION_ARGS) |
Datum | arraycontained (PG_FUNCTION_ARGS) |
Datum | array_ndims (PG_FUNCTION_ARGS) |
Datum | array_dims (PG_FUNCTION_ARGS) |
Datum | array_lower (PG_FUNCTION_ARGS) |
Datum | array_upper (PG_FUNCTION_ARGS) |
Datum | array_length (PG_FUNCTION_ARGS) |
Datum | array_larger (PG_FUNCTION_ARGS) |
Datum | array_smaller (PG_FUNCTION_ARGS) |
Datum | generate_subscripts (PG_FUNCTION_ARGS) |
Datum | generate_subscripts_nodir (PG_FUNCTION_ARGS) |
Datum | array_fill (PG_FUNCTION_ARGS) |
Datum | array_fill_with_lower_bounds (PG_FUNCTION_ARGS) |
Datum | array_unnest (PG_FUNCTION_ARGS) |
Datum | array_remove (PG_FUNCTION_ARGS) |
Datum | array_replace (PG_FUNCTION_ARGS) |
Datum | array_ref (ArrayType *array, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull) |
ArrayType * | array_set (ArrayType *array, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign) |
ArrayType * | array_get_slice (ArrayType *array, int nSubscripts, int *upperIndx, int *lowerIndx, int arraytyplen, int elmlen, bool elmbyval, char elmalign) |
ArrayType * | array_set_slice (ArrayType *array, int nSubscripts, int *upperIndx, int *lowerIndx, ArrayType *srcArray, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign) |
Datum | array_map (FunctionCallInfo fcinfo, Oid inpType, Oid retType, ArrayMapState *amstate) |
void | array_bitmap_copy (bits8 *destbitmap, int destoffset, const bits8 *srcbitmap, int srcoffset, int nitems) |
ArrayType * | construct_array (Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign) |
ArrayType * | construct_md_array (Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign) |
ArrayType * | construct_empty_array (Oid elmtype) |
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) |
ArrayBuildState * | accumArrayResult (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) |
ArrayIterator | array_create_iterator (ArrayType *arr, int slice_ndim) |
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) |
int32 * | ArrayGetIntegerTypmods (ArrayType *arr, int *n) |
Datum | array_push (PG_FUNCTION_ARGS) |
Datum | array_cat (PG_FUNCTION_ARGS) |
ArrayType * | create_singleton_array (FunctionCallInfo fcinfo, Oid element_type, Datum element, bool isNull, int ndims) |
Datum | array_agg_transfn (PG_FUNCTION_ARGS) |
Datum | array_agg_finalfn (PG_FUNCTION_ARGS) |
Datum | array_typanalyze (PG_FUNCTION_ARGS) |
Variables | |
bool | Array_nulls |
#define ARR_DATA_OFFSET | ( | a | ) | (ARR_HASNULL(a) ? (a)->dataoffset : ARR_OVERHEAD_NONULLS(ARR_NDIM(a))) |
Definition at line 169 of file array.h.
Referenced by array_cat(), array_set(), array_set_slice(), ExecEvalArray(), and resize_intArrayType().
#define ARR_DATA_PTR | ( | a | ) | (((char *) (a)) + ARR_DATA_OFFSET(a)) |
Definition at line 175 of file array.h.
Referenced by _arrq_cons(), _lca(), _lt_q_regex(), _ltree_compress(), array_cat(), array_cmp(), array_contain_compare(), array_create_iterator(), array_eq(), array_extract_slice(), array_fill_internal(), array_get_slice(), array_insert_slice(), array_iterator(), array_map(), array_out(), array_ref(), array_replace_internal(), array_send(), array_set(), array_set_slice(), array_to_text_internal(), array_unnest(), arrq_cons(), build_function_result_tupdesc_d(), check_float8_array(), check_functional_grouping(), CopyArrayEls(), cube_subset(), deconstruct_array(), ExecEvalArray(), ExecEvalScalarArrayOp(), extension_config_remove(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_text_array_contents(), getWeights(), hash_array(), int2_avg_accum(), int4_avg_accum(), int8_avg(), lt_q_regex(), pg_extension_config_dump(), ProcedureCreate(), RelationGetExclusionInfo(), ri_LoadConstraintInfo(), and TryReuseForeignKey().
#define ARR_DIMS | ( | a | ) | ((int *) (((char *) (a)) + sizeof(ArrayType))) |
Definition at line 147 of file array.h.
Referenced by _arrq_cons(), _lca(), _lt_q_regex(), _ltree_compress(), aclnewowner(), aclupdate(), allocacl(), array_cat(), array_cmp(), array_contain_compare(), array_contains_nulls(), array_create_iterator(), array_dims(), array_eq(), array_fill_internal(), array_get_slice(), array_in(), array_insert_slice(), array_iterator(), array_length(), array_map(), array_out(), array_push(), array_recv(), array_ref(), array_replace_internal(), array_send(), array_set(), array_set_slice(), array_to_json_internal(), array_to_text_internal(), array_unnest(), array_upper(), arrq_cons(), build_function_result_tupdesc_d(), check_float8_array(), check_functional_grouping(), construct_md_array(), create_array_envelope(), deconstruct_array(), estimate_array_length(), ExecEvalArray(), ExecEvalScalarArrayOp(), extension_config_remove(), generate_subscripts(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_text_array_contents(), getWeights(), GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), hash_array(), hstore_from_array(), hstore_from_arrays(), hstore_slice_to_array(), int2vectorrecv(), is_strict_saop(), lt_q_regex(), new_intArrayType(), oidvectorrecv(), pg_extension_config_dump(), pg_get_functiondef(), plperl_ref_from_pg_array(), PLyList_FromArray(), predicate_classify(), ProcedureCreate(), ProcessGUCArray(), RelationGetExclusionInfo(), resize_intArrayType(), ri_LoadConstraintInfo(), TryReuseForeignKey(), and tsa_rewrite_accum().
#define ARR_ELEMTYPE | ( | a | ) | ((a)->elemtype) |
Definition at line 145 of file array.h.
Referenced by _bt_preprocess_array_keys(), array_cat(), array_cmp(), array_contain_compare(), array_create_iterator(), array_eq(), array_get_slice(), array_iterate(), array_map(), array_out(), array_push(), array_replace_internal(), array_send(), array_set(), array_set_slice(), array_to_json_internal(), array_to_text_internal(), array_unnest(), arrayconst_startup_fn(), ArrayGetIntegerTypmods(), build_function_result_tupdesc_d(), check_acl(), check_float8_array(), check_functional_grouping(), compute_array_stats(), DecodeTextArrayToCString(), deconstruct_array(), exec_stmt_foreach_a(), ExecEvalArray(), ExecEvalArrayCoerceExpr(), ExecEvalScalarArrayOp(), ExecIndexEvalArrayKeys(), extension_config_remove(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_text_array_contents(), ginarrayextract(), gincost_scalararrayopexpr(), ginqueryarrayextract(), GUCArrayAdd(), hash_array(), hstore_from_array(), hstore_from_arrays(), int2vectorrecv(), map_sql_value_to_xml_value(), new_intArrayType(), oidvectorrecv(), parseRelOptions(), pg_extension_config_dump(), pg_get_functiondef(), plperl_ref_from_pg_array(), ProcedureCreate(), ProcessGUCArray(), RelationGetExclusionInfo(), ri_LoadConstraintInfo(), scalararraysel(), text_format(), transformRelOptions(), TryReuseForeignKey(), tsa_rewrite_accum(), and untransformRelOptions().
#define ARR_HASNULL | ( | a | ) | ((a)->dataoffset != 0) |
Definition at line 144 of file array.h.
Referenced by array_cat(), array_contains_nulls(), array_send(), array_set(), array_set_slice(), build_function_result_tupdesc_d(), check_acl(), check_float8_array(), check_functional_grouping(), DecodeTextArrayToCString(), ExecEvalArray(), extension_config_remove(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), int2_avg_accum(), int2vectorrecv(), int4_avg_accum(), int8_avg(), oidvectorrecv(), pg_extension_config_dump(), ProcedureCreate(), RelationGetExclusionInfo(), ri_LoadConstraintInfo(), and TryReuseForeignKey().
#define ARR_LBOUND | ( | a | ) |
Definition at line 149 of file array.h.
Referenced by allocacl(), array_cat(), array_create_iterator(), array_dims(), array_fill_internal(), array_get_slice(), array_in(), array_lower(), array_out(), array_push(), array_recv(), array_ref(), array_send(), array_set(), array_set_slice(), array_upper(), construct_md_array(), create_array_envelope(), ExecEvalArray(), extension_config_remove(), generate_subscripts(), GUCArrayAdd(), hstore_from_arrays(), hstore_slice_to_array(), int2vectorrecv(), new_intArrayType(), oidvectorrecv(), pg_extension_config_dump(), pg_get_functiondef(), PLyList_FromArray(), and ProcessGUCArray().
#define ARR_NDIM | ( | a | ) | ((a)->ndim) |
Definition at line 143 of file array.h.
Referenced by _arrq_cons(), _lca(), _lt_q_regex(), _ltree_compress(), array_cat(), array_cmp(), array_contain_compare(), array_contains_nulls(), array_create_iterator(), array_dims(), array_eq(), array_fill_internal(), array_get_slice(), array_insert_slice(), array_iterator(), array_length(), array_lower(), array_map(), array_ndims(), array_out(), array_push(), array_ref(), array_replace_internal(), array_send(), array_set(), array_set_slice(), array_to_json_internal(), array_to_text_internal(), array_unnest(), array_upper(), ArrayGetIntegerTypmods(), arrq_cons(), build_function_result_tupdesc_d(), check_acl(), check_float8_array(), check_functional_grouping(), DecodeTextArrayToCString(), deconstruct_array(), estimate_array_length(), exec_stmt_foreach_a(), ExecEvalArray(), ExecEvalScalarArrayOp(), extension_config_remove(), generate_subscripts(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_text_array_contents(), getWeights(), GUCArrayAdd(), hash_array(), hstore_from_array(), hstore_from_arrays(), hstore_slice_to_array(), int2vectorrecv(), is_strict_saop(), lt_q_regex(), new_intArrayType(), oidvectorrecv(), pg_extension_config_dump(), pg_get_functiondef(), plperl_ref_from_pg_array(), PLyList_FromArray(), predicate_classify(), ProcedureCreate(), ProcessGUCArray(), RelationGetExclusionInfo(), resize_intArrayType(), ri_LoadConstraintInfo(), TryReuseForeignKey(), and tsa_rewrite_accum().
#define ARR_NULLBITMAP | ( | a | ) |
(ARR_HASNULL(a) ? \ (bits8 *) (((char *) (a)) + sizeof(ArrayType) + \ 2 * sizeof(int) * ARR_NDIM(a)) \ : (bits8 *) NULL)
Definition at line 153 of file array.h.
Referenced by array_cat(), array_cmp(), array_contain_compare(), array_contains_nulls(), array_create_iterator(), array_eq(), array_extract_slice(), array_get_slice(), array_insert_slice(), array_map(), array_out(), array_ref(), array_replace_internal(), array_send(), array_set(), array_set_slice(), array_to_text_internal(), array_unnest(), CopyArrayEls(), deconstruct_array(), ExecEvalArray(), ExecEvalScalarArrayOp(), get_text_array_contents(), and hash_array().
#define ARR_OVERHEAD_NONULLS | ( | ndims | ) | MAXALIGN(sizeof(ArrayType) + 2 * sizeof(int) * (ndims)) |
Definition at line 163 of file array.h.
Referenced by array_cat(), array_fill_internal(), array_get_slice(), array_in(), array_map(), array_recv(), array_replace_internal(), array_set(), array_set_slice(), construct_md_array(), ExecEvalArray(), int2_avg_accum(), int4_avg_accum(), int8_avg(), and new_intArrayType().
#define ARR_OVERHEAD_WITHNULLS | ( | ndims, | ||
nitems | ||||
) |
Definition at line 165 of file array.h.
Referenced by array_cat(), array_fill_internal(), array_get_slice(), array_in(), array_map(), array_recv(), array_replace_internal(), array_set(), array_set_slice(), construct_md_array(), and ExecEvalArray().
#define ARR_SIZE | ( | a | ) | VARSIZE(a) |
Definition at line 142 of file array.h.
Referenced by array_cat(), array_set(), array_set_slice(), ExecEvalArray(), int2_avg_accum(), int4_avg_accum(), and int8_avg().
#define DatumGetArrayTypeP | ( | X | ) | ((ArrayType *) PG_DETOAST_DATUM(X)) |
Definition at line 123 of file array.h.
Referenced by _bt_preprocess_array_keys(), _ltree_compress(), AlterFunction(), AlterSetting(), ApplySetting(), array_get_slice(), array_ref(), array_set(), array_set_slice(), array_to_json_internal(), arrayconst_startup_fn(), build_function_result_tupdesc_d(), calc_arraycontsel(), check_functional_grouping(), compute_array_stats(), DecodeTextArrayToCString(), decompile_column_index_array(), estimate_array_length(), ExecEvalArray(), ExecEvalArrayCoerceExpr(), ExecEvalScalarArrayOp(), ExecIndexEvalArrayKeys(), extension_config_remove(), g_int_compress(), g_int_decompress(), g_intbig_compress(), generateClonedIndexStmt(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), gincost_scalararrayopexpr(), is_strict_saop(), map_sql_value_to_xml_value(), parseRelOptions(), pg_extension_config_dump(), pg_get_constraintdef_worker(), pg_get_functiondef(), plperl_ref_from_pg_array(), PLyList_FromArray(), predicate_classify(), RelationGetExclusionInfo(), ri_LoadConstraintInfo(), scalararraysel(), TidListCreate(), transformRelOptions(), TryReuseForeignKey(), and untransformRelOptions().
#define DatumGetArrayTypePCopy | ( | X | ) | ((ArrayType *) PG_DETOAST_DATUM_COPY(X)) |
Definition at line 124 of file array.h.
Referenced by exec_stmt_foreach_a(), ExecEvalArrayCoerceExpr(), fmgr_security_definer(), and g_int_compress().
#define PG_GETARG_ARRAYTYPE_P | ( | n | ) | DatumGetArrayTypeP(PG_GETARG_DATUM(n)) |
Definition at line 125 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_cmp(), array_dims(), array_eq(), array_fill(), array_fill_with_lower_bounds(), array_larger(), array_length(), array_lower(), array_map(), array_ndims(), array_out(), array_push(), array_remove(), array_replace(), array_send(), array_smaller(), array_to_text(), array_to_text_null(), array_unnest(), array_upper(), arraycontained(), arraycontains(), arrayoverlap(), bittypmodin(), bpchartypmodin(), concat_internal(), create_empty_extension(), cube_a_f8(), cube_a_f8_f8(), cube_subset(), dblink_build_sql_delete(), dblink_build_sql_insert(), dblink_build_sql_update(), float4_accum(), float8_accum(), float8_avg(), float8_corr(), float8_covar_pop(), float8_covar_samp(), float8_regr_accum(), float8_regr_avgx(), float8_regr_avgy(), 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(), generate_subscripts(), get_path_all(), ghstore_consistent(), gin_extract_hstore_query(), ginint4_queryextract(), hash_array(), 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_accum(), int2_avg_accum(), int4_accum(), int4_avg_accum(), int8_accum(), int8_avg(), int8_avg_accum(), intarray_push_array(), intarray_push_elem(), interval_accum(), interval_avg(), intervaltypmodin(), intset_union_elem(), lt_q_regex(), numeric_accum(), numeric_avg(), numeric_avg_accum(), numeric_stddev_pop(), numeric_stddev_samp(), numeric_var_pop(), numeric_var_samp(), numerictypmodin(), subarray(), text_format(), timestamptypmodin(), timestamptztypmodin(), timetypmodin(), timetztypmodin(), varbittypmodin(), varchartypmodin(), xpath(), and xpath_exists().
#define PG_GETARG_ARRAYTYPE_P_COPY | ( | n | ) | DatumGetArrayTypePCopy(PG_GETARG_DATUM(n)) |
Definition at line 126 of file array.h.
Referenced by _int_contains(), _int_inter(), _int_overlap(), _int_same(), _int_union(), boolop(), g_int_consistent(), ginarrayextract(), ginqueryarrayextract(), int2_avg_accum(), int4_avg_accum(), intarray_del_elem(), intset_subtract(), sort(), sort_asc(), sort_desc(), tsa_rewrite_accum(), and uniq().
#define PG_RETURN_ARRAYTYPE_P | ( | x | ) | PG_RETURN_POINTER(x) |
Definition at line 127 of file array.h.
Referenced by array_cat(), array_fill(), array_fill_with_lower_bounds(), array_in(), array_larger(), array_map(), array_push(), array_recv(), array_remove(), array_replace(), array_smaller(), dblink_get_connections(), enum_range_all(), enum_range_bounds(), ExecEvalArrayCoerceExpr(), float4_accum(), float8_accum(), float8_regr_accum(), int2_accum(), int2_avg_accum(), int4_accum(), int4_avg_accum(), int8_accum(), int8_avg_accum(), interval_accum(), numeric_accum(), numeric_avg_accum(), regexp_split_to_array(), text_to_array_internal(), and xpath().
typedef struct ArrayBuildState ArrayBuildState |
typedef struct ArrayIteratorData* ArrayIterator |
typedef struct ArrayMapState ArrayMapState |
typedef struct ArrayMetaState ArrayMetaState |
ArrayBuildState* accumArrayResult | ( | ArrayBuildState * | astate, | |
Datum | dvalue, | |||
bool | disnull, | |||
Oid | element_type, | |||
MemoryContext | rcontext | |||
) |
Definition at line 4556 of file arrayfuncs.c.
References ArrayBuildState::alen, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), Assert, datumCopy(), ArrayBuildState::dnulls, ArrayBuildState::dvalues, ArrayBuildState::element_type, get_typlenbyvalalign(), ArrayBuildState::mcontext, MemoryContextSwitchTo(), ArrayBuildState::nelems, NULL, palloc(), PG_DETOAST_DATUM_COPY, PointerGetDatum, repalloc(), ArrayBuildState::typalign, ArrayBuildState::typbyval, and ArrayBuildState::typlen.
Referenced by array_agg_transfn(), array_to_datum_internal(), dblink_get_connections(), ExecScanSubPlan(), ExecSetParamPlan(), optionListToArray(), regexp_split_to_array(), text_to_array_internal(), and transformRelOptions().
{ MemoryContext arr_context, oldcontext; if (astate == NULL) { /* First time through --- initialize */ /* Make a temporary context to hold all the junk */ arr_context = AllocSetContextCreate(rcontext, "accumArrayResult", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); oldcontext = MemoryContextSwitchTo(arr_context); astate = (ArrayBuildState *) palloc(sizeof(ArrayBuildState)); astate->mcontext = arr_context; astate->alen = 64; /* arbitrary starting array size */ astate->dvalues = (Datum *) palloc(astate->alen * sizeof(Datum)); astate->dnulls = (bool *) palloc(astate->alen * sizeof(bool)); astate->nelems = 0; astate->element_type = element_type; get_typlenbyvalalign(element_type, &astate->typlen, &astate->typbyval, &astate->typalign); } else { oldcontext = MemoryContextSwitchTo(astate->mcontext); Assert(astate->element_type == element_type); /* enlarge dvalues[]/dnulls[] if needed */ if (astate->nelems >= astate->alen) { astate->alen *= 2; astate->dvalues = (Datum *) repalloc(astate->dvalues, astate->alen * sizeof(Datum)); astate->dnulls = (bool *) repalloc(astate->dnulls, astate->alen * sizeof(bool)); } } /* * Ensure pass-by-ref stuff is copied into mcontext; and detoast it too if * it's varlena. (You might think that detoasting is not needed here * because construct_md_array can detoast the array elements later. * However, we must not let construct_md_array modify the ArrayBuildState * because that would mean array_agg_finalfn damages its input, which is * verboten. Also, this way frequently saves one copying step.) */ if (!disnull && !astate->typbyval) { if (astate->typlen == -1) dvalue = PointerGetDatum(PG_DETOAST_DATUM_COPY(dvalue)); else dvalue = datumCopy(dvalue, astate->typbyval, astate->typlen); } astate->dvalues[astate->nelems] = dvalue; astate->dnulls[astate->nelems] = disnull; astate->nelems++; MemoryContextSwitchTo(oldcontext); return astate; }
Datum array_agg_finalfn | ( | PG_FUNCTION_ARGS | ) |
Definition at line 512 of file array_userfuncs.c.
References AggCheckCallContext(), Assert, CurrentMemoryContext, makeMdArrayResult(), ArrayBuildState::nelems, NULL, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_DATUM, and PG_RETURN_NULL.
{ Datum result; ArrayBuildState *state; int dims[1]; int lbs[1]; /* * Test for null before Asserting we are in right context. This is to * avoid possible Assert failure in 8.4beta installations, where it is * possible for users to create NULL constants of type internal. */ if (PG_ARGISNULL(0)) PG_RETURN_NULL(); /* returns null iff no input values */ /* cannot be called directly because of internal-type argument */ Assert(AggCheckCallContext(fcinfo, NULL)); state = (ArrayBuildState *) PG_GETARG_POINTER(0); dims[0] = state->nelems; lbs[0] = 1; /* * Make the result. We cannot release the ArrayBuildState because * sometimes aggregate final functions are re-executed. Rather, it is * nodeAgg.c's responsibility to reset the aggcontext when it's safe to do * so. */ result = makeMdArrayResult(state, 1, dims, lbs, CurrentMemoryContext, false); PG_RETURN_DATUM(result); }
Datum array_agg_transfn | ( | PG_FUNCTION_ARGS | ) |
Definition at line 477 of file array_userfuncs.c.
References accumArrayResult(), AggCheckCallContext(), elog, ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, NULL, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, and PG_RETURN_POINTER.
{ Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1); MemoryContext aggcontext; ArrayBuildState *state; Datum elem; if (arg1_typeid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not determine input data type"))); if (!AggCheckCallContext(fcinfo, &aggcontext)) { /* cannot be called directly because of internal-type argument */ elog(ERROR, "array_agg_transfn called in non-aggregate context"); } state = PG_ARGISNULL(0) ? NULL : (ArrayBuildState *) PG_GETARG_POINTER(0); elem = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1); state = accumArrayResult(state, elem, PG_ARGISNULL(1), arg1_typeid, aggcontext); /* * The transition type for array_agg() is declared to be "internal", which * is a pass-by-value type the same size as a pointer. So we can safely * pass the ArrayBuildState pointer through nodeAgg.c's machinations. */ PG_RETURN_POINTER(state); }
void array_bitmap_copy | ( | bits8 * | destbitmap, | |
int | destoffset, | |||
const bits8 * | srcbitmap, | |||
int | srcoffset, | |||
int | nitems | |||
) |
Definition at line 4252 of file arrayfuncs.c.
References Assert.
Referenced by array_cat(), array_extract_slice(), array_insert_slice(), array_set(), array_set_slice(), and ExecEvalArray().
{ int destbitmask, destbitval, srcbitmask, srcbitval; Assert(destbitmap); if (nitems <= 0) return; /* don't risk fetch off end of memory */ destbitmap += destoffset / 8; destbitmask = 1 << (destoffset % 8); destbitval = *destbitmap; if (srcbitmap) { srcbitmap += srcoffset / 8; srcbitmask = 1 << (srcoffset % 8); srcbitval = *srcbitmap; while (nitems-- > 0) { if (srcbitval & srcbitmask) destbitval |= destbitmask; else destbitval &= ~destbitmask; destbitmask <<= 1; if (destbitmask == 0x100) { *destbitmap++ = destbitval; destbitmask = 1; if (nitems > 0) destbitval = *destbitmap; } srcbitmask <<= 1; if (srcbitmask == 0x100) { srcbitmap++; srcbitmask = 1; if (nitems > 0) srcbitval = *srcbitmap; } } if (destbitmask != 1) *destbitmap = destbitval; } else { while (nitems-- > 0) { destbitval |= destbitmask; destbitmask <<= 1; if (destbitmask == 0x100) { *destbitmap++ = destbitval; destbitmask = 1; if (nitems > 0) destbitval = *destbitmap; } } if (destbitmask != 1) *destbitmap = destbitval; } }
Datum array_cat | ( | PG_FUNCTION_ARGS | ) |
Definition at line 169 of file array_userfuncs.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(), ArrayGetNItems(), ArrayType::dataoffset, ArrayType::elemtype, ereport, errcode(), errdetail(), errmsg(), ERROR, format_type_be(), i, ArrayType::ndim, palloc(), palloc0(), PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_RETURN_ARRAYTYPE_P, PG_RETURN_NULL, and SET_VARSIZE.
{ ArrayType *v1, *v2; ArrayType *result; int *dims, *lbs, ndims, nitems, ndatabytes, nbytes; int *dims1, *lbs1, ndims1, nitems1, ndatabytes1; int *dims2, *lbs2, ndims2, nitems2, ndatabytes2; int i; char *dat1, *dat2; bits8 *bitmap1, *bitmap2; Oid element_type; Oid element_type1; Oid element_type2; int32 dataoffset; /* Concatenating a null array is a no-op, just return the other input */ if (PG_ARGISNULL(0)) { if (PG_ARGISNULL(1)) PG_RETURN_NULL(); result = PG_GETARG_ARRAYTYPE_P(1); PG_RETURN_ARRAYTYPE_P(result); } if (PG_ARGISNULL(1)) { result = PG_GETARG_ARRAYTYPE_P(0); PG_RETURN_ARRAYTYPE_P(result); } v1 = PG_GETARG_ARRAYTYPE_P(0); v2 = PG_GETARG_ARRAYTYPE_P(1); element_type1 = ARR_ELEMTYPE(v1); element_type2 = ARR_ELEMTYPE(v2); /* Check we have matching element types */ if (element_type1 != element_type2) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with element types %s and %s are not " "compatible for concatenation.", format_type_be(element_type1), format_type_be(element_type2)))); /* OK, use it */ element_type = element_type1; /*---------- * We must have one of the following combinations of inputs: * 1) one empty array, and one non-empty array * 2) both arrays empty * 3) two arrays with ndims1 == ndims2 * 4) ndims1 == ndims2 - 1 * 5) ndims1 == ndims2 + 1 *---------- */ ndims1 = ARR_NDIM(v1); ndims2 = ARR_NDIM(v2); /* * short circuit - if one input array is empty, and the other is not, we * return the non-empty one as the result * * if both are empty, return the first one */ if (ndims1 == 0 && ndims2 > 0) PG_RETURN_ARRAYTYPE_P(v2); if (ndims2 == 0) PG_RETURN_ARRAYTYPE_P(v1); /* the rest fall under rule 3, 4, or 5 */ if (ndims1 != ndims2 && ndims1 != ndims2 - 1 && ndims1 != ndims2 + 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays of %d and %d dimensions are not " "compatible for concatenation.", ndims1, ndims2))); /* get argument array details */ lbs1 = ARR_LBOUND(v1); lbs2 = ARR_LBOUND(v2); dims1 = ARR_DIMS(v1); dims2 = ARR_DIMS(v2); dat1 = ARR_DATA_PTR(v1); dat2 = ARR_DATA_PTR(v2); bitmap1 = ARR_NULLBITMAP(v1); bitmap2 = ARR_NULLBITMAP(v2); nitems1 = ArrayGetNItems(ndims1, dims1); nitems2 = ArrayGetNItems(ndims2, dims2); ndatabytes1 = ARR_SIZE(v1) - ARR_DATA_OFFSET(v1); ndatabytes2 = ARR_SIZE(v2) - ARR_DATA_OFFSET(v2); if (ndims1 == ndims2) { /* * resulting array is made up of the elements (possibly arrays * themselves) of the input argument arrays */ ndims = ndims1; dims = (int *) palloc(ndims * sizeof(int)); lbs = (int *) palloc(ndims * sizeof(int)); dims[0] = dims1[0] + dims2[0]; lbs[0] = lbs1[0]; for (i = 1; i < ndims; i++) { if (dims1[i] != dims2[i] || lbs1[i] != lbs2[i]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with differing element dimensions are " "not compatible for concatenation."))); dims[i] = dims1[i]; lbs[i] = lbs1[i]; } } else if (ndims1 == ndims2 - 1) { /* * resulting array has the second argument as the outer array, with * the first argument inserted at the front of the outer dimension */ ndims = ndims2; dims = (int *) palloc(ndims * sizeof(int)); lbs = (int *) palloc(ndims * sizeof(int)); memcpy(dims, dims2, ndims * sizeof(int)); memcpy(lbs, lbs2, ndims * sizeof(int)); /* increment number of elements in outer array */ dims[0] += 1; /* make sure the added element matches our existing elements */ for (i = 0; i < ndims1; i++) { if (dims1[i] != dims[i + 1] || lbs1[i] != lbs[i + 1]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with differing dimensions are not " "compatible for concatenation."))); } } else { /* * (ndims1 == ndims2 + 1) * * resulting array has the first argument as the outer array, with the * second argument appended to the end of the outer dimension */ ndims = ndims1; dims = (int *) palloc(ndims * sizeof(int)); lbs = (int *) palloc(ndims * sizeof(int)); memcpy(dims, dims1, ndims * sizeof(int)); memcpy(lbs, lbs1, ndims * sizeof(int)); /* increment number of elements in outer array */ dims[0] += 1; /* make sure the added element matches our existing elements */ for (i = 0; i < ndims2; i++) { if (dims2[i] != dims[i + 1] || lbs2[i] != lbs[i + 1]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with differing dimensions are not " "compatible for concatenation."))); } } /* Do this mainly for overflow checking */ nitems = ArrayGetNItems(ndims, dims); /* build the result array */ ndatabytes = ndatabytes1 + ndatabytes2; if (ARR_HASNULL(v1) || ARR_HASNULL(v2)) { dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems); nbytes = ndatabytes + dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ nbytes = ndatabytes + ARR_OVERHEAD_NONULLS(ndims); } result = (ArrayType *) palloc0(nbytes); SET_VARSIZE(result, nbytes); result->ndim = ndims; result->dataoffset = dataoffset; result->elemtype = element_type; memcpy(ARR_DIMS(result), dims, ndims * sizeof(int)); memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int)); /* data area is arg1 then arg2 */ memcpy(ARR_DATA_PTR(result), dat1, ndatabytes1); memcpy(ARR_DATA_PTR(result) + ndatabytes1, dat2, ndatabytes2); /* handle the null bitmap if needed */ if (ARR_HASNULL(result)) { array_bitmap_copy(ARR_NULLBITMAP(result), 0, bitmap1, 0, nitems1); array_bitmap_copy(ARR_NULLBITMAP(result), nitems1, bitmap2, 0, nitems2); } PG_RETURN_ARRAYTYPE_P(result); }
Definition at line 3084 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(), ArrayGetIntegerTypmods(), arrq_cons(), cube_a_f8(), cube_a_f8_f8(), cube_subset(), get_path_all(), getWeights(), and lt_q_regex().
{ int nelems; bits8 *bitmap; int bitmask; /* Easy answer if there's no null bitmap */ if (!ARR_HASNULL(array)) return false; nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); bitmap = ARR_NULLBITMAP(array); /* check whole bytes of the bitmap byte-at-a-time */ while (nelems >= 8) { if (*bitmap != 0xFF) return true; bitmap++; nelems -= 8; } /* check last partial byte */ bitmask = 1; while (nelems > 0) { if ((*bitmap & bitmask) == 0) return true; bitmask <<= 1; nelems--; } return false; }
ArrayIterator array_create_iterator | ( | ArrayType * | arr, | |
int | slice_ndim | |||
) |
Definition at line 3893 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, 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, ArrayIteratorData::typbyval, and ArrayIteratorData::typlen.
Referenced by exec_stmt_foreach_a().
{ ArrayIterator iterator = palloc0(sizeof(ArrayIteratorData)); /* * Sanity-check inputs --- caller should have got this right already */ Assert(PointerIsValid(arr)); if (slice_ndim < 0 || slice_ndim > ARR_NDIM(arr)) elog(ERROR, "invalid arguments to array_create_iterator"); /* * Remember basic info about the array and its element type */ iterator->arr = arr; iterator->nullbitmap = ARR_NULLBITMAP(arr); iterator->nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr)); get_typlenbyvalalign(ARR_ELEMTYPE(arr), &iterator->typlen, &iterator->typbyval, &iterator->typalign); /* * Remember the slicing parameters. */ iterator->slice_ndim = slice_ndim; if (slice_ndim > 0) { /* * Get pointers into the array's dims and lbound arrays to represent * the dims/lbound arrays of a slice. These are the same as the * rightmost N dimensions of the array. */ iterator->slice_dims = ARR_DIMS(arr) + ARR_NDIM(arr) - slice_ndim; iterator->slice_lbound = ARR_LBOUND(arr) + ARR_NDIM(arr) - slice_ndim; /* * Compute number of elements in a slice. */ iterator->slice_len = ArrayGetNItems(slice_ndim, iterator->slice_dims); /* * Create workspace for building sub-arrays. */ iterator->slice_values = (Datum *) palloc(iterator->slice_len * sizeof(Datum)); iterator->slice_nulls = (bool *) palloc(iterator->slice_len * sizeof(bool)); } /* * Initialize our data pointer and linear element number. These will * advance through the array during array_iterate(). */ iterator->data_ptr = ARR_DATA_PTR(arr); iterator->current_item = 0; return iterator; }
Datum array_dims | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1625 of file arrayfuncs.c.
References ARR_DIMS, ARR_LBOUND, ARR_NDIM, buf, cstring_to_text(), i, MAXDIM, PG_GETARG_ARRAYTYPE_P, PG_RETURN_NULL, and PG_RETURN_TEXT_P.
{ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); char *p; int i; int *dimv, *lb; /* * 33 since we assume 15 digits per number + ':' +'[]' * * +1 for trailing null */ char buf[MAXDIM * 33 + 1]; /* Sanity check: does it look like an array at all? */ if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM) PG_RETURN_NULL(); dimv = ARR_DIMS(v); lb = ARR_LBOUND(v); p = buf; for (i = 0; i < ARR_NDIM(v); i++) { sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1); p += strlen(p); } PG_RETURN_TEXT_P(cstring_to_text(buf)); }
Datum array_eq | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3131 of file arrayfuncs.c.
References FunctionCallInfoData::arg, FunctionCallInfoData::argnull, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), att_addlength_pointer, att_align_nominal, DatumGetBool, TypeCacheEntry::eq_opr_finfo, ereport, errcode(), errmsg(), ERROR, fetch_att, FmgrInfo::fn_oid, format_type_be(), FunctionCallInvoke, i, InitFunctionCallInfoData, FunctionCallInfoData::isnull, lookup_type_cache(), memcmp(), NULL, OidIsValid, PG_FREE_IF_COPY, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, PG_RETURN_BOOL, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TYPECACHE_EQ_OPR_FINFO, and TypeCacheEntry::typlen.
Referenced by array_ne().
{ ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0); ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1); Oid collation = PG_GET_COLLATION(); int ndims1 = ARR_NDIM(array1); int ndims2 = ARR_NDIM(array2); int *dims1 = ARR_DIMS(array1); int *dims2 = ARR_DIMS(array2); Oid element_type = ARR_ELEMTYPE(array1); bool result = true; int nitems; TypeCacheEntry *typentry; int typlen; bool typbyval; char typalign; char *ptr1; char *ptr2; bits8 *bitmap1; bits8 *bitmap2; int bitmask; int i; FunctionCallInfoData locfcinfo; if (element_type != ARR_ELEMTYPE(array2)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot compare arrays of different element types"))); /* fast path if the arrays do not have the same dimensionality */ if (ndims1 != ndims2 || memcmp(dims1, dims2, 2 * ndims1 * sizeof(int)) != 0) result = false; else { /* * We arrange to look up the equality function only once per series of * calls, assuming the element type doesn't change underneath us. The * typcache is used so that we have no memory leakage when being used * as an index support function. */ typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra; if (typentry == NULL || typentry->type_id != element_type) { typentry = lookup_type_cache(element_type, TYPECACHE_EQ_OPR_FINFO); if (!OidIsValid(typentry->eq_opr_finfo.fn_oid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify an equality operator for type %s", format_type_be(element_type)))); fcinfo->flinfo->fn_extra = (void *) typentry; } typlen = typentry->typlen; typbyval = typentry->typbyval; typalign = typentry->typalign; /* * apply the operator to each pair of array elements. */ InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2, collation, NULL, NULL); /* Loop over source data */ nitems = ArrayGetNItems(ndims1, dims1); ptr1 = ARR_DATA_PTR(array1); ptr2 = ARR_DATA_PTR(array2); bitmap1 = ARR_NULLBITMAP(array1); bitmap2 = ARR_NULLBITMAP(array2); bitmask = 1; /* use same bitmask for both arrays */ for (i = 0; i < nitems; i++) { Datum elt1; Datum elt2; bool isnull1; bool isnull2; bool oprresult; /* Get elements, checking for NULL */ if (bitmap1 && (*bitmap1 & bitmask) == 0) { isnull1 = true; elt1 = (Datum) 0; } else { isnull1 = false; elt1 = fetch_att(ptr1, typbyval, typlen); ptr1 = att_addlength_pointer(ptr1, typlen, ptr1); ptr1 = (char *) att_align_nominal(ptr1, typalign); } if (bitmap2 && (*bitmap2 & bitmask) == 0) { isnull2 = true; elt2 = (Datum) 0; } else { isnull2 = false; elt2 = fetch_att(ptr2, typbyval, typlen); ptr2 = att_addlength_pointer(ptr2, typlen, ptr2); ptr2 = (char *) att_align_nominal(ptr2, typalign); } /* advance bitmap pointers if any */ bitmask <<= 1; if (bitmask == 0x100) { if (bitmap1) bitmap1++; if (bitmap2) bitmap2++; bitmask = 1; } /* * We consider two NULLs equal; NULL and not-NULL are unequal. */ if (isnull1 && isnull2) continue; if (isnull1 || isnull2) { result = false; break; } /* * Apply the operator to the element pair */ locfcinfo.arg[0] = elt1; locfcinfo.arg[1] = elt2; locfcinfo.argnull[0] = false; locfcinfo.argnull[1] = false; locfcinfo.isnull = false; oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo)); if (!oprresult) { result = false; break; } } } /* Avoid leaking memory when handed toasted input. */ PG_FREE_IF_COPY(array1, 0); PG_FREE_IF_COPY(array2, 1); PG_RETURN_BOOL(result); }
Datum array_fill | ( | PG_FUNCTION_ARGS | ) |
Definition at line 4848 of file arrayfuncs.c.
References array_fill_internal(), elog, ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), NULL, OidIsValid, PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_ARRAYTYPE_P, and value.
{ ArrayType *dims; ArrayType *result; Oid elmtype; Datum value; bool isnull; if (PG_ARGISNULL(1)) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("dimension array or low bound array cannot be null"))); dims = PG_GETARG_ARRAYTYPE_P(1); if (!PG_ARGISNULL(0)) { value = PG_GETARG_DATUM(0); isnull = false; } else { value = 0; isnull = true; } elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0); if (!OidIsValid(elmtype)) elog(ERROR, "could not determine data type of input"); result = array_fill_internal(dims, NULL, value, isnull, elmtype, fcinfo); PG_RETURN_ARRAYTYPE_P(result); }
Datum array_fill_with_lower_bounds | ( | PG_FUNCTION_ARGS | ) |
Definition at line 4807 of file arrayfuncs.c.
References array_fill_internal(), elog, ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), OidIsValid, PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_ARRAYTYPE_P, and value.
{ ArrayType *dims; ArrayType *lbs; ArrayType *result; Oid elmtype; Datum value; bool isnull; if (PG_ARGISNULL(1) || PG_ARGISNULL(2)) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("dimension array or low bound array cannot be null"))); dims = PG_GETARG_ARRAYTYPE_P(1); lbs = PG_GETARG_ARRAYTYPE_P(2); if (!PG_ARGISNULL(0)) { value = PG_GETARG_DATUM(0); isnull = false; } else { value = 0; isnull = true; } elmtype = get_fn_expr_argtype(fcinfo->flinfo, 0); if (!OidIsValid(elmtype)) elog(ERROR, "could not determine data type of input"); result = array_fill_internal(dims, lbs, value, isnull, elmtype, fcinfo); PG_RETURN_ARRAYTYPE_P(result); }
void array_free_iterator | ( | ArrayIterator | iterator | ) |
Definition at line 4045 of file arrayfuncs.c.
References pfree(), ArrayIteratorData::slice_ndim, ArrayIteratorData::slice_nulls, and ArrayIteratorData::slice_values.
Referenced by exec_stmt_foreach_a().
{ if (iterator->slice_ndim > 0) { pfree(iterator->slice_values); pfree(iterator->slice_nulls); } pfree(iterator); }
Datum array_ge | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3319 of file arrayfuncs.c.
References array_cmp(), and PG_RETURN_BOOL.
{ PG_RETURN_BOOL(array_cmp(fcinfo) >= 0); }
ArrayType* array_get_slice | ( | ArrayType * | array, | |
int | nSubscripts, | |||
int * | upperIndx, | |||
int * | lowerIndx, | |||
int | arraytyplen, | |||
int | elmlen, | |||
bool | elmbyval, | |||
char | elmalign | |||
) |
Definition at line 1874 of file arrayfuncs.c.
References ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_extract_slice(), array_slice_size(), ArrayGetNItems(), construct_empty_array(), ArrayType::dataoffset, DatumGetArrayTypeP, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, MAXDIM, mda_get_range(), ArrayType::ndim, palloc0(), PointerGetDatum, and SET_VARSIZE.
Referenced by ExecEvalArrayRef().
{ ArrayType *newarray; int i, ndim, *dim, *lb, *newlb; int fixedDim[1], fixedLb[1]; Oid elemtype; char *arraydataptr; bits8 *arraynullsptr; int32 dataoffset; int bytes, span[MAXDIM]; if (arraytyplen > 0) { /* * fixed-length arrays -- currently, cannot slice these because parser * labels output as being of the fixed-length array type! Code below * shows how we could support it if the parser were changed to label * output as a suitable varlena array type. */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("slices of fixed-length arrays not implemented"))); /* * fixed-length arrays -- these are assumed to be 1-d, 0-based * * XXX where would we get the correct ELEMTYPE from? */ ndim = 1; fixedDim[0] = arraytyplen / elmlen; fixedLb[0] = 0; dim = fixedDim; lb = fixedLb; elemtype = InvalidOid; /* XXX */ arraydataptr = (char *) array; arraynullsptr = NULL; } else { /* detoast input array if necessary */ array = DatumGetArrayTypeP(PointerGetDatum(array)); ndim = ARR_NDIM(array); dim = ARR_DIMS(array); lb = ARR_LBOUND(array); elemtype = ARR_ELEMTYPE(array); arraydataptr = ARR_DATA_PTR(array); arraynullsptr = ARR_NULLBITMAP(array); } /* * Check provided subscripts. A slice exceeding the current array limits * is silently truncated to the array limits. If we end up with an empty * slice, return an empty array. */ if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM) return construct_empty_array(elemtype); for (i = 0; i < nSubscripts; i++) { if (lowerIndx[i] < lb[i]) lowerIndx[i] = lb[i]; if (upperIndx[i] >= (dim[i] + lb[i])) upperIndx[i] = dim[i] + lb[i] - 1; if (lowerIndx[i] > upperIndx[i]) return construct_empty_array(elemtype); } /* fill any missing subscript positions with full array range */ for (; i < ndim; i++) { lowerIndx[i] = lb[i]; upperIndx[i] = dim[i] + lb[i] - 1; if (lowerIndx[i] > upperIndx[i]) return construct_empty_array(elemtype); } mda_get_range(ndim, span, lowerIndx, upperIndx); bytes = array_slice_size(arraydataptr, arraynullsptr, ndim, dim, lb, lowerIndx, upperIndx, elmlen, elmbyval, elmalign); /* * Currently, we put a null bitmap in the result if the source has one; * could be smarter ... */ if (arraynullsptr) { dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, ArrayGetNItems(ndim, span)); bytes += dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ bytes += ARR_OVERHEAD_NONULLS(ndim); } newarray = (ArrayType *) palloc0(bytes); SET_VARSIZE(newarray, bytes); newarray->ndim = ndim; newarray->dataoffset = dataoffset; newarray->elemtype = elemtype; memcpy(ARR_DIMS(newarray), span, ndim * sizeof(int)); /* * Lower bounds of the new array are set to 1. Formerly (before 7.3) we * copied the given lowerIndx values ... but that seems confusing. */ newlb = ARR_LBOUND(newarray); for (i = 0; i < ndim; i++) newlb[i] = 1; array_extract_slice(newarray, ndim, dim, lb, arraydataptr, arraynullsptr, lowerIndx, upperIndx, elmlen, elmbyval, elmalign); return newarray; }
Datum array_gt | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3307 of file arrayfuncs.c.
References array_cmp(), and PG_RETURN_BOOL.
{ PG_RETURN_BOOL(array_cmp(fcinfo) > 0); }
Datum array_in | ( | PG_FUNCTION_ARGS | ) |
Definition at line 144 of file arrayfuncs.c.
References ARR_DIMS, ARR_LBOUND, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, array_isspace(), ArrayCount(), ArrayGetNItems(), ASSGN, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, ArrayMetaState::element_type, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, fmgr_info_cxt(), FmgrInfo::fn_mcxt, get_type_io_data(), i, IOFunc_input, MAXDIM, MemoryContextAlloc(), ArrayType::ndim, NULL, palloc(), palloc0(), pfree(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_ARRAYTYPE_P, ArrayMetaState::proc, pstrdup(), ReadArrayStr(), SET_VARSIZE, ArrayMetaState::typalign, ArrayMetaState::typbyval, ArrayMetaState::typdelim, ArrayMetaState::typiofunc, ArrayMetaState::typioparam, and ArrayMetaState::typlen.
{ char *string = PG_GETARG_CSTRING(0); /* external form */ Oid element_type = PG_GETARG_OID(1); /* type of an array * element */ int32 typmod = PG_GETARG_INT32(2); /* typmod for array elements */ int typlen; bool typbyval; char typalign; char typdelim; Oid typioparam; char *string_save, *p; int i, nitems; Datum *dataPtr; bool *nullsPtr; bool hasnulls; int32 nbytes; int32 dataoffset; ArrayType *retval; int ndim, dim[MAXDIM], lBound[MAXDIM]; ArrayMetaState *my_extra; /* * We arrange to look up info about element type, including its input * conversion proc, only once per series of calls, assuming the element * type doesn't change underneath us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { /* * Get info about element type, including its input conversion proc */ get_type_io_data(element_type, IOFunc_input, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign, &my_extra->typdelim, &my_extra->typioparam, &my_extra->typiofunc); fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc, fcinfo->flinfo->fn_mcxt); my_extra->element_type = element_type; } typlen = my_extra->typlen; typbyval = my_extra->typbyval; typalign = my_extra->typalign; typdelim = my_extra->typdelim; typioparam = my_extra->typioparam; /* Make a modifiable copy of the input */ string_save = pstrdup(string); /* * If the input string starts with dimension info, read and use that. * Otherwise, we require the input to be in curly-brace style, and we * prescan the input to determine dimensions. * * Dimension info takes the form of one or more [n] or [m:n] items. The * outer loop iterates once per dimension item. */ p = string_save; ndim = 0; for (;;) { char *q; int ub; /* * Note: we currently allow whitespace between, but not within, * dimension items. */ while (array_isspace(*p)) p++; if (*p != '[') break; /* no more dimension items */ p++; if (ndim >= MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", ndim + 1, MAXDIM))); for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++); if (q == p) /* no digits? */ ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("missing dimension value"))); if (*q == ':') { /* [m:n] format */ *q = '\0'; lBound[ndim] = atoi(p); p = q + 1; for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++); if (q == p) /* no digits? */ ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("missing dimension value"))); } else { /* [n] format */ lBound[ndim] = 1; } if (*q != ']') ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("missing \"]\" in array dimensions"))); *q = '\0'; ub = atoi(p); p = q + 1; if (ub < lBound[ndim]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("upper bound cannot be less than lower bound"))); dim[ndim] = ub - lBound[ndim] + 1; ndim++; } if (ndim == 0) { /* No array dimensions, so intuit dimensions from brace structure */ if (*p != '{') ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("array value must start with \"{\" or dimension information"))); ndim = ArrayCount(p, dim, typdelim); for (i = 0; i < ndim; i++) lBound[i] = 1; } else { int ndim_braces, dim_braces[MAXDIM]; /* If array dimensions are given, expect '=' operator */ if (strncmp(p, ASSGN, strlen(ASSGN)) != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("missing assignment operator"))); p += strlen(ASSGN); while (array_isspace(*p)) p++; /* * intuit dimensions from brace structure -- it better match what we * were given */ if (*p != '{') ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("array value must start with \"{\" or dimension information"))); ndim_braces = ArrayCount(p, dim_braces, typdelim); if (ndim_braces != ndim) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("array dimensions incompatible with array literal"))); for (i = 0; i < ndim; ++i) { if (dim[i] != dim_braces[i]) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("array dimensions incompatible with array literal"))); } } #ifdef ARRAYDEBUG printf("array_in- ndim %d (", ndim); for (i = 0; i < ndim; i++) { printf(" %d", dim[i]); }; printf(") for %s\n", string); #endif /* This checks for overflow of the array dimensions */ nitems = ArrayGetNItems(ndim, dim); /* Empty array? */ if (nitems == 0) PG_RETURN_ARRAYTYPE_P(construct_empty_array(element_type)); dataPtr = (Datum *) palloc(nitems * sizeof(Datum)); nullsPtr = (bool *) palloc(nitems * sizeof(bool)); ReadArrayStr(p, string, nitems, ndim, dim, &my_extra->proc, typioparam, typmod, typdelim, typlen, typbyval, typalign, dataPtr, nullsPtr, &hasnulls, &nbytes); if (hasnulls) { dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems); nbytes += dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ nbytes += ARR_OVERHEAD_NONULLS(ndim); } retval = (ArrayType *) palloc0(nbytes); SET_VARSIZE(retval, nbytes); retval->ndim = ndim; retval->dataoffset = dataoffset; /* * This comes from the array's pg_type.typelem (which points to the base * data type's pg_type.oid) and stores system oids in user tables. This * oid must be preserved by binary upgrades. */ retval->elemtype = element_type; memcpy(ARR_DIMS(retval), dim, ndim * sizeof(int)); memcpy(ARR_LBOUND(retval), lBound, ndim * sizeof(int)); CopyArrayEls(retval, dataPtr, nullsPtr, nitems, typlen, typbyval, typalign, true); pfree(dataPtr); pfree(nullsPtr); pfree(string_save); PG_RETURN_ARRAYTYPE_P(retval); }
bool array_iterate | ( | ArrayIterator | iterator, | |
Datum * | value, | |||
bool * | isnull | |||
) |
Definition at line 3962 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 exec_stmt_foreach_a().
{ /* Done if we have reached the end of the array */ if (iterator->current_item >= iterator->nitems) return false; if (iterator->slice_ndim == 0) { /* * Scalar case: return one element. */ if (array_get_isnull(iterator->nullbitmap, iterator->current_item++)) { *isnull = true; *value = (Datum) 0; } else { /* non-NULL, so fetch the individual Datum to return */ char *p = iterator->data_ptr; *isnull = false; *value = fetch_att(p, iterator->typbyval, iterator->typlen); /* Move our data pointer forward to the next element */ p = att_addlength_pointer(p, iterator->typlen, p); p = (char *) att_align_nominal(p, iterator->typalign); iterator->data_ptr = p; } } else { /* * Slice case: build and return an array of the requested size. */ ArrayType *result; Datum *values = iterator->slice_values; bool *nulls = iterator->slice_nulls; char *p = iterator->data_ptr; int i; for (i = 0; i < iterator->slice_len; i++) { if (array_get_isnull(iterator->nullbitmap, iterator->current_item++)) { nulls[i] = true; values[i] = (Datum) 0; } else { nulls[i] = false; values[i] = fetch_att(p, iterator->typbyval, iterator->typlen); /* Move our data pointer forward to the next element */ p = att_addlength_pointer(p, iterator->typlen, p); p = (char *) att_align_nominal(p, iterator->typalign); } } iterator->data_ptr = p; result = construct_md_array(values, nulls, iterator->slice_ndim, iterator->slice_dims, iterator->slice_lbound, ARR_ELEMTYPE(iterator->arr), iterator->typlen, iterator->typbyval, iterator->typalign); *isnull = false; *value = PointerGetDatum(result); } return true; }
Datum array_larger | ( | PG_FUNCTION_ARGS | ) |
Definition at line 4690 of file arrayfuncs.c.
References array_cmp(), PG_GETARG_ARRAYTYPE_P, and PG_RETURN_ARRAYTYPE_P.
{ ArrayType *v1, *v2, *result; v1 = PG_GETARG_ARRAYTYPE_P(0); v2 = PG_GETARG_ARRAYTYPE_P(1); result = ((array_cmp(fcinfo) > 0) ? v1 : v2); PG_RETURN_ARRAYTYPE_P(result); }
Datum array_le | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3313 of file arrayfuncs.c.
References array_cmp(), and PG_RETURN_BOOL.
{ PG_RETURN_BOOL(array_cmp(fcinfo) <= 0); }
Datum array_length | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1720 of file arrayfuncs.c.
References ARR_DIMS, ARR_NDIM, MAXDIM, PG_GETARG_ARRAYTYPE_P, PG_GETARG_INT32, PG_RETURN_INT32, and PG_RETURN_NULL.
{ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int reqdim = PG_GETARG_INT32(1); int *dimv; int result; /* Sanity check: does it look like an array at all? */ if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM) PG_RETURN_NULL(); /* Sanity check: was the requested dim valid */ if (reqdim <= 0 || reqdim > ARR_NDIM(v)) PG_RETURN_NULL(); dimv = ARR_DIMS(v); result = dimv[reqdim - 1]; PG_RETURN_INT32(result); }
Datum array_lower | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1663 of file arrayfuncs.c.
References ARR_LBOUND, ARR_NDIM, MAXDIM, PG_GETARG_ARRAYTYPE_P, PG_GETARG_INT32, PG_RETURN_INT32, and PG_RETURN_NULL.
{ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int reqdim = PG_GETARG_INT32(1); int *lb; int result; /* Sanity check: does it look like an array at all? */ if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM) PG_RETURN_NULL(); /* Sanity check: was the requested dim valid */ if (reqdim <= 0 || reqdim > ARR_NDIM(v)) PG_RETURN_NULL(); lb = ARR_LBOUND(v); result = lb[reqdim - 1]; PG_RETURN_INT32(result); }
Datum array_lt | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3301 of file arrayfuncs.c.
References array_cmp(), and PG_RETURN_BOOL.
{ PG_RETURN_BOOL(array_cmp(fcinfo) < 0); }
Datum array_map | ( | FunctionCallInfo | fcinfo, | |
Oid | inpType, | |||
Oid | retType, | |||
ArrayMapState * | amstate | |||
) |
Definition at line 2653 of file arrayfuncs.c.
References AllocSizeIsValid, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, ARR_NULLBITMAP, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ArrayGetNItems(), Assert, att_addlength_datum, att_align_nominal, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, ArrayMetaState::element_type, ArrayType::elemtype, elog, ereport, errcode(), errmsg(), ERROR, fetch_att, FunctionCallInfoData::flinfo, FmgrInfo::fn_strict, FunctionCallInvoke, get_typlenbyvalalign(), i, ArrayMapState::inp_extra, FunctionCallInfoData::isnull, MaxAllocSize, FunctionCallInfoData::nargs, ArrayType::ndim, palloc(), palloc0(), pfree(), PG_ARGISNULL, PG_DETOAST_DATUM, PG_GETARG_ARRAYTYPE_P, PG_RETURN_ARRAYTYPE_P, PointerGetDatum, ArrayMapState::ret_extra, SET_VARSIZE, ArrayMetaState::typalign, ArrayMetaState::typbyval, ArrayMetaState::typlen, and values.
Referenced by ExecEvalArrayCoerceExpr().
{ ArrayType *v; ArrayType *result; Datum *values; bool *nulls; Datum elt; int *dim; int ndim; int nitems; int i; int32 nbytes = 0; int32 dataoffset; bool hasnulls; int inp_typlen; bool inp_typbyval; char inp_typalign; int typlen; bool typbyval; char typalign; char *s; bits8 *bitmap; int bitmask; ArrayMetaState *inp_extra; ArrayMetaState *ret_extra; /* Get input array */ if (fcinfo->nargs < 1) elog(ERROR, "invalid nargs: %d", fcinfo->nargs); if (PG_ARGISNULL(0)) elog(ERROR, "null input array"); v = PG_GETARG_ARRAYTYPE_P(0); Assert(ARR_ELEMTYPE(v) == inpType); ndim = ARR_NDIM(v); dim = ARR_DIMS(v); nitems = ArrayGetNItems(ndim, dim); /* Check for empty array */ if (nitems <= 0) { /* Return empty array */ PG_RETURN_ARRAYTYPE_P(construct_empty_array(retType)); } /* * We arrange to look up info about input and return element types only * once per series of calls, assuming the element type doesn't change * underneath us. */ inp_extra = &amstate->inp_extra; ret_extra = &amstate->ret_extra; if (inp_extra->element_type != inpType) { get_typlenbyvalalign(inpType, &inp_extra->typlen, &inp_extra->typbyval, &inp_extra->typalign); inp_extra->element_type = inpType; } inp_typlen = inp_extra->typlen; inp_typbyval = inp_extra->typbyval; inp_typalign = inp_extra->typalign; if (ret_extra->element_type != retType) { get_typlenbyvalalign(retType, &ret_extra->typlen, &ret_extra->typbyval, &ret_extra->typalign); ret_extra->element_type = retType; } typlen = ret_extra->typlen; typbyval = ret_extra->typbyval; typalign = ret_extra->typalign; /* Allocate temporary arrays for new values */ values = (Datum *) palloc(nitems * sizeof(Datum)); nulls = (bool *) palloc(nitems * sizeof(bool)); /* Loop over source data */ s = ARR_DATA_PTR(v); bitmap = ARR_NULLBITMAP(v); bitmask = 1; hasnulls = false; for (i = 0; i < nitems; i++) { bool callit = true; /* Get source element, checking for NULL */ if (bitmap && (*bitmap & bitmask) == 0) { fcinfo->argnull[0] = true; } else { elt = fetch_att(s, inp_typbyval, inp_typlen); s = att_addlength_datum(s, inp_typlen, elt); s = (char *) att_align_nominal(s, inp_typalign); fcinfo->arg[0] = elt; fcinfo->argnull[0] = false; } /* * Apply the given function to source elt and extra args. */ if (fcinfo->flinfo->fn_strict) { int j; for (j = 0; j < fcinfo->nargs; j++) { if (fcinfo->argnull[j]) { callit = false; break; } } } if (callit) { fcinfo->isnull = false; values[i] = FunctionCallInvoke(fcinfo); } else fcinfo->isnull = true; nulls[i] = fcinfo->isnull; if (fcinfo->isnull) hasnulls = true; else { /* Ensure data is not toasted */ if (typlen == -1) values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i])); /* Update total result size */ nbytes = att_addlength_datum(nbytes, typlen, values[i]); nbytes = att_align_nominal(nbytes, typalign); /* check for overflow of total request */ if (!AllocSizeIsValid(nbytes)) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("array size exceeds the maximum allowed (%d)", (int) MaxAllocSize))); } /* advance bitmap pointer if any */ if (bitmap) { bitmask <<= 1; if (bitmask == 0x100) { bitmap++; bitmask = 1; } } } /* Allocate and initialize the result array */ if (hasnulls) { dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems); nbytes += dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ nbytes += ARR_OVERHEAD_NONULLS(ndim); } result = (ArrayType *) palloc0(nbytes); SET_VARSIZE(result, nbytes); result->ndim = ndim; result->dataoffset = dataoffset; result->elemtype = retType; memcpy(ARR_DIMS(result), ARR_DIMS(v), 2 * ndim * sizeof(int)); /* * Note: do not risk trying to pfree the results of the called function */ CopyArrayEls(result, values, nulls, nitems, typlen, typbyval, typalign, false); pfree(values); pfree(nulls); PG_RETURN_ARRAYTYPE_P(result); }
Datum array_ndims | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1609 of file arrayfuncs.c.
References ARR_NDIM, MAXDIM, PG_GETARG_ARRAYTYPE_P, PG_RETURN_INT32, and PG_RETURN_NULL.
{ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); /* Sanity check: does it look like an array at all? */ if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM) PG_RETURN_NULL(); PG_RETURN_INT32(ARR_NDIM(v)); }
Datum array_ne | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3295 of file arrayfuncs.c.
References array_eq(), DatumGetBool, and PG_RETURN_BOOL.
{ PG_RETURN_BOOL(!DatumGetBool(array_eq(fcinfo))); }
Datum array_out | ( | PG_FUNCTION_ARGS | ) |
Definition at line 956 of file arrayfuncs.c.
References APPENDCHAR, APPENDSTR, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, array_isspace(), ArrayGetNItems(), att_addlength_pointer, att_align_nominal, ArrayMetaState::element_type, fetch_att, fmgr_info_cxt(), FmgrInfo::fn_mcxt, get_type_io_data(), i, IOFunc_output, MAXDIM, MemoryContextAlloc(), NULL, OutputFunctionCall(), palloc(), pfree(), PG_GETARG_ARRAYTYPE_P, PG_RETURN_CSTRING, pg_strcasecmp(), ArrayMetaState::proc, pstrdup(), ArrayMetaState::typalign, ArrayMetaState::typbyval, ArrayMetaState::typdelim, ArrayMetaState::typiofunc, ArrayMetaState::typioparam, ArrayMetaState::typlen, and values.
Referenced by anyarray_out().
{ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); Oid element_type = ARR_ELEMTYPE(v); int typlen; bool typbyval; char typalign; char typdelim; char *p, *tmp, *retval, **values, dims_str[(MAXDIM * 33) + 2]; /* * 33 per dim since we assume 15 digits per number + ':' +'[]' * * +2 allows for assignment operator + trailing null */ bits8 *bitmap; int bitmask; bool *needquotes, needdims = false; int nitems, overall_length, i, j, k, indx[MAXDIM]; int ndim, *dims, *lb; ArrayMetaState *my_extra; /* * We arrange to look up info about element type, including its output * conversion proc, only once per series of calls, assuming the element * type doesn't change underneath us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { /* * Get info about element type, including its output conversion proc */ get_type_io_data(element_type, IOFunc_output, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign, &my_extra->typdelim, &my_extra->typioparam, &my_extra->typiofunc); fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc, fcinfo->flinfo->fn_mcxt); my_extra->element_type = element_type; } typlen = my_extra->typlen; typbyval = my_extra->typbyval; typalign = my_extra->typalign; typdelim = my_extra->typdelim; ndim = ARR_NDIM(v); dims = ARR_DIMS(v); lb = ARR_LBOUND(v); nitems = ArrayGetNItems(ndim, dims); if (nitems == 0) { retval = pstrdup("{}"); PG_RETURN_CSTRING(retval); } /* * we will need to add explicit dimensions if any dimension has a lower * bound other than one */ for (i = 0; i < ndim; i++) { if (lb[i] != 1) { needdims = true; break; } } /* * Convert all values to string form, count total space needed (including * any overhead such as escaping backslashes), and detect whether each * item needs double quotes. */ values = (char **) palloc(nitems * sizeof(char *)); needquotes = (bool *) palloc(nitems * sizeof(bool)); overall_length = 1; /* don't forget to count \0 at end. */ p = ARR_DATA_PTR(v); bitmap = ARR_NULLBITMAP(v); bitmask = 1; for (i = 0; i < nitems; i++) { bool needquote; /* Get source element, checking for NULL */ if (bitmap && (*bitmap & bitmask) == 0) { values[i] = pstrdup("NULL"); overall_length += 4; needquote = false; } else { Datum itemvalue; itemvalue = fetch_att(p, typbyval, typlen); values[i] = OutputFunctionCall(&my_extra->proc, itemvalue); p = att_addlength_pointer(p, typlen, p); p = (char *) att_align_nominal(p, typalign); /* count data plus backslashes; detect chars needing quotes */ if (values[i][0] == '\0') needquote = true; /* force quotes for empty string */ else if (pg_strcasecmp(values[i], "NULL") == 0) needquote = true; /* force quotes for literal NULL */ else needquote = false; for (tmp = values[i]; *tmp != '\0'; tmp++) { char ch = *tmp; overall_length += 1; if (ch == '"' || ch == '\\') { needquote = true; overall_length += 1; } else if (ch == '{' || ch == '}' || ch == typdelim || array_isspace(ch)) needquote = true; } } needquotes[i] = needquote; /* Count the pair of double quotes, if needed */ if (needquote) overall_length += 2; /* and the comma */ overall_length += 1; /* advance bitmap pointer if any */ if (bitmap) { bitmask <<= 1; if (bitmask == 0x100) { bitmap++; bitmask = 1; } } } /* * count total number of curly braces in output string */ for (i = j = 0, k = 1; i < ndim; i++) k *= dims[i], j += k; dims_str[0] = '\0'; /* add explicit dimensions if required */ if (needdims) { char *ptr = dims_str; for (i = 0; i < ndim; i++) { sprintf(ptr, "[%d:%d]", lb[i], lb[i] + dims[i] - 1); ptr += strlen(ptr); } *ptr++ = *ASSGN; *ptr = '\0'; } retval = (char *) palloc(strlen(dims_str) + overall_length + 2 * j); p = retval; #define APPENDSTR(str) (strcpy(p, (str)), p += strlen(p)) #define APPENDCHAR(ch) (*p++ = (ch), *p = '\0') if (needdims) APPENDSTR(dims_str); APPENDCHAR('{'); for (i = 0; i < ndim; i++) indx[i] = 0; j = 0; k = 0; do { for (i = j; i < ndim - 1; i++) APPENDCHAR('{'); if (needquotes[k]) { APPENDCHAR('"'); for (tmp = values[k]; *tmp; tmp++) { char ch = *tmp; if (ch == '"' || ch == '\\') *p++ = '\\'; *p++ = ch; } *p = '\0'; APPENDCHAR('"'); } else APPENDSTR(values[k]); pfree(values[k++]); for (i = ndim - 1; i >= 0; i--) { indx[i] = (indx[i] + 1) % dims[i]; if (indx[i]) { APPENDCHAR(typdelim); break; } else APPENDCHAR('}'); } j = i; } while (j != -1); #undef APPENDSTR #undef APPENDCHAR pfree(values); pfree(needquotes); PG_RETURN_CSTRING(retval); }
Datum array_push | ( | PG_FUNCTION_ARGS | ) |
Definition at line 26 of file array_userfuncs.c.
References ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, array_set(), construct_empty_array(), ArrayMetaState::element_type, ereport, errcode(), errmsg(), ERROR, get_element_type(), get_fn_expr_argtype(), get_typlenbyvalalign(), InvalidOid, MemoryContextAlloc(), NULL, PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_ARRAYTYPE_P, PG_RETURN_NULL, ArrayMetaState::typalign, ArrayMetaState::typbyval, and ArrayMetaState::typlen.
{ ArrayType *v; Datum newelem; bool isNull; int *dimv, *lb; ArrayType *result; int indx; Oid element_type; int16 typlen; bool typbyval; char typalign; Oid arg0_typeid = get_fn_expr_argtype(fcinfo->flinfo, 0); Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1); Oid arg0_elemid; Oid arg1_elemid; ArrayMetaState *my_extra; if (arg0_typeid == InvalidOid || arg1_typeid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not determine input data types"))); arg0_elemid = get_element_type(arg0_typeid); arg1_elemid = get_element_type(arg1_typeid); if (arg0_elemid != InvalidOid) { if (PG_ARGISNULL(0)) v = construct_empty_array(arg0_elemid); else v = PG_GETARG_ARRAYTYPE_P(0); isNull = PG_ARGISNULL(1); if (isNull) newelem = (Datum) 0; else newelem = PG_GETARG_DATUM(1); } else if (arg1_elemid != InvalidOid) { if (PG_ARGISNULL(1)) v = construct_empty_array(arg1_elemid); else v = PG_GETARG_ARRAYTYPE_P(1); isNull = PG_ARGISNULL(0); if (isNull) newelem = (Datum) 0; else newelem = PG_GETARG_DATUM(0); } else { /* Shouldn't get here given proper type checking in parser */ ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("neither input type is an array"))); PG_RETURN_NULL(); /* keep compiler quiet */ } element_type = ARR_ELEMTYPE(v); if (ARR_NDIM(v) == 1) { lb = ARR_LBOUND(v); dimv = ARR_DIMS(v); if (arg0_elemid != InvalidOid) { /* append newelem */ int ub = dimv[0] + lb[0] - 1; indx = ub + 1; /* overflow? */ if (indx < ub) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } else { /* prepend newelem */ indx = lb[0] - 1; /* overflow? */ if (indx > lb[0]) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } } else if (ARR_NDIM(v) == 0) indx = 1; else ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("argument must be empty or one-dimensional array"))); /* * We arrange to look up info about element type only once per series of * calls, assuming the element type doesn't change underneath us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { /* Get info about element type */ get_typlenbyvalalign(element_type, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign); my_extra->element_type = element_type; } typlen = my_extra->typlen; typbyval = my_extra->typbyval; typalign = my_extra->typalign; result = array_set(v, 1, &indx, newelem, isNull, -1, typlen, typbyval, typalign); /* * Readjust result's LB to match the input's. This does nothing in the * append case, but it's the simplest way to implement the prepend case. */ if (ARR_NDIM(v) == 1) ARR_LBOUND(result)[0] = ARR_LBOUND(v)[0]; PG_RETURN_ARRAYTYPE_P(result); }
Datum array_recv | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1213 of file arrayfuncs.c.
References ARR_DIMS, ARR_LBOUND, ARR_OVERHEAD_NONULLS, ARR_OVERHEAD_WITHNULLS, ArrayGetNItems(), buf, construct_empty_array(), CopyArrayEls(), ArrayType::dataoffset, ArrayMetaState::element_type, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, fmgr_info_cxt(), FmgrInfo::fn_mcxt, format_type_be(), get_type_io_data(), i, IOFunc_receive, MAXDIM, MemoryContextAlloc(), ArrayType::ndim, NULL, OidIsValid, palloc(), palloc0(), pfree(), PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_ARRAYTYPE_P, pq_getmsgint(), ArrayMetaState::proc, ReadArrayBinary(), SET_VARSIZE, ArrayMetaState::typalign, ArrayMetaState::typbyval, ArrayMetaState::typdelim, ArrayMetaState::typiofunc, ArrayMetaState::typioparam, and ArrayMetaState::typlen.
Referenced by int2vectorrecv(), and oidvectorrecv().
{ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); Oid spec_element_type = PG_GETARG_OID(1); /* type of an array * element */ int32 typmod = PG_GETARG_INT32(2); /* typmod for array elements */ Oid element_type; int typlen; bool typbyval; char typalign; Oid typioparam; int i, nitems; Datum *dataPtr; bool *nullsPtr; bool hasnulls; int32 nbytes; int32 dataoffset; ArrayType *retval; int ndim, flags, dim[MAXDIM], lBound[MAXDIM]; ArrayMetaState *my_extra; /* Get the array header information */ ndim = pq_getmsgint(buf, 4); if (ndim < 0) /* we do allow zero-dimension arrays */ ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid number of dimensions: %d", ndim))); if (ndim > MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", ndim, MAXDIM))); flags = pq_getmsgint(buf, 4); if (flags != 0 && flags != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid array flags"))); element_type = pq_getmsgint(buf, sizeof(Oid)); if (element_type != spec_element_type) { /* XXX Can we allow taking the input element type in any cases? */ ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("wrong element type"))); } for (i = 0; i < ndim; i++) { dim[i] = pq_getmsgint(buf, 4); lBound[i] = pq_getmsgint(buf, 4); /* * Check overflow of upper bound. (ArrayNItems() below checks that * dim[i] >= 0) */ if (dim[i] != 0) { int ub = lBound[i] + dim[i] - 1; if (lBound[i] > ub) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } } /* This checks for overflow of array dimensions */ nitems = ArrayGetNItems(ndim, dim); /* * We arrange to look up info about element type, including its receive * conversion proc, only once per series of calls, assuming the element * type doesn't change underneath us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { /* Get info about element type, including its receive proc */ get_type_io_data(element_type, IOFunc_receive, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign, &my_extra->typdelim, &my_extra->typioparam, &my_extra->typiofunc); if (!OidIsValid(my_extra->typiofunc)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("no binary input function available for type %s", format_type_be(element_type)))); fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc, fcinfo->flinfo->fn_mcxt); my_extra->element_type = element_type; } if (nitems == 0) { /* Return empty array ... but not till we've validated element_type */ PG_RETURN_ARRAYTYPE_P(construct_empty_array(element_type)); } typlen = my_extra->typlen; typbyval = my_extra->typbyval; typalign = my_extra->typalign; typioparam = my_extra->typioparam; dataPtr = (Datum *) palloc(nitems * sizeof(Datum)); nullsPtr = (bool *) palloc(nitems * sizeof(bool)); ReadArrayBinary(buf, nitems, &my_extra->proc, typioparam, typmod, typlen, typbyval, typalign, dataPtr, nullsPtr, &hasnulls, &nbytes); if (hasnulls) { dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems); nbytes += dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ nbytes += ARR_OVERHEAD_NONULLS(ndim); } retval = (ArrayType *) palloc0(nbytes); SET_VARSIZE(retval, nbytes); retval->ndim = ndim; retval->dataoffset = dataoffset; retval->elemtype = element_type; memcpy(ARR_DIMS(retval), dim, ndim * sizeof(int)); memcpy(ARR_LBOUND(retval), lBound, ndim * sizeof(int)); CopyArrayEls(retval, dataPtr, nullsPtr, nitems, typlen, typbyval, typalign, true); pfree(dataPtr); pfree(nullsPtr); PG_RETURN_ARRAYTYPE_P(retval); }
Datum array_ref | ( | ArrayType * | array, | |
int | nSubscripts, | |||
int * | indx, | |||
int | arraytyplen, | |||
int | elmlen, | |||
bool | elmbyval, | |||
char | elmalign, | |||
bool * | isNull | |||
) |
Definition at line 1764 of file arrayfuncs.c.
References ARR_DATA_PTR, ARR_DIMS, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, array_get_isnull(), array_seek(), ArrayCast(), ArrayGetOffset(), DatumGetArrayTypeP, i, MAXDIM, and PointerGetDatum.
Referenced by ExecEvalArrayRef(), GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), pg_get_functiondef(), PLyList_FromArray(), and ProcessGUCArray().
{ int i, ndim, *dim, *lb, offset, fixedDim[1], fixedLb[1]; char *arraydataptr, *retptr; bits8 *arraynullsptr; if (arraytyplen > 0) { /* * fixed-length arrays -- these are assumed to be 1-d, 0-based */ ndim = 1; fixedDim[0] = arraytyplen / elmlen; fixedLb[0] = 0; dim = fixedDim; lb = fixedLb; arraydataptr = (char *) array; arraynullsptr = NULL; } else { /* detoast input array if necessary */ array = DatumGetArrayTypeP(PointerGetDatum(array)); ndim = ARR_NDIM(array); dim = ARR_DIMS(array); lb = ARR_LBOUND(array); arraydataptr = ARR_DATA_PTR(array); arraynullsptr = ARR_NULLBITMAP(array); } /* * Return NULL for invalid subscript */ if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM) { *isNull = true; return (Datum) 0; } for (i = 0; i < ndim; i++) { if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i])) { *isNull = true; return (Datum) 0; } } /* * Calculate the element number */ offset = ArrayGetOffset(nSubscripts, dim, lb, indx); /* * Check for NULL array element */ if (array_get_isnull(arraynullsptr, offset)) { *isNull = true; return (Datum) 0; } /* * OK, get the element */ *isNull = false; retptr = array_seek(arraydataptr, 0, arraynullsptr, offset, elmlen, elmbyval, elmalign); return ArrayCast(retptr, elmbyval, elmlen); }
Datum array_remove | ( | PG_FUNCTION_ARGS | ) |
Definition at line 5443 of file arrayfuncs.c.
References array_replace_internal(), PG_ARGISNULL, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_ARRAYTYPE_P, and PG_RETURN_NULL.
{ ArrayType *array; Datum search = PG_GETARG_DATUM(1); bool search_isnull = PG_ARGISNULL(1); if (PG_ARGISNULL(0)) PG_RETURN_NULL(); array = PG_GETARG_ARRAYTYPE_P(0); array = array_replace_internal(array, search, search_isnull, (Datum) 0, true, true, PG_GET_COLLATION(), fcinfo); PG_RETURN_ARRAYTYPE_P(array); }
Datum array_replace | ( | PG_FUNCTION_ARGS | ) |
Definition at line 5465 of file arrayfuncs.c.
References array_replace_internal(), PG_ARGISNULL, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, PG_GETARG_DATUM, PG_RETURN_ARRAYTYPE_P, and PG_RETURN_NULL.
{ ArrayType *array; Datum search = PG_GETARG_DATUM(1); bool search_isnull = PG_ARGISNULL(1); Datum replace = PG_GETARG_DATUM(2); bool replace_isnull = PG_ARGISNULL(2); if (PG_ARGISNULL(0)) PG_RETURN_NULL(); array = PG_GETARG_ARRAYTYPE_P(0); array = array_replace_internal(array, search, search_isnull, replace, replace_isnull, false, PG_GET_COLLATION(), fcinfo); PG_RETURN_ARRAYTYPE_P(array); }
Datum array_send | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1493 of file arrayfuncs.c.
References ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_LBOUND, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), att_addlength_pointer, att_align_nominal, buf, ArrayMetaState::element_type, ereport, errcode(), errmsg(), ERROR, fetch_att, fmgr_info_cxt(), FmgrInfo::fn_mcxt, format_type_be(), get_type_io_data(), i, IOFunc_send, MemoryContextAlloc(), NULL, OidIsValid, pfree(), PG_GETARG_ARRAYTYPE_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendbytes(), pq_sendint(), ArrayMetaState::proc, SendFunctionCall(), ArrayMetaState::typalign, ArrayMetaState::typbyval, ArrayMetaState::typdelim, ArrayMetaState::typiofunc, ArrayMetaState::typioparam, ArrayMetaState::typlen, VARDATA, VARHDRSZ, and VARSIZE.
Referenced by anyarray_send(), int2vectorsend(), and oidvectorsend().
{ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); Oid element_type = ARR_ELEMTYPE(v); int typlen; bool typbyval; char typalign; char *p; bits8 *bitmap; int bitmask; int nitems, i; int ndim, *dim; StringInfoData buf; ArrayMetaState *my_extra; /* * We arrange to look up info about element type, including its send * conversion proc, only once per series of calls, assuming the element * type doesn't change underneath us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { /* Get info about element type, including its send proc */ get_type_io_data(element_type, IOFunc_send, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign, &my_extra->typdelim, &my_extra->typioparam, &my_extra->typiofunc); if (!OidIsValid(my_extra->typiofunc)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("no binary output function available for type %s", format_type_be(element_type)))); fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc, fcinfo->flinfo->fn_mcxt); my_extra->element_type = element_type; } typlen = my_extra->typlen; typbyval = my_extra->typbyval; typalign = my_extra->typalign; ndim = ARR_NDIM(v); dim = ARR_DIMS(v); nitems = ArrayGetNItems(ndim, dim); pq_begintypsend(&buf); /* Send the array header information */ pq_sendint(&buf, ndim, 4); pq_sendint(&buf, ARR_HASNULL(v) ? 1 : 0, 4); pq_sendint(&buf, element_type, sizeof(Oid)); for (i = 0; i < ndim; i++) { pq_sendint(&buf, ARR_DIMS(v)[i], 4); pq_sendint(&buf, ARR_LBOUND(v)[i], 4); } /* Send the array elements using the element's own sendproc */ p = ARR_DATA_PTR(v); bitmap = ARR_NULLBITMAP(v); bitmask = 1; for (i = 0; i < nitems; i++) { /* Get source element, checking for NULL */ if (bitmap && (*bitmap & bitmask) == 0) { /* -1 length means a NULL */ pq_sendint(&buf, -1, 4); } else { Datum itemvalue; bytea *outputbytes; itemvalue = fetch_att(p, typbyval, typlen); outputbytes = SendFunctionCall(&my_extra->proc, itemvalue); pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4); pq_sendbytes(&buf, VARDATA(outputbytes), VARSIZE(outputbytes) - VARHDRSZ); pfree(outputbytes); p = att_addlength_pointer(p, typlen, p); p = (char *) att_align_nominal(p, typalign); } /* advance bitmap pointer if any */ if (bitmap) { bitmask <<= 1; if (bitmask == 0x100) { bitmap++; bitmask = 1; } } } PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
ArrayType* array_set | ( | ArrayType * | array, | |
int | nSubscripts, | |||
int * | indx, | |||
Datum | dataValue, | |||
bool | isNull, | |||
int | arraytyplen, | |||
int | elmlen, | |||
bool | elmbyval, | |||
char | elmalign | |||
) |
Definition at line 2040 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_isnull(), ArrayCastAndSet(), ArrayGetNItems(), ArrayGetOffset(), att_addlength_datum, att_addlength_pointer, att_align_nominal, construct_md_array(), ArrayType::dataoffset, DatumGetArrayTypeP, ArrayType::elemtype, ereport, errcode(), errmsg(), ERROR, i, MAXDIM, MemSet, ArrayType::ndim, palloc(), palloc0(), PG_DETOAST_DATUM, PointerGetDatum, and SET_VARSIZE.
Referenced by array_push(), exec_assign_value(), ExecEvalArrayRef(), GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), and pg_extension_config_dump().
{ ArrayType *newarray; int i, ndim, dim[MAXDIM], lb[MAXDIM], offset; char *elt_ptr; bool newhasnulls; bits8 *oldnullbitmap; int oldnitems, newnitems, olddatasize, newsize, olditemlen, newitemlen, overheadlen, oldoverheadlen, addedbefore, addedafter, lenbefore, lenafter; if (arraytyplen > 0) { /* * fixed-length arrays -- these are assumed to be 1-d, 0-based. We * cannot extend them, either. */ if (nSubscripts != 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); if (indx[0] < 0 || indx[0] * elmlen >= arraytyplen) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array subscript out of range"))); if (isNull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("cannot assign null value to an element of a fixed-length array"))); newarray = (ArrayType *) palloc(arraytyplen); memcpy(newarray, array, arraytyplen); elt_ptr = (char *) newarray + indx[0] * elmlen; ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elt_ptr); return newarray; } if (nSubscripts <= 0 || nSubscripts > MAXDIM) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); /* make sure item to be inserted is not toasted */ if (elmlen == -1 && !isNull) dataValue = PointerGetDatum(PG_DETOAST_DATUM(dataValue)); /* detoast input array if necessary */ array = DatumGetArrayTypeP(PointerGetDatum(array)); ndim = ARR_NDIM(array); /* * if number of dims is zero, i.e. an empty array, create an array with * nSubscripts dimensions, and set the lower bounds to the supplied * subscripts */ if (ndim == 0) { Oid elmtype = ARR_ELEMTYPE(array); for (i = 0; i < nSubscripts; i++) { dim[i] = 1; lb[i] = indx[i]; } return construct_md_array(&dataValue, &isNull, nSubscripts, dim, lb, elmtype, elmlen, elmbyval, elmalign); } if (ndim != nSubscripts) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); /* copy dim/lb since we may modify them */ memcpy(dim, ARR_DIMS(array), ndim * sizeof(int)); memcpy(lb, ARR_LBOUND(array), ndim * sizeof(int)); newhasnulls = (ARR_HASNULL(array) || isNull); addedbefore = addedafter = 0; /* * Check subscripts */ if (ndim == 1) { if (indx[0] < lb[0]) { addedbefore = lb[0] - indx[0]; dim[0] += addedbefore; lb[0] = indx[0]; if (addedbefore > 1) newhasnulls = true; /* will insert nulls */ } if (indx[0] >= (dim[0] + lb[0])) { addedafter = indx[0] - (dim[0] + lb[0]) + 1; dim[0] += addedafter; if (addedafter > 1) newhasnulls = true; /* will insert nulls */ } } else { /* * XXX currently we do not support extending multi-dimensional arrays * during assignment */ for (i = 0; i < ndim; i++) { if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i])) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array subscript out of range"))); } } /* * Compute sizes of items and areas to copy */ newnitems = ArrayGetNItems(ndim, dim); if (newhasnulls) overheadlen = ARR_OVERHEAD_WITHNULLS(ndim, newnitems); else overheadlen = ARR_OVERHEAD_NONULLS(ndim); oldnitems = ArrayGetNItems(ndim, ARR_DIMS(array)); oldnullbitmap = ARR_NULLBITMAP(array); oldoverheadlen = ARR_DATA_OFFSET(array); olddatasize = ARR_SIZE(array) - oldoverheadlen; if (addedbefore) { offset = 0; lenbefore = 0; olditemlen = 0; lenafter = olddatasize; } else if (addedafter) { offset = oldnitems; lenbefore = olddatasize; olditemlen = 0; lenafter = 0; } else { offset = ArrayGetOffset(nSubscripts, dim, lb, indx); elt_ptr = array_seek(ARR_DATA_PTR(array), 0, oldnullbitmap, offset, elmlen, elmbyval, elmalign); lenbefore = (int) (elt_ptr - ARR_DATA_PTR(array)); if (array_get_isnull(oldnullbitmap, offset)) olditemlen = 0; else { olditemlen = att_addlength_pointer(0, elmlen, elt_ptr); olditemlen = att_align_nominal(olditemlen, elmalign); } lenafter = (int) (olddatasize - lenbefore - olditemlen); } if (isNull) newitemlen = 0; else { newitemlen = att_addlength_datum(0, elmlen, dataValue); newitemlen = att_align_nominal(newitemlen, elmalign); } newsize = overheadlen + lenbefore + newitemlen + lenafter; /* * OK, create the new array and fill in header/dimensions */ newarray = (ArrayType *) palloc0(newsize); SET_VARSIZE(newarray, newsize); newarray->ndim = ndim; newarray->dataoffset = newhasnulls ? overheadlen : 0; newarray->elemtype = ARR_ELEMTYPE(array); memcpy(ARR_DIMS(newarray), dim, ndim * sizeof(int)); memcpy(ARR_LBOUND(newarray), lb, ndim * sizeof(int)); /* * Fill in data */ memcpy((char *) newarray + overheadlen, (char *) array + oldoverheadlen, lenbefore); if (!isNull) ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, (char *) newarray + overheadlen + lenbefore); memcpy((char *) newarray + overheadlen + lenbefore + newitemlen, (char *) array + oldoverheadlen + lenbefore + olditemlen, lenafter); /* * Fill in nulls bitmap if needed * * Note: it's possible we just replaced the last NULL with a non-NULL, and * could get rid of the bitmap. Seems not worth testing for though. */ if (newhasnulls) { bits8 *newnullbitmap = ARR_NULLBITMAP(newarray); /* Zero the bitmap to take care of marking inserted positions null */ MemSet(newnullbitmap, 0, (newnitems + 7) / 8); /* Fix the inserted value */ if (addedafter) array_set_isnull(newnullbitmap, newnitems - 1, isNull); else array_set_isnull(newnullbitmap, offset, isNull); /* Fix the copied range(s) */ if (addedbefore) array_bitmap_copy(newnullbitmap, addedbefore, oldnullbitmap, 0, oldnitems); else { array_bitmap_copy(newnullbitmap, 0, oldnullbitmap, 0, offset); if (addedafter == 0) array_bitmap_copy(newnullbitmap, offset + 1, oldnullbitmap, offset + 1, oldnitems - offset - 1); } } return newarray; }
ArrayType* array_set_slice | ( | ArrayType * | array, | |
int | nSubscripts, | |||
int * | upperIndx, | |||
int * | lowerIndx, | |||
ArrayType * | srcArray, | |||
bool | isNull, | |||
int | arraytyplen, | |||
int | elmlen, | |||
bool | elmbyval, | |||
char | elmalign | |||
) |
Definition at line 2332 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(), errmsg(), ERROR, i, Max, MAXDIM, mda_get_range(), MemSet, Min, ArrayType::ndim, palloc0(), PointerGetDatum, and SET_VARSIZE.
Referenced by ExecEvalArrayRef().
{ ArrayType *newarray; int i, ndim, dim[MAXDIM], lb[MAXDIM], span[MAXDIM]; bool newhasnulls; int nitems, nsrcitems, olddatasize, newsize, olditemsize, newitemsize, overheadlen, oldoverheadlen, addedbefore, addedafter, lenbefore, lenafter, itemsbefore, itemsafter, nolditems; /* Currently, assignment from a NULL source array is a no-op */ if (isNull) return array; if (arraytyplen > 0) { /* * fixed-length arrays -- not got round to doing this... */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("updates on slices of fixed-length arrays not implemented"))); } /* detoast arrays if necessary */ array = DatumGetArrayTypeP(PointerGetDatum(array)); srcArray = DatumGetArrayTypeP(PointerGetDatum(srcArray)); /* note: we assume srcArray contains no toasted elements */ ndim = ARR_NDIM(array); /* * if number of dims is zero, i.e. an empty array, create an array with * nSubscripts dimensions, and set the upper and lower bounds to the * supplied subscripts */ if (ndim == 0) { Datum *dvalues; bool *dnulls; int nelems; Oid elmtype = ARR_ELEMTYPE(array); deconstruct_array(srcArray, elmtype, elmlen, elmbyval, elmalign, &dvalues, &dnulls, &nelems); for (i = 0; i < nSubscripts; i++) { dim[i] = 1 + upperIndx[i] - lowerIndx[i]; lb[i] = lowerIndx[i]; } /* complain if too few source items; we ignore extras, however */ if (nelems < ArrayGetNItems(nSubscripts, dim)) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("source array too small"))); return construct_md_array(dvalues, dnulls, nSubscripts, dim, lb, elmtype, elmlen, elmbyval, elmalign); } if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); /* copy dim/lb since we may modify them */ memcpy(dim, ARR_DIMS(array), ndim * sizeof(int)); memcpy(lb, ARR_LBOUND(array), ndim * sizeof(int)); newhasnulls = (ARR_HASNULL(array) || ARR_HASNULL(srcArray)); addedbefore = addedafter = 0; /* * Check subscripts */ if (ndim == 1) { Assert(nSubscripts == 1); if (lowerIndx[0] > upperIndx[0]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("upper bound cannot be less than lower bound"))); if (lowerIndx[0] < lb[0]) { if (upperIndx[0] < lb[0] - 1) newhasnulls = true; /* will insert nulls */ addedbefore = lb[0] - lowerIndx[0]; dim[0] += addedbefore; lb[0] = lowerIndx[0]; } if (upperIndx[0] >= (dim[0] + lb[0])) { if (lowerIndx[0] > (dim[0] + lb[0])) newhasnulls = true; /* will insert nulls */ addedafter = upperIndx[0] - (dim[0] + lb[0]) + 1; dim[0] += addedafter; } } else { /* * XXX currently we do not support extending multi-dimensional arrays * during assignment */ for (i = 0; i < nSubscripts; i++) { if (lowerIndx[i] > upperIndx[i]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("upper bound cannot be less than lower bound"))); if (lowerIndx[i] < lb[i] || upperIndx[i] >= (dim[i] + lb[i])) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array subscript out of range"))); } /* fill any missing subscript positions with full array range */ for (; i < ndim; i++) { lowerIndx[i] = lb[i]; upperIndx[i] = dim[i] + lb[i] - 1; if (lowerIndx[i] > upperIndx[i]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("upper bound cannot be less than lower bound"))); } } /* Do this mainly to check for overflow */ nitems = ArrayGetNItems(ndim, dim); /* * Make sure source array has enough entries. Note we ignore the shape of * the source array and just read entries serially. */ mda_get_range(ndim, span, lowerIndx, upperIndx); nsrcitems = ArrayGetNItems(ndim, span); if (nsrcitems > ArrayGetNItems(ARR_NDIM(srcArray), ARR_DIMS(srcArray))) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("source array too small"))); /* * Compute space occupied by new entries, space occupied by replaced * entries, and required space for new array. */ if (newhasnulls) overheadlen = ARR_OVERHEAD_WITHNULLS(ndim, nitems); else overheadlen = ARR_OVERHEAD_NONULLS(ndim); newitemsize = array_nelems_size(ARR_DATA_PTR(srcArray), 0, ARR_NULLBITMAP(srcArray), nsrcitems, elmlen, elmbyval, elmalign); oldoverheadlen = ARR_DATA_OFFSET(array); olddatasize = ARR_SIZE(array) - oldoverheadlen; if (ndim > 1) { /* * here we do not need to cope with extension of the array; it would * be a lot more complicated if we had to do so... */ olditemsize = array_slice_size(ARR_DATA_PTR(array), ARR_NULLBITMAP(array), ndim, dim, lb, lowerIndx, upperIndx, elmlen, elmbyval, elmalign); lenbefore = lenafter = 0; /* keep compiler quiet */ itemsbefore = itemsafter = nolditems = 0; } else { /* * here we must allow for possibility of slice larger than orig array * and/or not adjacent to orig array subscripts */ int oldlb = ARR_LBOUND(array)[0]; int oldub = oldlb + ARR_DIMS(array)[0] - 1; int slicelb = Max(oldlb, lowerIndx[0]); int sliceub = Min(oldub, upperIndx[0]); char *oldarraydata = ARR_DATA_PTR(array); bits8 *oldarraybitmap = ARR_NULLBITMAP(array); /* count/size of old array entries that will go before the slice */ itemsbefore = Min(slicelb, oldub + 1) - oldlb; lenbefore = array_nelems_size(oldarraydata, 0, oldarraybitmap, itemsbefore, elmlen, elmbyval, elmalign); /* count/size of old array entries that will be replaced by slice */ if (slicelb > sliceub) { nolditems = 0; olditemsize = 0; } else { nolditems = sliceub - slicelb + 1; olditemsize = array_nelems_size(oldarraydata + lenbefore, itemsbefore, oldarraybitmap, nolditems, elmlen, elmbyval, elmalign); } /* count/size of old array entries that will go after the slice */ itemsafter = oldub + 1 - Max(sliceub + 1, oldlb); lenafter = olddatasize - lenbefore - olditemsize; } newsize = overheadlen + olddatasize - olditemsize + newitemsize; newarray = (ArrayType *) palloc0(newsize); SET_VARSIZE(newarray, newsize); newarray->ndim = ndim; newarray->dataoffset = newhasnulls ? overheadlen : 0; newarray->elemtype = ARR_ELEMTYPE(array); memcpy(ARR_DIMS(newarray), dim, ndim * sizeof(int)); memcpy(ARR_LBOUND(newarray), lb, ndim * sizeof(int)); if (ndim > 1) { /* * here we do not need to cope with extension of the array; it would * be a lot more complicated if we had to do so... */ array_insert_slice(newarray, array, srcArray, ndim, dim, lb, lowerIndx, upperIndx, elmlen, elmbyval, elmalign); } else { /* fill in data */ memcpy((char *) newarray + overheadlen, (char *) array + oldoverheadlen, lenbefore); memcpy((char *) newarray + overheadlen + lenbefore, ARR_DATA_PTR(srcArray), newitemsize); memcpy((char *) newarray + overheadlen + lenbefore + newitemsize, (char *) array + oldoverheadlen + lenbefore + olditemsize, lenafter); /* fill in nulls bitmap if needed */ if (newhasnulls) { bits8 *newnullbitmap = ARR_NULLBITMAP(newarray); bits8 *oldnullbitmap = ARR_NULLBITMAP(array); /* Zero the bitmap to handle marking inserted positions null */ MemSet(newnullbitmap, 0, (nitems + 7) / 8); array_bitmap_copy(newnullbitmap, addedbefore, oldnullbitmap, 0, itemsbefore); array_bitmap_copy(newnullbitmap, lowerIndx[0] - lb[0], ARR_NULLBITMAP(srcArray), 0, nsrcitems); array_bitmap_copy(newnullbitmap, addedbefore + itemsbefore + nolditems, oldnullbitmap, itemsbefore + nolditems, itemsafter); } } return newarray; }
Datum array_smaller | ( | PG_FUNCTION_ARGS | ) |
Definition at line 4705 of file arrayfuncs.c.
References array_cmp(), PG_GETARG_ARRAYTYPE_P, and PG_RETURN_ARRAYTYPE_P.
{ ArrayType *v1, *v2, *result; v1 = PG_GETARG_ARRAYTYPE_P(0); v2 = PG_GETARG_ARRAYTYPE_P(1); result = ((array_cmp(fcinfo) < 0) ? v1 : v2); PG_RETURN_ARRAYTYPE_P(result); }
Datum array_typanalyze | ( | PG_FUNCTION_ARGS | ) |
Definition at line 97 of file array_typanalyze.c.
References VacAttrStats::attrtypid, ArrayAnalyzeExtraData::cmp, TypeCacheEntry::cmp_proc_finfo, VacAttrStats::compute_stats, elog, ArrayAnalyzeExtraData::eq_opr, TypeCacheEntry::eq_opr, ERROR, VacAttrStats::extra_data, FmgrInfo::fn_oid, get_base_element_type(), ArrayAnalyzeExtraData::hash, TypeCacheEntry::hash_proc_finfo, lookup_type_cache(), OidIsValid, palloc(), PG_GETARG_POINTER, PG_RETURN_BOOL, ArrayAnalyzeExtraData::std_compute_stats, ArrayAnalyzeExtraData::std_extra_data, std_typanalyze(), TypeCacheEntry::typalign, ArrayAnalyzeExtraData::typalign, TypeCacheEntry::typbyval, ArrayAnalyzeExtraData::typbyval, TypeCacheEntry::type_id, ArrayAnalyzeExtraData::type_id, TYPECACHE_CMP_PROC_FINFO, TYPECACHE_EQ_OPR, TYPECACHE_HASH_PROC_FINFO, TypeCacheEntry::typlen, and ArrayAnalyzeExtraData::typlen.
{ VacAttrStats *stats = (VacAttrStats *) PG_GETARG_POINTER(0); Oid element_typeid; TypeCacheEntry *typentry; ArrayAnalyzeExtraData *extra_data; /* * Call the standard typanalyze function. It may fail to find needed * operators, in which case we also can't do anything, so just fail. */ if (!std_typanalyze(stats)) PG_RETURN_BOOL(false); /* * Check attribute data type is a varlena array (or a domain over one). */ element_typeid = get_base_element_type(stats->attrtypid); if (!OidIsValid(element_typeid)) elog(ERROR, "array_typanalyze was invoked for non-array type %u", stats->attrtypid); /* * Gather information about the element type. If we fail to find * something, return leaving the state from std_typanalyze() in place. */ typentry = lookup_type_cache(element_typeid, TYPECACHE_EQ_OPR | TYPECACHE_CMP_PROC_FINFO | TYPECACHE_HASH_PROC_FINFO); if (!OidIsValid(typentry->eq_opr) || !OidIsValid(typentry->cmp_proc_finfo.fn_oid) || !OidIsValid(typentry->hash_proc_finfo.fn_oid)) PG_RETURN_BOOL(true); /* Store our findings for use by compute_array_stats() */ extra_data = (ArrayAnalyzeExtraData *) palloc(sizeof(ArrayAnalyzeExtraData)); extra_data->type_id = typentry->type_id; extra_data->eq_opr = typentry->eq_opr; extra_data->typbyval = typentry->typbyval; extra_data->typlen = typentry->typlen; extra_data->typalign = typentry->typalign; extra_data->cmp = &typentry->cmp_proc_finfo; extra_data->hash = &typentry->hash_proc_finfo; /* Save old compute_stats and extra_data for scalar statistics ... */ extra_data->std_compute_stats = stats->compute_stats; extra_data->std_extra_data = stats->extra_data; /* ... and replace with our info */ stats->compute_stats = compute_array_stats; stats->extra_data = extra_data; /* * Note we leave stats->minrows set as std_typanalyze set it. Should it * be increased for array analysis purposes? */ PG_RETURN_BOOL(true); }
Datum array_unnest | ( | PG_FUNCTION_ARGS | ) |
Definition at line 5079 of file arrayfuncs.c.
References ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, ARR_NULLBITMAP, array_get_isnull(), ArrayCast(), ArrayGetNItems(), att_addlength_pointer, att_align_nominal, get_typlenbyvalalign(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, palloc(), PG_GETARG_ARRAYTYPE_P, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and FuncCallContext::user_fctx.
{ typedef struct { ArrayType *arr; int nextelem; int numelems; char *elemdataptr; /* this moves with nextelem */ bits8 *arraynullsptr; /* this does not */ int16 elmlen; bool elmbyval; char elmalign; } array_unnest_fctx; FuncCallContext *funcctx; array_unnest_fctx *fctx; MemoryContext oldcontext; /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { ArrayType *arr; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); /* * switch to memory context appropriate for multiple function calls */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* * Get the array value and detoast if needed. We can't do this * earlier because if we have to detoast, we want the detoasted copy * to be in multi_call_memory_ctx, so it will go away when we're done * and not before. (If no detoast happens, we assume the originally * passed array will stick around till then.) */ arr = PG_GETARG_ARRAYTYPE_P(0); /* allocate memory for user context */ fctx = (array_unnest_fctx *) palloc(sizeof(array_unnest_fctx)); /* initialize state */ fctx->arr = arr; fctx->nextelem = 0; fctx->numelems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr)); fctx->elemdataptr = ARR_DATA_PTR(arr); fctx->arraynullsptr = ARR_NULLBITMAP(arr); get_typlenbyvalalign(ARR_ELEMTYPE(arr), &fctx->elmlen, &fctx->elmbyval, &fctx->elmalign); funcctx->user_fctx = fctx; MemoryContextSwitchTo(oldcontext); } /* stuff done on every call of the function */ funcctx = SRF_PERCALL_SETUP(); fctx = funcctx->user_fctx; if (fctx->nextelem < fctx->numelems) { int offset = fctx->nextelem++; Datum elem; /* * Check for NULL array element */ if (array_get_isnull(fctx->arraynullsptr, offset)) { fcinfo->isnull = true; elem = (Datum) 0; /* elemdataptr does not move */ } else { /* * OK, get the element */ char *ptr = fctx->elemdataptr; fcinfo->isnull = false; elem = ArrayCast(ptr, fctx->elmbyval, fctx->elmlen); /* * Advance elemdataptr over it */ ptr = att_addlength_pointer(ptr, fctx->elmlen, ptr); ptr = (char *) att_align_nominal(ptr, fctx->elmalign); fctx->elemdataptr = ptr; } SRF_RETURN_NEXT(funcctx, elem); } else { /* do when there is no more left */ SRF_RETURN_DONE(funcctx); } }
Datum array_upper | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1690 of file arrayfuncs.c.
References ARR_DIMS, ARR_LBOUND, ARR_NDIM, MAXDIM, PG_GETARG_ARRAYTYPE_P, PG_GETARG_INT32, PG_RETURN_INT32, and PG_RETURN_NULL.
{ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int reqdim = PG_GETARG_INT32(1); int *dimv, *lb; int result; /* Sanity check: does it look like an array at all? */ if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM) PG_RETURN_NULL(); /* Sanity check: was the requested dim valid */ if (reqdim <= 0 || reqdim > ARR_NDIM(v)) PG_RETURN_NULL(); lb = ARR_LBOUND(v); dimv = ARR_DIMS(v); result = dimv[reqdim - 1] + lb[reqdim - 1] - 1; PG_RETURN_INT32(result); }
Datum arraycontained | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3856 of file arrayfuncs.c.
References array_contain_compare(), PG_FREE_IF_COPY, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, and PG_RETURN_BOOL.
{ ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0); ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1); Oid collation = PG_GET_COLLATION(); bool result; result = array_contain_compare(array1, array2, collation, true, &fcinfo->flinfo->fn_extra); /* Avoid leaking memory when handed toasted input. */ PG_FREE_IF_COPY(array1, 0); PG_FREE_IF_COPY(array2, 1); PG_RETURN_BOOL(result); }
Datum arraycontains | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3838 of file arrayfuncs.c.
References array_contain_compare(), PG_FREE_IF_COPY, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, and PG_RETURN_BOOL.
{ ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0); ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1); Oid collation = PG_GET_COLLATION(); bool result; result = array_contain_compare(array2, array1, collation, true, &fcinfo->flinfo->fn_extra); /* Avoid leaking memory when handed toasted input. */ PG_FREE_IF_COPY(array1, 0); PG_FREE_IF_COPY(array2, 1); PG_RETURN_BOOL(result); }
Definition at line 200 of file arrayutils.c.
References ARR_ELEMTYPE, ARR_NDIM, array_contains_nulls(), CSTRINGOID, DatumGetCString, deconstruct_array(), ereport, errcode(), errmsg(), ERROR, i, NULL, palloc(), pfree(), and pg_atoi().
Referenced by anybit_typmodin(), anychar_typmodin(), anytime_typmodin(), anytimestamp_typmodin(), intervaltypmodin(), and numerictypmodin().
{ int32 *result; Datum *elem_values; int i; if (ARR_ELEMTYPE(arr) != CSTRINGOID) ereport(ERROR, (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), errmsg("typmod array must be type cstring[]"))); if (ARR_NDIM(arr) != 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("typmod array must be one-dimensional"))); if (array_contains_nulls(arr)) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("typmod array must not contain nulls"))); /* hardwired knowledge about cstring's representation details here */ deconstruct_array(arr, CSTRINGOID, -2, false, 'c', &elem_values, NULL, n); result = (int32 *) palloc(*n * sizeof(int32)); for (i = 0; i < *n; i++) result[i] = pg_atoi(DatumGetCString(elem_values[i]), sizeof(int32), '\0'); pfree(elem_values); return result; }
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(), 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(), array_set_slice(), array_slice_size(), array_to_json_internal(), array_to_text_internal(), array_unnest(), arrq_cons(), construct_md_array(), deconstruct_array(), estimate_array_length(), ExecEvalArray(), ExecEvalScalarArrayOp(), get_text_array_contents(), getWeights(), hash_array(), is_strict_saop(), lt_q_regex(), predicate_classify(), and tsa_rewrite_accum().
{ int32 ret; int i; #define MaxArraySize ((Size) (MaxAllocSize / sizeof(Datum))) if (ndim <= 0) return 0; ret = 1; for (i = 0; i < ndim; i++) { int64 prod; /* A negative dimension implies that UB-LB overflowed ... */ if (dims[i] < 0) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("array size exceeds the maximum allowed (%d)", (int) MaxArraySize))); prod = (int64) ret *(int64) dims[i]; ret = (int32) prod; if ((int64) ret != prod) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("array size exceeds the maximum allowed (%d)", (int) MaxArraySize))); } Assert(ret >= 0); if ((Size) ret > MaxArraySize) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("array size exceeds the maximum allowed (%d)", (int) MaxArraySize))); return (int) ret; }
int ArrayGetOffset | ( | int | n, | |
const int * | dim, | |||
const int * | lb, | |||
const int * | indx | |||
) |
Definition at line 31 of file arrayutils.c.
Referenced by array_extract_slice(), array_insert_slice(), array_ref(), array_set(), and array_slice_size().
int ArrayGetOffset0 | ( | int | n, | |
const int * | tup, | |||
const int * | scale | |||
) |
Datum arrayoverlap | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3820 of file arrayfuncs.c.
References array_contain_compare(), PG_FREE_IF_COPY, PG_GET_COLLATION, PG_GETARG_ARRAYTYPE_P, and PG_RETURN_BOOL.
{ ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0); ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1); Oid collation = PG_GET_COLLATION(); bool result; result = array_contain_compare(array1, array2, collation, false, &fcinfo->flinfo->fn_extra); /* Avoid leaking memory when handed toasted input. */ PG_FREE_IF_COPY(array1, 0); PG_FREE_IF_COPY(array2, 1); PG_RETURN_BOOL(result); }
Datum btarraycmp | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3325 of file arrayfuncs.c.
References array_cmp(), and PG_RETURN_INT32.
{ PG_RETURN_INT32(array_cmp(fcinfo)); }
ArrayType* construct_array | ( | Datum * | elems, | |
int | nelems, | |||
Oid | elmtype, | |||
int | elmlen, | |||
bool | elmbyval, | |||
char | elmalign | |||
) |
Definition at line 2865 of file arrayfuncs.c.
References construct_md_array(), and NULL.
Referenced by build_regtype_array(), CreateConstraintEntry(), current_schemas(), do_numeric_accum(), do_numeric_avg_accum(), enum_range_internal(), examine_parameter_list(), extension_config_remove(), filter_list_to_array(), float4_accum(), float8_accum(), float8_regr_accum(), get_available_versions_for_extension(), GUCArrayAdd(), GUCArrayDelete(), GUCArrayReset(), hstore_akeys(), interval_accum(), pg_extension_config_dump(), show_trgm(), ts_lexize(), typenameTypeMod(), and update_attstats().
{ int dims[1]; int lbs[1]; dims[0] = nelems; lbs[0] = 1; return construct_md_array(elems, NULL, 1, dims, lbs, elmtype, elmlen, elmbyval, elmalign); }
Definition at line 2983 of file arrayfuncs.c.
References ArrayType::dataoffset, ArrayType::elemtype, ArrayType::ndim, palloc0(), and SET_VARSIZE.
Referenced by array_fill_internal(), array_get_slice(), array_in(), array_map(), array_push(), array_recv(), construct_md_array(), exec_assign_value(), ExecEvalArray(), ExecEvalArrayRef(), ExecScanSubPlan(), ExecSetParamPlan(), hstore_akeys(), hstore_avals(), hstore_slice_to_array(), hstore_to_array_internal(), plperl_array_to_datum(), text_to_array_internal(), transformGenericOptions(), and xpath().
{ ArrayType *result; result = (ArrayType *) palloc0(sizeof(ArrayType)); SET_VARSIZE(result, sizeof(ArrayType)); result->ndim = 0; result->dataoffset = 0; result->elemtype = elmtype; return result; }
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 2899 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(), array_set_slice(), build_regexp_matches_result(), construct_array(), create_singleton_array(), ExecEvalArray(), hstore_avals(), hstore_slice_to_array(), hstore_to_array_internal(), makeMdArrayResult(), plpgsql_exec_trigger(), and PLySequence_ToArray().
{ ArrayType *result; bool hasnulls; int32 nbytes; int32 dataoffset; int i; int nelems; if (ndims < 0) /* we do allow zero-dimension arrays */ ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid number of dimensions: %d", ndims))); if (ndims > MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", ndims, MAXDIM))); /* fast track for empty array */ if (ndims == 0) return construct_empty_array(elmtype); nelems = ArrayGetNItems(ndims, dims); /* compute required space */ nbytes = 0; hasnulls = false; for (i = 0; i < nelems; i++) { if (nulls && nulls[i]) { hasnulls = true; continue; } /* make sure data is not toasted */ if (elmlen == -1) elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i])); nbytes = att_addlength_datum(nbytes, elmlen, elems[i]); nbytes = att_align_nominal(nbytes, elmalign); /* check for overflow of total request */ if (!AllocSizeIsValid(nbytes)) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("array size exceeds the maximum allowed (%d)", (int) MaxAllocSize))); } /* Allocate and initialize result array */ if (hasnulls) { dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nelems); nbytes += dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ nbytes += ARR_OVERHEAD_NONULLS(ndims); } result = (ArrayType *) palloc0(nbytes); SET_VARSIZE(result, nbytes); result->ndim = ndims; result->dataoffset = dataoffset; result->elemtype = elmtype; memcpy(ARR_DIMS(result), dims, ndims * sizeof(int)); memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int)); CopyArrayEls(result, elems, nulls, nelems, elmlen, elmbyval, elmalign, false); return result; }
ArrayType* create_singleton_array | ( | FunctionCallInfo | fcinfo, | |
Oid | element_type, | |||
Datum | element, | |||
bool | isNull, | |||
int | ndims | |||
) |
Definition at line 407 of file array_userfuncs.c.
References construct_md_array(), ArrayMetaState::element_type, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, get_typlenbyvalalign(), i, MAXDIM, MemoryContextAlloc(), NULL, ArrayMetaState::typalign, ArrayMetaState::typbyval, and ArrayMetaState::typlen.
Referenced by text_to_array_internal().
{ Datum dvalues[1]; bool nulls[1]; int16 typlen; bool typbyval; char typalign; int dims[MAXDIM]; int lbs[MAXDIM]; int i; ArrayMetaState *my_extra; if (ndims < 1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid number of dimensions: %d", ndims))); if (ndims > MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", ndims, MAXDIM))); dvalues[0] = element; nulls[0] = isNull; for (i = 0; i < ndims; i++) { dims[i] = 1; lbs[i] = 1; } /* * We arrange to look up info about element type only once per series of * calls, assuming the element type doesn't change underneath us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { /* Get info about element type */ get_typlenbyvalalign(element_type, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign); my_extra->element_type = element_type; } typlen = my_extra->typlen; typbyval = my_extra->typbyval; typalign = my_extra->typalign; return construct_md_array(dvalues, nulls, ndims, dims, lbs, element_type, typlen, typbyval, typalign); }
void deconstruct_array | ( | ArrayType * | array, | |
Oid | elmtype, | |||
int | elmlen, | |||
bool | elmbyval, | |||
char | elmalign, | |||
Datum ** | elemsp, | |||
bool ** | nullsp, | |||
int * | nelemsp | |||
) |
Definition at line 3017 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(), arrayconst_startup_fn(), ArrayGetIntegerTypmods(), build_function_result_tupdesc_d(), compute_array_stats(), create_empty_extension(), DecodeTextArrayToCString(), decompile_column_index_array(), do_numeric_accum(), do_numeric_avg_accum(), ExecIndexEvalArrayKeys(), extension_config_remove(), generateClonedIndexStmt(), get_attstatsslot(), get_func_arg_info(), get_func_input_arg_names(), get_func_result_name(), get_path_all(), ghstore_consistent(), gin_extract_hstore_query(), ginarrayextract(), gincost_scalararrayopexpr(), ginqueryarrayextract(), hstore_from_array(), hstore_from_arrays(), hstore_slice_to_array(), hstoreArrayToPairs(), interval_accum(), interval_avg(), map_sql_value_to_xml_value(), mcelem_array_selec(), numeric_avg(), numeric_stddev_internal(), parseRelOptions(), pg_get_constraintdef_worker(), plperl_ref_from_pg_array(), scalararraysel(), text_format(), TidListCreate(), transformRelOptions(), tsa_rewrite_accum(), and untransformRelOptions().
{ Datum *elems; bool *nulls; int nelems; char *p; bits8 *bitmap; int bitmask; int i; Assert(ARR_ELEMTYPE(array) == elmtype); nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum)); if (nullsp) *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool)); else nulls = NULL; *nelemsp = nelems; p = ARR_DATA_PTR(array); bitmap = ARR_NULLBITMAP(array); bitmask = 1; for (i = 0; i < nelems; i++) { /* Get source element, checking for NULL */ if (bitmap && (*bitmap & bitmask) == 0) { elems[i] = (Datum) 0; if (nulls) nulls[i] = true; else ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("null array element not allowed in this context"))); } else { elems[i] = fetch_att(p, elmbyval, elmlen); p = att_addlength_pointer(p, elmlen, p); p = (char *) att_align_nominal(p, elmalign); } /* advance bitmap pointer if any */ if (bitmap) { bitmask <<= 1; if (bitmask == 0x100) { bitmap++; bitmask = 1; } } } }
Datum generate_subscripts | ( | PG_FUNCTION_ARGS | ) |
Definition at line 4732 of file arrayfuncs.c.
References ARR_DIMS, ARR_LBOUND, ARR_NDIM, Int32GetDatum, generate_subscripts_fctx::lower, MAXDIM, MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, palloc(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_BOOL, PG_GETARG_INT32, PG_NARGS, generate_subscripts_fctx::reverse, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, generate_subscripts_fctx::upper, and FuncCallContext::user_fctx.
Referenced by generate_subscripts_nodir().
{ FuncCallContext *funcctx; MemoryContext oldcontext; generate_subscripts_fctx *fctx; /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int reqdim = PG_GETARG_INT32(1); int *lb, *dimv; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); /* Sanity check: does it look like an array at all? */ if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM) SRF_RETURN_DONE(funcctx); /* Sanity check: was the requested dim valid */ if (reqdim <= 0 || reqdim > ARR_NDIM(v)) SRF_RETURN_DONE(funcctx); /* * switch to memory context appropriate for multiple function calls */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); fctx = (generate_subscripts_fctx *) palloc(sizeof(generate_subscripts_fctx)); lb = ARR_LBOUND(v); dimv = ARR_DIMS(v); fctx->lower = lb[reqdim - 1]; fctx->upper = dimv[reqdim - 1] + lb[reqdim - 1] - 1; fctx->reverse = (PG_NARGS() < 3) ? false : PG_GETARG_BOOL(2); funcctx->user_fctx = fctx; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); fctx = funcctx->user_fctx; if (fctx->lower <= fctx->upper) { if (!fctx->reverse) SRF_RETURN_NEXT(funcctx, Int32GetDatum(fctx->lower++)); else SRF_RETURN_NEXT(funcctx, Int32GetDatum(fctx->upper--)); } else /* done when there are no more elements left */ SRF_RETURN_DONE(funcctx); }
Datum generate_subscripts_nodir | ( | PG_FUNCTION_ARGS | ) |
Definition at line 4796 of file arrayfuncs.c.
References generate_subscripts().
{ /* just call the other one -- it can handle both cases */ return generate_subscripts(fcinfo); }
Datum hash_array | ( | PG_FUNCTION_ARGS | ) |
Definition at line 3535 of file arrayfuncs.c.
References FunctionCallInfoData::arg, FunctionCallInfoData::argnull, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, ARR_NULLBITMAP, ArrayGetNItems(), att_addlength_pointer, att_align_nominal, DatumGetUInt32, ereport, errcode(), errmsg(), ERROR, fetch_att, FmgrInfo::fn_oid, format_type_be(), FunctionCallInvoke, TypeCacheEntry::hash_proc_finfo, i, InitFunctionCallInfoData, InvalidOid, FunctionCallInfoData::isnull, lookup_type_cache(), NULL, OidIsValid, PG_FREE_IF_COPY, PG_GETARG_ARRAYTYPE_P, PG_RETURN_UINT32, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TYPECACHE_HASH_PROC_FINFO, and TypeCacheEntry::typlen.
{ ArrayType *array = PG_GETARG_ARRAYTYPE_P(0); int ndims = ARR_NDIM(array); int *dims = ARR_DIMS(array); Oid element_type = ARR_ELEMTYPE(array); uint32 result = 1; int nitems; TypeCacheEntry *typentry; int typlen; bool typbyval; char typalign; char *ptr; bits8 *bitmap; int bitmask; int i; FunctionCallInfoData locfcinfo; /* * We arrange to look up the hash function only once per series of calls, * assuming the element type doesn't change underneath us. The typcache * is used so that we have no memory leakage when being used as an index * support function. */ typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra; if (typentry == NULL || typentry->type_id != element_type) { typentry = lookup_type_cache(element_type, TYPECACHE_HASH_PROC_FINFO); if (!OidIsValid(typentry->hash_proc_finfo.fn_oid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify a hash function for type %s", format_type_be(element_type)))); fcinfo->flinfo->fn_extra = (void *) typentry; } typlen = typentry->typlen; typbyval = typentry->typbyval; typalign = typentry->typalign; /* * apply the hash function to each array element. */ InitFunctionCallInfoData(locfcinfo, &typentry->hash_proc_finfo, 1, InvalidOid, NULL, NULL); /* Loop over source data */ nitems = ArrayGetNItems(ndims, dims); ptr = ARR_DATA_PTR(array); bitmap = ARR_NULLBITMAP(array); bitmask = 1; for (i = 0; i < nitems; i++) { uint32 elthash; /* Get element, checking for NULL */ if (bitmap && (*bitmap & bitmask) == 0) { /* Treat nulls as having hashvalue 0 */ elthash = 0; } else { Datum elt; elt = fetch_att(ptr, typbyval, typlen); ptr = att_addlength_pointer(ptr, typlen, ptr); ptr = (char *) att_align_nominal(ptr, typalign); /* Apply the hash function */ locfcinfo.arg[0] = elt; locfcinfo.argnull[0] = false; locfcinfo.isnull = false; elthash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo)); } /* advance bitmap pointer if any */ if (bitmap) { bitmask <<= 1; if (bitmask == 0x100) { bitmap++; bitmask = 1; } } /* * Combine hash values of successive elements by multiplying the * current value by 31 and adding on the new element's hash value. * * The result is a sum in which each element's hash value is * multiplied by a different power of 31. This is modulo 2^32 * arithmetic, and the powers of 31 modulo 2^32 form a cyclic group of * order 2^27. So for arrays of up to 2^27 elements, each element's * hash value is multiplied by a different (odd) number, resulting in * a good mixing of all the elements' hash values. */ result = (result << 5) - result + elthash; } /* Avoid leaking memory when handed toasted input. */ PG_FREE_IF_COPY(array, 0); PG_RETURN_UINT32(result); }
Datum makeArrayResult | ( | ArrayBuildState * | astate, | |
MemoryContext | rcontext | |||
) |
Definition at line 4634 of file arrayfuncs.c.
References makeMdArrayResult(), and ArrayBuildState::nelems.
Referenced by dblink_get_connections(), ExecScanSubPlan(), ExecSetParamPlan(), optionListToArray(), regexp_split_to_array(), text_to_array_internal(), transformRelOptions(), and xpath().
{ int dims[1]; int lbs[1]; dims[0] = astate->nelems; lbs[0] = 1; return makeMdArrayResult(astate, 1, dims, lbs, rcontext, true); }
Datum makeMdArrayResult | ( | ArrayBuildState * | astate, | |
int | ndims, | |||
int * | dims, | |||
int * | lbs, | |||
MemoryContext | rcontext, | |||
bool | release | |||
) |
Definition at line 4657 of file arrayfuncs.c.
References construct_md_array(), ArrayBuildState::dnulls, ArrayBuildState::dvalues, ArrayBuildState::element_type, ArrayBuildState::mcontext, MemoryContextDelete(), MemoryContextSwitchTo(), PointerGetDatum, ArrayBuildState::typalign, ArrayBuildState::typbyval, and ArrayBuildState::typlen.
Referenced by array_agg_finalfn(), makeArrayResult(), and plperl_array_to_datum().
{ ArrayType *result; MemoryContext oldcontext; /* Build the final array result in rcontext */ oldcontext = MemoryContextSwitchTo(rcontext); result = construct_md_array(astate->dvalues, astate->dnulls, ndims, dims, lbs, astate->element_type, astate->typlen, astate->typbyval, astate->typalign); MemoryContextSwitchTo(oldcontext); /* Clean up all the junk */ if (release) MemoryContextDelete(astate->mcontext); return PointerGetDatum(result); }
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().
{ int i, j; dist[n - 1] = 0; for (j = n - 2; j >= 0; j--) { dist[j] = prod[j] - 1; for (i = j + 1; i < n; i++) dist[j] -= (span[i] - 1) * prod[i]; } }
void mda_get_prod | ( | int | n, | |
const int * | range, | |||
int * | prod | |||
) |
Definition at line 134 of file arrayutils.c.
References i.
Referenced by array_extract_slice(), array_insert_slice(), array_slice_size(), and ReadArrayStr().
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().
{ int i; for (i = 0; i < n; i++) span[i] = endp[i] - st[i] + 1; }
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().
{ int i; if (n <= 0) return -1; curr[n - 1] = (curr[n - 1] + 1) % span[n - 1]; for (i = n - 1; i && curr[i] == 0; i--) curr[i - 1] = (curr[i - 1] + 1) % span[i - 1]; if (i) return i; if (curr[0]) return 0; return -1; }
Definition at line 33 of file arrayfuncs.c.
Referenced by ReadArrayStr().