diff options
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 222 |
1 files changed, 1 insertions, 221 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 43acdffcaf0..38a86452e3f 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.137 2007/02/27 23:48:07 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.138 2007/03/27 23:21:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -95,10 +95,6 @@ static void array_insert_slice(ArrayType *destArray, ArrayType *origArray, int *st, int *endp, int typlen, bool typbyval, char typalign); static int array_cmp(FunctionCallInfo fcinfo); -static Datum array_type_length_coerce_internal(ArrayType *src, - int32 desttypmod, - bool isExplicit, - FmgrInfo *fmgr_info); /* @@ -4094,222 +4090,6 @@ array_insert_slice(ArrayType *destArray, } /* - * array_type_coerce -- allow explicit or assignment coercion from - * one array type to another. - * - * array_type_length_coerce -- the same, for cases where both type and length - * coercion are done by a single function on the element type. - * - * Caller should have already verified that the source element type can be - * coerced into the target element type. - */ -Datum -array_type_coerce(PG_FUNCTION_ARGS) -{ - ArrayType *src = PG_GETARG_ARRAYTYPE_P(0); - FmgrInfo *fmgr_info = fcinfo->flinfo; - - return array_type_length_coerce_internal(src, -1, false, fmgr_info); -} - -Datum -array_type_length_coerce(PG_FUNCTION_ARGS) -{ - ArrayType *src = PG_GETARG_ARRAYTYPE_P(0); - int32 desttypmod = PG_GETARG_INT32(1); - bool isExplicit = PG_GETARG_BOOL(2); - FmgrInfo *fmgr_info = fcinfo->flinfo; - - return array_type_length_coerce_internal(src, desttypmod, - isExplicit, fmgr_info); -} - -static Datum -array_type_length_coerce_internal(ArrayType *src, - int32 desttypmod, - bool isExplicit, - FmgrInfo *fmgr_info) -{ - Oid src_elem_type = ARR_ELEMTYPE(src); - typedef struct - { - Oid srctype; - Oid desttype; - FmgrInfo coerce_finfo; - ArrayMapState amstate; - } atc_extra; - atc_extra *my_extra; - FunctionCallInfoData locfcinfo; - - /* - * We arrange to look up the coercion function only once per series of - * calls, assuming the input data type doesn't change underneath us. - * (Output type can't change.) - */ - my_extra = (atc_extra *) fmgr_info->fn_extra; - if (my_extra == NULL) - { - fmgr_info->fn_extra = MemoryContextAllocZero(fmgr_info->fn_mcxt, - sizeof(atc_extra)); - my_extra = (atc_extra *) fmgr_info->fn_extra; - } - - if (my_extra->srctype != src_elem_type) - { - Oid tgt_type = get_fn_expr_rettype(fmgr_info); - Oid tgt_elem_type; - Oid funcId; - - if (tgt_type == InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not determine target array type"))); - - tgt_elem_type = get_element_type(tgt_type); - if (tgt_elem_type == InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("target type is not an array"))); - - /* - * We don't deal with domain constraints yet, so bail out. This isn't - * currently a problem, because we also don't support arrays of domain - * type elements either. But in the future we might. At that point - * consideration should be given to removing the check below and - * adding a domain constraints check to the coercion. - */ - if (getBaseType(tgt_elem_type) != tgt_elem_type) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("array coercion to domain type elements not " - "currently supported"))); - - if (!find_coercion_pathway(tgt_elem_type, src_elem_type, - COERCION_EXPLICIT, &funcId)) - { - /* should never happen, but check anyway */ - elog(ERROR, "no conversion function from %s to %s", - format_type_be(src_elem_type), - format_type_be(tgt_elem_type)); - } - if (OidIsValid(funcId)) - fmgr_info_cxt(funcId, &my_extra->coerce_finfo, fmgr_info->fn_mcxt); - else - my_extra->coerce_finfo.fn_oid = InvalidOid; - my_extra->srctype = src_elem_type; - my_extra->desttype = tgt_elem_type; - } - - /* - * If it's binary-compatible, modify the element type in the array header, - * but otherwise leave the array as we received it. - */ - if (my_extra->coerce_finfo.fn_oid == InvalidOid) - { - ArrayType *result; - - result = (ArrayType *) DatumGetPointer(datumCopy(PointerGetDatum(src), - false, -1)); - ARR_ELEMTYPE(result) = my_extra->desttype; - PG_RETURN_ARRAYTYPE_P(result); - } - - /* - * Use array_map to apply the function to each array element. - * - * We pass on the desttypmod and isExplicit flags whether or not the - * function wants them. - */ - InitFunctionCallInfoData(locfcinfo, &my_extra->coerce_finfo, 3, - NULL, NULL); - locfcinfo.arg[0] = PointerGetDatum(src); - locfcinfo.arg[1] = Int32GetDatum(desttypmod); - locfcinfo.arg[2] = BoolGetDatum(isExplicit); - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.argnull[2] = false; - - return array_map(&locfcinfo, my_extra->srctype, my_extra->desttype, - &my_extra->amstate); -} - -/* - * array_length_coerce -- apply the element type's length-coercion routine - * to each element of the given array. - */ -Datum -array_length_coerce(PG_FUNCTION_ARGS) -{ - ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); - int32 desttypmod = PG_GETARG_INT32(1); - bool isExplicit = PG_GETARG_BOOL(2); - FmgrInfo *fmgr_info = fcinfo->flinfo; - typedef struct - { - Oid elemtype; - FmgrInfo coerce_finfo; - ArrayMapState amstate; - } alc_extra; - alc_extra *my_extra; - FunctionCallInfoData locfcinfo; - - /* If no typmod is provided, shortcircuit the whole thing */ - if (desttypmod < 0) - PG_RETURN_ARRAYTYPE_P(v); - - /* - * We arrange to look up the element type's coercion function only once - * per series of calls, assuming the element type doesn't change - * underneath us. - */ - my_extra = (alc_extra *) fmgr_info->fn_extra; - if (my_extra == NULL) - { - fmgr_info->fn_extra = MemoryContextAllocZero(fmgr_info->fn_mcxt, - sizeof(alc_extra)); - my_extra = (alc_extra *) fmgr_info->fn_extra; - } - - if (my_extra->elemtype != ARR_ELEMTYPE(v)) - { - Oid funcId; - - funcId = find_typmod_coercion_function(ARR_ELEMTYPE(v)); - - if (OidIsValid(funcId)) - fmgr_info_cxt(funcId, &my_extra->coerce_finfo, fmgr_info->fn_mcxt); - else - my_extra->coerce_finfo.fn_oid = InvalidOid; - my_extra->elemtype = ARR_ELEMTYPE(v); - } - - /* - * If we didn't find a coercion function, return the array unmodified - * (this should not happen in the normal course of things, but might - * happen if this function is called manually). - */ - if (my_extra->coerce_finfo.fn_oid == InvalidOid) - PG_RETURN_ARRAYTYPE_P(v); - - /* - * Use array_map to apply the function to each array element. - * - * Note: we pass isExplicit whether or not the function wants it ... - */ - InitFunctionCallInfoData(locfcinfo, &my_extra->coerce_finfo, 3, - NULL, NULL); - locfcinfo.arg[0] = PointerGetDatum(v); - locfcinfo.arg[1] = Int32GetDatum(desttypmod); - locfcinfo.arg[2] = BoolGetDatum(isExplicit); - locfcinfo.argnull[0] = false; - locfcinfo.argnull[1] = false; - locfcinfo.argnull[2] = false; - - return array_map(&locfcinfo, ARR_ELEMTYPE(v), ARR_ELEMTYPE(v), - &my_extra->amstate); -} - -/* * accumArrayResult - accumulate one (more) Datum for an array result * * astate is working state (NULL on first call) |