#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().
1.7.1