aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/arrayfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r--src/backend/utils/adt/arrayfuncs.c85
1 files changed, 28 insertions, 57 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index d1f2fe7d958..ca04b13e825 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -3092,21 +3092,18 @@ array_set(ArrayType *array, int nSubscripts, int *indx,
/*
* array_map()
*
- * Map an array through an arbitrary function. Return a new array with
- * same dimensions and each source element transformed by fn(). Each
- * source element is passed as the first argument to fn(); additional
- * arguments to be passed to fn() can be specified by the caller.
- * The output array can have a different element type than the input.
+ * Map an array through an arbitrary expression. Return a new array with
+ * the same dimensions and each source element transformed by the given,
+ * already-compiled expression. Each source element is placed in the
+ * innermost_caseval/innermost_casenull fields of the ExprState.
*
* Parameters are:
- * * fcinfo: a function-call data structure pre-constructed by the caller
- * to be ready to call the desired function, with everything except the
- * first argument position filled in. In particular, flinfo identifies
- * the function fn(), and if nargs > 1 then argument positions after the
- * first must be preset to the additional values to be passed. The
- * first argument position initially holds the input array value.
+ * * arrayd: Datum representing array argument.
+ * * exprstate: ExprState representing the per-element transformation.
+ * * econtext: context for expression evaluation.
* * retType: OID of element type of output array. This must be the same as,
- * or binary-compatible with, the result type of fn().
+ * or binary-compatible with, the result type of the expression. It might
+ * be different from the input array's element type.
* * amstate: workspace for array_map. Must be zeroed by caller before
* first call, and not touched after that.
*
@@ -3116,11 +3113,14 @@ array_set(ArrayType *array, int nSubscripts, int *indx,
*
* NB: caller must assure that input array is not NULL. NULL elements in
* the array are OK however.
+ * NB: caller should be running in econtext's per-tuple memory context.
*/
Datum
-array_map(FunctionCallInfo fcinfo, Oid retType, ArrayMapState *amstate)
+array_map(Datum arrayd,
+ ExprState *exprstate, ExprContext *econtext,
+ Oid retType, ArrayMapState *amstate)
{
- AnyArrayType *v;
+ AnyArrayType *v = DatumGetAnyArrayP(arrayd);
ArrayType *result;
Datum *values;
bool *nulls;
@@ -3141,13 +3141,8 @@ array_map(FunctionCallInfo fcinfo, Oid retType, ArrayMapState *amstate)
array_iter iter;
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_ANY_ARRAY_P(0);
+ Datum *transform_source = exprstate->innermost_caseval;
+ bool *transform_source_isnull = exprstate->innermost_casenull;
inpType = AARR_ELEMTYPE(v);
ndim = AARR_NDIM(v);
@@ -3158,7 +3153,7 @@ array_map(FunctionCallInfo fcinfo, Oid retType, ArrayMapState *amstate)
if (nitems <= 0)
{
/* Return empty array */
- PG_RETURN_ARRAYTYPE_P(construct_empty_array(retType));
+ return PointerGetDatum(construct_empty_array(retType));
}
/*
@@ -3203,39 +3198,15 @@ array_map(FunctionCallInfo fcinfo, Oid retType, ArrayMapState *amstate)
for (i = 0; i < nitems; i++)
{
- bool callit = true;
-
/* Get source element, checking for NULL */
- fcinfo->arg[0] = array_iter_next(&iter, &fcinfo->argnull[0], i,
- inp_typlen, inp_typbyval, inp_typalign);
-
- /*
- * Apply the given function to source elt and extra args.
- */
- if (fcinfo->flinfo->fn_strict)
- {
- int j;
+ *transform_source =
+ array_iter_next(&iter, transform_source_isnull, i,
+ inp_typlen, inp_typbyval, inp_typalign);
- for (j = 0; j < fcinfo->nargs; j++)
- {
- if (fcinfo->argnull[j])
- {
- callit = false;
- break;
- }
- }
- }
+ /* Apply the given expression to source element */
+ values[i] = ExecEvalExpr(exprstate, econtext, &nulls[i]);
- if (callit)
- {
- fcinfo->isnull = false;
- values[i] = FunctionCallInvoke(fcinfo);
- }
- else
- fcinfo->isnull = true;
-
- nulls[i] = fcinfo->isnull;
- if (fcinfo->isnull)
+ if (nulls[i])
hasnulls = true;
else
{
@@ -3254,7 +3225,7 @@ array_map(FunctionCallInfo fcinfo, Oid retType, ArrayMapState *amstate)
}
}
- /* Allocate and initialize the result array */
+ /* Allocate and fill the result array */
if (hasnulls)
{
dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
@@ -3273,18 +3244,18 @@ array_map(FunctionCallInfo fcinfo, Oid retType, ArrayMapState *amstate)
memcpy(ARR_DIMS(result), AARR_DIMS(v), ndim * sizeof(int));
memcpy(ARR_LBOUND(result), AARR_LBOUND(v), 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);
+ /*
+ * Note: do not risk trying to pfree the results of the called expression
+ */
pfree(values);
pfree(nulls);
- PG_RETURN_ARRAYTYPE_P(result);
+ return PointerGetDatum(result);
}
/*