Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/README6
-rw-r--r--src/backend/executor/execExpr.c83
-rw-r--r--src/backend/executor/execExprInterp.c139
-rw-r--r--src/backend/executor/execSRF.c45
-rw-r--r--src/backend/executor/functions.c4
-rw-r--r--src/backend/executor/nodeAgg.c83
-rw-r--r--src/backend/executor/nodeWindowAgg.c64
7 files changed, 230 insertions, 194 deletions
diff --git a/src/backend/executor/README b/src/backend/executor/README
index ddbd62b4dba..05f197bc75b 100644
--- a/src/backend/executor/README
+++ b/src/backend/executor/README
@@ -124,7 +124,7 @@ For example, "a + b" (one OpExpr, with two Var expressions) would be
represented as two steps to fetch the Var values, and one step for the
evaluation of the function underlying the + operator. The steps for the
Vars would have their resvalue/resnull pointing directly to the appropriate
-arg[] and argnull[] array elements in the FunctionCallInfoData struct that
+args[].value .isnull elements in the FunctionCallInfoBaseData struct that
is used by the function evaluation step, thus avoiding extra work to copy
the result values around.
@@ -145,7 +145,7 @@ sub-expressions.
Each ExecInitExprRec() call has to specify where that subexpression's
results are to be stored (via the resv/resnull parameters). This allows
the above scenario of evaluating a (sub-)expression directly into
-fcinfo->arg/argnull, but also requires some care: target Datum/isnull
+fcinfo->args[].value/isnull, but also requires some care: target Datum/isnull
variables may not be shared with another ExecInitExprRec() unless the
results are only needed by steps executing before further usages of those
target Datum/isnull variables. Due to the non-recursiveness of the
@@ -158,7 +158,7 @@ not enough space. Because of that it is *not* allowed to point directly
into any of the steps during expression initialization. Therefore, the
resv/resnull for a subexpression usually point to some storage that is
palloc'd separately from the steps array. For instance, the
-FunctionCallInfoData for a function call step is separately allocated
+FunctionCallInfoBaseData for a function call step is separately allocated
rather than being part of the ExprEvalStep array. The overall result
of a complete expression is typically returned into the resvalue/resnull
fields of the ExprState node itself.
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 4047d24b03e..2e061a5ee36 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -966,7 +966,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
/* Set up the primary fmgr lookup information */
finfo = palloc0(sizeof(FmgrInfo));
- fcinfo = palloc0(sizeof(FunctionCallInfoData));
+ fcinfo = palloc0(SizeForFunctionCallInfo(2));
fmgr_info(opexpr->opfuncid, finfo);
fmgr_info_set_expr((Node *) node, finfo);
InitFunctionCallInfoData(*fcinfo, finfo, 2,
@@ -974,7 +974,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
/* Evaluate scalar directly into left function argument */
ExecInitExprRec(scalararg, state,
- &fcinfo->arg[0], &fcinfo->argnull[0]);
+ &fcinfo->args[0].value, &fcinfo->args[0].isnull);
/*
* Evaluate array argument into our return value. There's no
@@ -1263,7 +1263,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
/* lookup the source type's output function */
scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
- scratch.d.iocoerce.fcinfo_data_out = palloc0(sizeof(FunctionCallInfoData));
+ scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfo(1));
getTypeOutputInfo(exprType((Node *) iocoerce->arg),
&iofunc, &typisvarlena);
@@ -1275,7 +1275,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
/* lookup the result type's input function */
scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
- scratch.d.iocoerce.fcinfo_data_in = palloc0(sizeof(FunctionCallInfoData));
+ scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3));
getTypeInputInfo(iocoerce->resulttype,
&iofunc, &typioparam);
@@ -1290,10 +1290,10 @@ ExecInitExprRec(Expr *node, ExprState *state,
* function, since they're constants.
*/
fcinfo_in = scratch.d.iocoerce.fcinfo_data_in;
- fcinfo_in->arg[1] = ObjectIdGetDatum(typioparam);
- fcinfo_in->argnull[1] = false;
- fcinfo_in->arg[2] = Int32GetDatum(-1);
- fcinfo_in->argnull[2] = false;
+ fcinfo_in->args[1].value = ObjectIdGetDatum(typioparam);
+ fcinfo_in->args[1].isnull = false;
+ fcinfo_in->args[2].value = Int32GetDatum(-1);
+ fcinfo_in->args[2].isnull = false;
ExprEvalPushStep(state, &scratch);
break;
@@ -1735,7 +1735,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
/* Set up the primary fmgr lookup information */
finfo = palloc0(sizeof(FmgrInfo));
- fcinfo = palloc0(sizeof(FunctionCallInfoData));
+ fcinfo = palloc0(SizeForFunctionCallInfo(2));
fmgr_info(proc, finfo);
fmgr_info_set_expr((Node *) node, finfo);
InitFunctionCallInfoData(*fcinfo, finfo, 2,
@@ -1750,9 +1750,9 @@ ExecInitExprRec(Expr *node, ExprState *state,
/* evaluate left and right args directly into fcinfo */
ExecInitExprRec(left_expr, state,
- &fcinfo->arg[0], &fcinfo->argnull[0]);
+ &fcinfo->args[0].value, &fcinfo->args[0].isnull);
ExecInitExprRec(right_expr, state,
- &fcinfo->arg[1], &fcinfo->argnull[1]);
+ &fcinfo->args[1].value, &fcinfo->args[1].isnull);
scratch.opcode = EEOP_ROWCOMPARE_STEP;
scratch.d.rowcompare_step.finfo = finfo;
@@ -1878,7 +1878,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
/* Perform function lookup */
finfo = palloc0(sizeof(FmgrInfo));
- fcinfo = palloc0(sizeof(FunctionCallInfoData));
+ fcinfo = palloc0(SizeForFunctionCallInfo(2));
fmgr_info(typentry->cmp_proc, finfo);
fmgr_info_set_expr((Node *) node, finfo);
InitFunctionCallInfoData(*fcinfo, finfo, 2,
@@ -2187,7 +2187,7 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
/* Allocate function lookup data and parameter workspace for this call */
scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
- scratch->d.func.fcinfo_data = palloc0(sizeof(FunctionCallInfoData));
+ scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfo(nargs));
flinfo = scratch->d.func.finfo;
fcinfo = scratch->d.func.fcinfo_data;
@@ -2226,13 +2226,14 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
*/
Const *con = (Const *) arg;
- fcinfo->arg[argno] = con->constvalue;
- fcinfo->argnull[argno] = con->constisnull;
+ fcinfo->args[argno].value = con->constvalue;
+ fcinfo->args[argno].isnull = con->constisnull;
}
else
{
ExecInitExprRec(arg, state,
- &fcinfo->arg[argno], &fcinfo->argnull[argno]);
+ &fcinfo->args[argno].value,
+ &fcinfo->args[argno].isnull);
}
argno++;
}
@@ -2961,10 +2962,11 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
AggStatePerTrans pertrans = &aggstate->pertrans[transno];
int argno;
int setno;
- FunctionCallInfo trans_fcinfo = &pertrans->transfn_fcinfo;
+ FunctionCallInfo trans_fcinfo = pertrans->transfn_fcinfo;
ListCell *arg;
ListCell *bail;
List *adjust_bailout = NIL;
+ NullableDatum *strictargs = NULL;
bool *strictnulls = NULL;
/*
@@ -3002,7 +3004,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
Assert(pertrans->numSortCols == 0);
Assert(list_length(pertrans->aggref->args) == 1);
- strictnulls = trans_fcinfo->argnull + 1;
+ strictargs = trans_fcinfo->args + 1;
source_tle = (TargetEntry *) linitial(pertrans->aggref->args);
/*
@@ -3016,21 +3018,21 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
* value
*/
ExecInitExprRec(source_tle->expr, state,
- &trans_fcinfo->arg[argno + 1],
- &trans_fcinfo->argnull[argno + 1]);
+ &trans_fcinfo->args[argno + 1].value,
+ &trans_fcinfo->args[argno + 1].isnull);
}
else
{
- FunctionCallInfo ds_fcinfo = &pertrans->deserialfn_fcinfo;
+ FunctionCallInfo ds_fcinfo = pertrans->deserialfn_fcinfo;
/* evaluate argument */
ExecInitExprRec(source_tle->expr, state,
- &ds_fcinfo->arg[0],
- &ds_fcinfo->argnull[0]);
+ &ds_fcinfo->args[0].value,
+ &ds_fcinfo->args[0].isnull);
/* Dummy second argument for type-safety reasons */
- ds_fcinfo->arg[1] = PointerGetDatum(NULL);
- ds_fcinfo->argnull[1] = false;
+ ds_fcinfo->args[1].value = PointerGetDatum(NULL);
+ ds_fcinfo->args[1].isnull = false;
/*
* Don't call a strict deserialization function with NULL
@@ -3044,8 +3046,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
scratch.d.agg_deserialize.aggstate = aggstate;
scratch.d.agg_deserialize.fcinfo_data = ds_fcinfo;
scratch.d.agg_deserialize.jumpnull = -1; /* adjust later */
- scratch.resvalue = &trans_fcinfo->arg[argno + 1];
- scratch.resnull = &trans_fcinfo->argnull[argno + 1];
+ scratch.resvalue = &trans_fcinfo->args[argno + 1].value;
+ scratch.resnull = &trans_fcinfo->args[argno + 1].isnull;
ExprEvalPushStep(state, &scratch);
adjust_bailout = lappend_int(adjust_bailout,
@@ -3062,7 +3064,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
/*
* Normal transition function without ORDER BY / DISTINCT.
*/
- strictnulls = trans_fcinfo->argnull + 1;
+ strictargs = trans_fcinfo->args + 1;
foreach(arg, pertrans->aggref->args)
{
@@ -3073,8 +3075,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
* value
*/
ExecInitExprRec(source_tle->expr, state,
- &trans_fcinfo->arg[argno + 1],
- &trans_fcinfo->argnull[argno + 1]);
+ &trans_fcinfo->args[argno + 1].value,
+ &trans_fcinfo->args[argno + 1].isnull);
argno++;
}
}
@@ -3122,8 +3124,12 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
*/
if (trans_fcinfo->flinfo->fn_strict && pertrans->numTransInputs > 0)
{
- scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK;
+ if (strictnulls)
+ scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_NULLS;
+ else
+ scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_ARGS;
scratch.d.agg_strict_input_check.nulls = strictnulls;
+ scratch.d.agg_strict_input_check.args = strictargs;
scratch.d.agg_strict_input_check.jumpnull = -1; /* adjust later */
scratch.d.agg_strict_input_check.nargs = pertrans->numTransInputs;
ExprEvalPushStep(state, &scratch);
@@ -3177,7 +3183,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
Assert(as->d.jump.jumpdone == -1);
as->d.jump.jumpdone = state->steps_len;
}
- else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK)
+ else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS ||
+ as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
{
Assert(as->d.agg_strict_input_check.jumpnull == -1);
as->d.agg_strict_input_check.jumpnull = state->steps_len;
@@ -3312,7 +3319,7 @@ ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
*/
ExprState *
ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
- const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
+ const TupleTableSlotOps * lops, const TupleTableSlotOps * rops,
int numCols,
const AttrNumber *keyColIdx,
const Oid *eqfunctions,
@@ -3389,7 +3396,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
/* Set up the primary fmgr lookup information */
finfo = palloc0(sizeof(FmgrInfo));
- fcinfo = palloc0(sizeof(FunctionCallInfoData));
+ fcinfo = palloc0(SizeForFunctionCallInfo(2));
fmgr_info(foid, finfo);
fmgr_info_set_expr(NULL, finfo);
InitFunctionCallInfoData(*fcinfo, finfo, 2,
@@ -3399,16 +3406,16 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
scratch.opcode = EEOP_INNER_VAR;
scratch.d.var.attnum = attno - 1;
scratch.d.var.vartype = latt->atttypid;
- scratch.resvalue = &fcinfo->arg[0];
- scratch.resnull = &fcinfo->argnull[0];
+ scratch.resvalue = &fcinfo->args[0].value;
+ scratch.resnull = &fcinfo->args[0].isnull;
ExprEvalPushStep(state, &scratch);
/* right arg */
scratch.opcode = EEOP_OUTER_VAR;
scratch.d.var.attnum = attno - 1;
scratch.d.var.vartype = ratt->atttypid;
- scratch.resvalue = &fcinfo->arg[1];
- scratch.resnull = &fcinfo->argnull[1];
+ scratch.resvalue = &fcinfo->args[1].value;
+ scratch.resnull = &fcinfo->args[1].isnull;
ExprEvalPushStep(state, &scratch);
/* evaluate distinctness */
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 5a7206f5882..5c5f655645d 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -387,7 +387,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
&&CASE_EEOP_ALTERNATIVE_SUBPLAN,
&&CASE_EEOP_AGG_STRICT_DESERIALIZE,
&&CASE_EEOP_AGG_DESERIALIZE,
- &&CASE_EEOP_AGG_STRICT_INPUT_CHECK,
+ &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
+ &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
&&CASE_EEOP_AGG_INIT_TRANS,
&&CASE_EEOP_AGG_STRICT_TRANS_CHECK,
&&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL,
@@ -631,14 +632,14 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_CASE(EEOP_FUNCEXPR_STRICT)
{
FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
- bool *argnull = fcinfo->argnull;
+ NullableDatum *args = fcinfo->args;
int argno;
Datum d;
/* strict function, so check for NULL args */
for (argno = 0; argno < op->d.func.nargs; argno++)
{
- if (argnull[argno])
+ if (args[argno].isnull)
{
*op->resnull = true;
goto strictfail;
@@ -1054,8 +1055,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
FunctionCallInfo fcinfo_out;
fcinfo_out = op->d.iocoerce.fcinfo_data_out;
- fcinfo_out->arg[0] = *op->resvalue;
- fcinfo_out->argnull[0] = false;
+ fcinfo_out->args[0].value = *op->resvalue;
+ fcinfo_out->args[0].isnull = false;
fcinfo_out->isnull = false;
str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
@@ -1071,8 +1072,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
Datum d;
fcinfo_in = op->d.iocoerce.fcinfo_data_in;
- fcinfo_in->arg[0] = PointerGetDatum(str);
- fcinfo_in->argnull[0] = *op->resnull;
+ fcinfo_in->args[0].value = PointerGetDatum(str);
+ fcinfo_in->args[0].isnull = *op->resnull;
/* second and third arguments are already set up */
fcinfo_in->isnull = false;
@@ -1099,23 +1100,23 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
{
/*
* IS DISTINCT FROM must evaluate arguments (already done into
- * fcinfo->arg/argnull) to determine whether they are NULL; if
- * either is NULL then the result is determined. If neither is
- * NULL, then proceed to evaluate the comparison function, which
- * is just the type's standard equality operator. We need not
- * care whether that function is strict. Because the handling of
- * nulls is different, we can't just reuse EEOP_FUNCEXPR.
+ * fcinfo->args) to determine whether they are NULL; if either is
+ * NULL then the result is determined. If neither is NULL, then
+ * proceed to evaluate the comparison function, which is just the
+ * type's standard equality operator. We need not care whether
+ * that function is strict. Because the handling of nulls is
+ * different, we can't just reuse EEOP_FUNCEXPR.
*/
FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
/* check function arguments for NULLness */
- if (fcinfo->argnull[0] && fcinfo->argnull[1])
+ if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
{
/* Both NULL? Then is not distinct... */
*op->resvalue = BoolGetDatum(false);
*op->resnull = false;
}
- else if (fcinfo->argnull[0] || fcinfo->argnull[1])
+ else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
{
/* Only one is NULL? Then is distinct... */
*op->resvalue = BoolGetDatum(true);
@@ -1141,12 +1142,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
{
FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
- if (fcinfo->argnull[0] && fcinfo->argnull[1])
+ if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
{
*op->resvalue = BoolGetDatum(true);
*op->resnull = false;
}
- else if (fcinfo->argnull[0] || fcinfo->argnull[1])
+ else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
{
*op->resvalue = BoolGetDatum(false);
*op->resnull = false;
@@ -1167,12 +1168,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_CASE(EEOP_NULLIF)
{
/*
- * The arguments are already evaluated into fcinfo->arg/argnull.
+ * The arguments are already evaluated into fcinfo->args.
*/
FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
/* if either argument is NULL they can't be equal */
- if (!fcinfo->argnull[0] && !fcinfo->argnull[1])
+ if (!fcinfo->args[0].isnull && !fcinfo->args[1].isnull)
{
Datum result;
@@ -1190,8 +1191,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
}
/* Arguments aren't equal, so return the first one */
- *op->resvalue = fcinfo->arg[0];
- *op->resnull = fcinfo->argnull[0];
+ *op->resvalue = fcinfo->args[0].value;
+ *op->resnull = fcinfo->args[0].isnull;
EEO_NEXT();
}
@@ -1257,7 +1258,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
/* force NULL result if strict fn and NULL input */
if (op->d.rowcompare_step.finfo->fn_strict &&
- (fcinfo->argnull[0] || fcinfo->argnull[1]))
+ (fcinfo->args[0].isnull || fcinfo->args[1].isnull))
{
*op->resnull = true;
EEO_JUMP(op->d.rowcompare_step.jumpnull);
@@ -1496,10 +1497,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
/* evaluate a strict aggregate deserialization function */
EEO_CASE(EEOP_AGG_STRICT_DESERIALIZE)
{
- bool *argnull = op->d.agg_deserialize.fcinfo_data->argnull;
-
/* Don't call a strict deserialization function with NULL input */
- if (argnull[0])
+ if (op->d.agg_deserialize.fcinfo_data->args[0].isnull)
EEO_JUMP(op->d.agg_deserialize.jumpnull);
/* fallthrough */
@@ -1529,7 +1528,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
* Check that a strict aggregate transition / combination function's
* input is not NULL.
*/
- EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK)
+ EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
{
int argno;
bool *nulls = op->d.agg_strict_input_check.nulls;
@@ -1543,6 +1542,20 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_NEXT();
}
+ EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS)
+ {
+ int argno;
+ NullableDatum *args = op->d.agg_strict_input_check.args;
+ int nargs = op->d.agg_strict_input_check.nargs;
+
+ for (argno = 0; argno < nargs; argno++)
+ {
+ if (args[argno].isnull)
+ EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
+ }
+ EEO_NEXT();
+ }
+
/*
* Initialize an aggregate's first value if necessary.
*/
@@ -1613,7 +1626,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
Assert(pertrans->transtypeByVal);
- fcinfo = &pertrans->transfn_fcinfo;
+ fcinfo = pertrans->transfn_fcinfo;
/* cf. select_current_set() */
aggstate->curaggcontext = op->d.agg_trans.aggcontext;
@@ -1625,8 +1638,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
/* invoke transition function in per-tuple context */
oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
- fcinfo->arg[0] = pergroup->transValue;
- fcinfo->argnull[0] = pergroup->transValueIsNull;
+ fcinfo->args[0].value = pergroup->transValue;
+ fcinfo->args[0].isnull = pergroup->transValueIsNull;
fcinfo->isnull = false; /* just in case transfn doesn't set it */
newVal = FunctionCallInvoke(fcinfo);
@@ -1664,7 +1677,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
Assert(!pertrans->transtypeByVal);
- fcinfo = &pertrans->transfn_fcinfo;
+ fcinfo = pertrans->transfn_fcinfo;
/* cf. select_current_set() */
aggstate->curaggcontext = op->d.agg_trans.aggcontext;
@@ -1676,8 +1689,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
/* invoke transition function in per-tuple context */
oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
- fcinfo->arg[0] = pergroup->transValue;
- fcinfo->argnull[0] = pergroup->transValueIsNull;
+ fcinfo->args[0].value = pergroup->transValue;
+ fcinfo->args[0].isnull = pergroup->transValueIsNull;
fcinfo->isnull = false; /* just in case transfn doesn't set it */
newVal = FunctionCallInvoke(fcinfo);
@@ -2075,7 +2088,7 @@ ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
{
ExprEvalStep *op = &state->steps[0];
FunctionCallInfo fcinfo;
- bool *argnull;
+ NullableDatum *args;
int argno;
Datum d;
@@ -2089,12 +2102,12 @@ ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
op++;
fcinfo = op->d.func.fcinfo_data;
- argnull = fcinfo->argnull;
+ args = fcinfo->args;
/* strict function, so check for NULL args */
for (argno = 0; argno < op->d.func.nargs; argno++)
{
- if (argnull[argno])
+ if (args[argno].isnull)
{
*isnull = true;
return (Datum) 0;
@@ -2220,14 +2233,14 @@ ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op,
FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
PgStat_FunctionCallUsage fcusage;
- bool *argnull = fcinfo->argnull;
+ NullableDatum *args = fcinfo->args;
int argno;
Datum d;
/* strict function, so check for NULL args */
for (argno = 0; argno < op->d.func.nargs; argno++)
{
- if (argnull[argno])
+ if (args[argno].isnull)
{
*op->resnull = true;
return;
@@ -2317,8 +2330,8 @@ ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
void
ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
{
+ LOCAL_FCINFO(fcinfo, 0);
SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
- FunctionCallInfoData fcinfo;
*op->resnull = false;
@@ -2350,24 +2363,24 @@ ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
case SVFOP_CURRENT_ROLE:
case SVFOP_CURRENT_USER:
case SVFOP_USER:
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
- *op->resvalue = current_user(&fcinfo);
- *op->resnull = fcinfo.isnull;
+ InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = current_user(fcinfo);
+ *op->resnull = fcinfo->isnull;
break;
case SVFOP_SESSION_USER:
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
- *op->resvalue = session_user(&fcinfo);
- *op->resnull = fcinfo.isnull;
+ InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = session_user(fcinfo);
+ *op->resnull = fcinfo->isnull;
break;
case SVFOP_CURRENT_CATALOG:
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
- *op->resvalue = current_database(&fcinfo);
- *op->resnull = fcinfo.isnull;
+ InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = current_database(fcinfo);
+ *op->resnull = fcinfo->isnull;
break;
case SVFOP_CURRENT_SCHEMA:
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
- *op->resvalue = current_schema(&fcinfo);
- *op->resnull = fcinfo.isnull;
+ InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ *op->resvalue = current_schema(fcinfo);
+ *op->resnull = fcinfo->isnull;
break;
}
}
@@ -2800,8 +2813,8 @@ ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
int off;
/* set at initialization */
- Assert(fcinfo->argnull[0] == false);
- Assert(fcinfo->argnull[1] == false);
+ Assert(fcinfo->args[0].isnull == false);
+ Assert(fcinfo->args[1].isnull == false);
/* default to null result */
*op->resnull = true;
@@ -2823,8 +2836,8 @@ ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
int cmpresult;
/* apply comparison function */
- fcinfo->arg[0] = *op->resvalue;
- fcinfo->arg[1] = values[off];
+ fcinfo->args[0].value = *op->resvalue;
+ fcinfo->args[1].value = values[off];
fcinfo->isnull = false;
cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
@@ -3324,7 +3337,7 @@ ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext
* Evaluate "scalar op ANY/ALL (array)".
*
* Source array is in our result area, scalar arg is already evaluated into
- * fcinfo->arg[0]/argnull[0].
+ * fcinfo->args[0].
*
* The operator always yields boolean, and we combine the results across all
* array elements using OR and AND (for ANY and ALL respectively). Of course
@@ -3376,7 +3389,7 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
* If the scalar is NULL, and the function is strict, return NULL; no
* point in iterating the loop.
*/
- if (fcinfo->argnull[0] && strictfunc)
+ if (fcinfo->args[0].isnull && strictfunc)
{
*op->resnull = true;
return;
@@ -3416,20 +3429,20 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
/* Get array element, checking for NULL */
if (bitmap && (*bitmap & bitmask) == 0)
{
- fcinfo->arg[1] = (Datum) 0;
- fcinfo->argnull[1] = true;
+ fcinfo->args[1].value = (Datum) 0;
+ fcinfo->args[1].isnull = true;
}
else
{
elt = fetch_att(s, typbyval, typlen);
s = att_addlength_pointer(s, typlen, s);
s = (char *) att_align_nominal(s, typalign);
- fcinfo->arg[1] = elt;
- fcinfo->argnull[1] = false;
+ fcinfo->args[1].value = elt;
+ fcinfo->args[1].isnull = false;
}
/* Call comparison function */
- if (fcinfo->argnull[1] && strictfunc)
+ if (fcinfo->args[1].isnull && strictfunc)
{
fcinfo->isnull = true;
thisresult = (Datum) 0;
@@ -4044,7 +4057,7 @@ ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
void
ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup)
{
- FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+ FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
MemoryContext oldContext;
/*
@@ -4055,7 +4068,7 @@ ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup
*/
oldContext = MemoryContextSwitchTo(
aggstate->curaggcontext->ecxt_per_tuple_memory);
- pergroup->transValue = datumCopy(fcinfo->arg[1],
+ pergroup->transValue = datumCopy(fcinfo->args[1].value,
pertrans->transtypeByVal,
pertrans->transtypeLen);
pergroup->transValueIsNull = false;
diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c
index 0c086c52904..265250186a1 100644
--- a/src/backend/executor/execSRF.c
+++ b/src/backend/executor/execSRF.c
@@ -109,7 +109,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
Oid funcrettype;
bool returnsTuple;
bool returnsSet = false;
- FunctionCallInfoData fcinfo;
+ FunctionCallInfo fcinfo;
PgStat_FunctionCallUsage fcusage;
ReturnSetInfo rsinfo;
HeapTupleData tmptup;
@@ -141,6 +141,8 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
rsinfo.setResult = NULL;
rsinfo.setDesc = NULL;
+ fcinfo = palloc(SizeForFunctionCallInfo(list_length(setexpr->args)));
+
/*
* Normally the passed expression tree will be a SetExprState, since the
* grammar only allows a function call at the top level of a table
@@ -157,9 +159,9 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
* This path is similar to ExecMakeFunctionResultSet.
*/
returnsSet = setexpr->funcReturnsSet;
- InitFunctionCallInfoData(fcinfo, &(setexpr->func),
+ InitFunctionCallInfoData(*fcinfo, &(setexpr->func),
list_length(setexpr->args),
- setexpr->fcinfo_data.fncollation,
+ setexpr->fcinfo->fncollation,
NULL, (Node *) &rsinfo);
/*
@@ -174,7 +176,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
*/
MemoryContextReset(argContext);
oldcontext = MemoryContextSwitchTo(argContext);
- ExecEvalFuncArgs(&fcinfo, setexpr->args, econtext);
+ ExecEvalFuncArgs(fcinfo, setexpr->args, econtext);
MemoryContextSwitchTo(oldcontext);
/*
@@ -186,9 +188,9 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
{
int i;
- for (i = 0; i < fcinfo.nargs; i++)
+ for (i = 0; i < fcinfo->nargs; i++)
{
- if (fcinfo.argnull[i])
+ if (fcinfo->args[i].isnull)
goto no_function_result;
}
}
@@ -196,7 +198,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
else
{
/* Treat setexpr as a generic expression */
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
}
/*
@@ -224,11 +226,11 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
/* Call the function or expression one time */
if (!setexpr->elidedFuncState)
{
- pgstat_init_function_usage(&fcinfo, &fcusage);
+ pgstat_init_function_usage(fcinfo, &fcusage);
- fcinfo.isnull = false;
+ fcinfo->isnull = false;
rsinfo.isDone = ExprSingleResult;
- result = FunctionCallInvoke(&fcinfo);
+ result = FunctionCallInvoke(fcinfo);
pgstat_end_function_usage(&fcusage,
rsinfo.isDone != ExprMultipleResult);
@@ -236,7 +238,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
else
{
result =
- ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo.isnull);
+ ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo->isnull);
rsinfo.isDone = ExprSingleResult;
}
@@ -277,7 +279,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
*/
if (returnsTuple)
{
- if (!fcinfo.isnull)
+ if (!fcinfo->isnull)
{
HeapTupleHeader td = DatumGetHeapTupleHeader(result);
@@ -338,7 +340,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
else
{
/* Scalar-type case: just store the function result */
- tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull);
+ tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo->isnull);
}
/*
@@ -547,7 +549,7 @@ restart:
* rows from this SRF have been returned, otherwise ValuePerCall SRFs
* would reference freed memory after the first returned row.
*/
- fcinfo = &fcache->fcinfo_data;
+ fcinfo = fcache->fcinfo;
arguments = fcache->args;
if (!fcache->setArgsValid)
{
@@ -587,7 +589,7 @@ restart:
{
for (i = 0; i < fcinfo->nargs; i++)
{
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
{
callit = false;
break;
@@ -678,6 +680,7 @@ init_sexpr(Oid foid, Oid input_collation, Expr *node,
MemoryContext sexprCxt, bool allowSRF, bool needDescForSRF)
{
AclResult aclresult;
+ size_t numargs = list_length(sexpr->args);
/* Check permission to call function */
aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
@@ -704,8 +707,10 @@ init_sexpr(Oid foid, Oid input_collation, Expr *node,
fmgr_info_set_expr((Node *) sexpr->expr, &(sexpr->func));
/* Initialize the function call parameter struct as well */
- InitFunctionCallInfoData(sexpr->fcinfo_data, &(sexpr->func),
- list_length(sexpr->args),
+ sexpr->fcinfo =
+ (FunctionCallInfo) palloc(SizeForFunctionCallInfo(numargs));
+ InitFunctionCallInfoData(*sexpr->fcinfo, &(sexpr->func),
+ numargs,
input_collation, NULL, NULL);
/* If function returns set, check if that's allowed by caller */
@@ -820,9 +825,9 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo,
{
ExprState *argstate = (ExprState *) lfirst(arg);
- fcinfo->arg[i] = ExecEvalExpr(argstate,
- econtext,
- &fcinfo->argnull[i]);
+ fcinfo->args[i].value = ExecEvalExpr(argstate,
+ econtext,
+ &fcinfo->args[i].isnull);
i++;
}
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index de41588105e..c6b7203f813 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -933,8 +933,8 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
{
ParamExternData *prm = &paramLI->params[i];
- prm->value = fcinfo->arg[i];
- prm->isnull = fcinfo->argnull[i];
+ prm->value = fcinfo->args[i].value;
+ prm->isnull = fcinfo->args[i].isnull;
prm->pflags = 0;
prm->ptype = fcache->pinfo->argtypes[i];
}
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 508c9195743..2a260a71f24 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -553,7 +553,7 @@ advance_transition_function(AggState *aggstate,
AggStatePerTrans pertrans,
AggStatePerGroup pergroupstate)
{
- FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+ FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
MemoryContext oldContext;
Datum newVal;
@@ -568,7 +568,7 @@ advance_transition_function(AggState *aggstate,
for (i = 1; i <= numTransInputs; i++)
{
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
return;
}
if (pergroupstate->noTransValue)
@@ -584,7 +584,7 @@ advance_transition_function(AggState *aggstate,
*/
oldContext = MemoryContextSwitchTo(
aggstate->curaggcontext->ecxt_per_tuple_memory);
- pergroupstate->transValue = datumCopy(fcinfo->arg[1],
+ pergroupstate->transValue = datumCopy(fcinfo->args[1].value,
pertrans->transtypeByVal,
pertrans->transtypeLen);
pergroupstate->transValueIsNull = false;
@@ -613,8 +613,8 @@ advance_transition_function(AggState *aggstate,
/*
* OK to call the transition function
*/
- fcinfo->arg[0] = pergroupstate->transValue;
- fcinfo->argnull[0] = pergroupstate->transValueIsNull;
+ fcinfo->args[0].value = pergroupstate->transValue;
+ fcinfo->args[0].isnull = pergroupstate->transValueIsNull;
fcinfo->isnull = false; /* just in case transfn doesn't set it */
newVal = FunctionCallInvoke(fcinfo);
@@ -717,7 +717,7 @@ process_ordered_aggregate_single(AggState *aggstate,
bool isDistinct = (pertrans->numDistinctCols > 0);
Datum newAbbrevVal = (Datum) 0;
Datum oldAbbrevVal = (Datum) 0;
- FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+ FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
Datum *newVal;
bool *isNull;
@@ -726,8 +726,8 @@ process_ordered_aggregate_single(AggState *aggstate,
tuplesort_performsort(pertrans->sortstates[aggstate->current_set]);
/* Load the column into argument 1 (arg 0 will be transition value) */
- newVal = fcinfo->arg + 1;
- isNull = fcinfo->argnull + 1;
+ newVal = &fcinfo->args[1].value;
+ isNull = &fcinfo->args[1].isnull;
/*
* Note: if input type is pass-by-ref, the datums returned by the sort are
@@ -803,7 +803,7 @@ process_ordered_aggregate_multi(AggState *aggstate,
AggStatePerGroup pergroupstate)
{
ExprContext *tmpcontext = aggstate->tmpcontext;
- FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+ FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
TupleTableSlot *slot1 = pertrans->sortslot;
TupleTableSlot *slot2 = pertrans->uniqslot;
int numTransInputs = pertrans->numTransInputs;
@@ -843,8 +843,8 @@ process_ordered_aggregate_multi(AggState *aggstate,
/* Start from 1, since the 0th arg will be the transition value */
for (i = 0; i < numTransInputs; i++)
{
- fcinfo->arg[i + 1] = slot1->tts_values[i];
- fcinfo->argnull[i + 1] = slot1->tts_isnull[i];
+ fcinfo->args[i + 1].value = slot1->tts_values[i];
+ fcinfo->args[i + 1].isnull = slot1->tts_isnull[i];
}
advance_transition_function(aggstate, pertrans, pergroupstate);
@@ -897,7 +897,7 @@ finalize_aggregate(AggState *aggstate,
AggStatePerGroup pergroupstate,
Datum *resultVal, bool *resultIsNull)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
bool anynull = false;
MemoryContext oldContext;
int i;
@@ -917,10 +917,10 @@ finalize_aggregate(AggState *aggstate,
{
ExprState *expr = (ExprState *) lfirst(lc);
- fcinfo.arg[i] = ExecEvalExpr(expr,
- aggstate->ss.ps.ps_ExprContext,
- &fcinfo.argnull[i]);
- anynull |= fcinfo.argnull[i];
+ fcinfo->args[i].value = ExecEvalExpr(expr,
+ aggstate->ss.ps.ps_ExprContext,
+ &fcinfo->args[i].isnull);
+ anynull |= fcinfo->args[i].isnull;
i++;
}
@@ -934,27 +934,28 @@ finalize_aggregate(AggState *aggstate,
/* set up aggstate->curperagg for AggGetAggref() */
aggstate->curperagg = peragg;
- InitFunctionCallInfoData(fcinfo, &peragg->finalfn,
+ InitFunctionCallInfoData(*fcinfo, &peragg->finalfn,
numFinalArgs,
pertrans->aggCollation,
(void *) aggstate, NULL);
/* Fill in the transition state value */
- fcinfo.arg[0] = MakeExpandedObjectReadOnly(pergroupstate->transValue,
- pergroupstate->transValueIsNull,
- pertrans->transtypeLen);
- fcinfo.argnull[0] = pergroupstate->transValueIsNull;
+ fcinfo->args[0].value =
+ MakeExpandedObjectReadOnly(pergroupstate->transValue,
+ pergroupstate->transValueIsNull,
+ pertrans->transtypeLen);
+ fcinfo->args[0].isnull = pergroupstate->transValueIsNull;
anynull |= pergroupstate->transValueIsNull;
/* Fill any remaining argument positions with nulls */
for (; i < numFinalArgs; i++)
{
- fcinfo.arg[i] = (Datum) 0;
- fcinfo.argnull[i] = true;
+ fcinfo->args[i].value = (Datum) 0;
+ fcinfo->args[i].isnull = true;
anynull = true;
}
- if (fcinfo.flinfo->fn_strict && anynull)
+ if (fcinfo->flinfo->fn_strict && anynull)
{
/* don't call a strict function with NULL inputs */
*resultVal = (Datum) 0;
@@ -962,8 +963,8 @@ finalize_aggregate(AggState *aggstate,
}
else
{
- *resultVal = FunctionCallInvoke(&fcinfo);
- *resultIsNull = fcinfo.isnull;
+ *resultVal = FunctionCallInvoke(fcinfo);
+ *resultIsNull = fcinfo->isnull;
}
aggstate->curperagg = NULL;
}
@@ -1018,12 +1019,13 @@ finalize_partialaggregate(AggState *aggstate,
}
else
{
- FunctionCallInfo fcinfo = &pertrans->serialfn_fcinfo;
+ FunctionCallInfo fcinfo = pertrans->serialfn_fcinfo;
- fcinfo->arg[0] = MakeExpandedObjectReadOnly(pergroupstate->transValue,
- pergroupstate->transValueIsNull,
- pertrans->transtypeLen);
- fcinfo->argnull[0] = pergroupstate->transValueIsNull;
+ fcinfo->args[0].value =
+ MakeExpandedObjectReadOnly(pergroupstate->transValue,
+ pergroupstate->transValueIsNull,
+ pertrans->transtypeLen);
+ fcinfo->args[0].isnull = pergroupstate->transValueIsNull;
*resultVal = FunctionCallInvoke(fcinfo);
*resultIsNull = fcinfo->isnull;
@@ -2927,7 +2929,9 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
fmgr_info(aggtransfn, &pertrans->transfn);
fmgr_info_set_expr((Node *) combinefnexpr, &pertrans->transfn);
- InitFunctionCallInfoData(pertrans->transfn_fcinfo,
+ pertrans->transfn_fcinfo =
+ (FunctionCallInfo) palloc(SizeForFunctionCallInfo(2));
+ InitFunctionCallInfoData(*pertrans->transfn_fcinfo,
&pertrans->transfn,
2,
pertrans->aggCollation,
@@ -2947,6 +2951,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
else
{
Expr *transfnexpr;
+ size_t numInputs = pertrans->numTransInputs + 1;
/*
* Set up infrastructure for calling the transfn. Note that invtrans
@@ -2965,9 +2970,11 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
fmgr_info(aggtransfn, &pertrans->transfn);
fmgr_info_set_expr((Node *) transfnexpr, &pertrans->transfn);
- InitFunctionCallInfoData(pertrans->transfn_fcinfo,
+ pertrans->transfn_fcinfo =
+ (FunctionCallInfo) palloc(SizeForFunctionCallInfo(numInputs));
+ InitFunctionCallInfoData(*pertrans->transfn_fcinfo,
&pertrans->transfn,
- pertrans->numTransInputs + 1,
+ numInputs,
pertrans->aggCollation,
(void *) aggstate, NULL);
@@ -3003,7 +3010,9 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
fmgr_info(aggserialfn, &pertrans->serialfn);
fmgr_info_set_expr((Node *) serialfnexpr, &pertrans->serialfn);
- InitFunctionCallInfoData(pertrans->serialfn_fcinfo,
+ pertrans->serialfn_fcinfo =
+ (FunctionCallInfo) palloc(SizeForFunctionCallInfo(1));
+ InitFunctionCallInfoData(*pertrans->serialfn_fcinfo,
&pertrans->serialfn,
1,
InvalidOid,
@@ -3017,7 +3026,9 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
fmgr_info(aggdeserialfn, &pertrans->deserialfn);
fmgr_info_set_expr((Node *) deserialfnexpr, &pertrans->deserialfn);
- InitFunctionCallInfoData(pertrans->deserialfn_fcinfo,
+ pertrans->deserialfn_fcinfo =
+ (FunctionCallInfo) palloc(SizeForFunctionCallInfo(2));
+ InitFunctionCallInfoData(*pertrans->deserialfn_fcinfo,
&pertrans->deserialfn,
2,
InvalidOid,
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 7ae56074ca8..731391f1907 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -241,10 +241,9 @@ advance_windowaggregate(WindowAggState *winstate,
WindowStatePerFunc perfuncstate,
WindowStatePerAgg peraggstate)
{
+ LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
WindowFuncExprState *wfuncstate = perfuncstate->wfuncstate;
int numArguments = perfuncstate->numArguments;
- FunctionCallInfoData fcinfodata;
- FunctionCallInfo fcinfo = &fcinfodata;
Datum newVal;
ListCell *arg;
int i;
@@ -273,8 +272,8 @@ advance_windowaggregate(WindowAggState *winstate,
{
ExprState *argstate = (ExprState *) lfirst(arg);
- fcinfo->arg[i] = ExecEvalExpr(argstate, econtext,
- &fcinfo->argnull[i]);
+ fcinfo->args[i].value = ExecEvalExpr(argstate, econtext,
+ &fcinfo->args[i].isnull);
i++;
}
@@ -287,7 +286,7 @@ advance_windowaggregate(WindowAggState *winstate,
*/
for (i = 1; i <= numArguments; i++)
{
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
{
MemoryContextSwitchTo(oldContext);
return;
@@ -306,7 +305,7 @@ advance_windowaggregate(WindowAggState *winstate,
if (peraggstate->transValueCount == 0 && peraggstate->transValueIsNull)
{
MemoryContextSwitchTo(peraggstate->aggcontext);
- peraggstate->transValue = datumCopy(fcinfo->arg[1],
+ peraggstate->transValue = datumCopy(fcinfo->args[1].value,
peraggstate->transtypeByVal,
peraggstate->transtypeLen);
peraggstate->transValueIsNull = false;
@@ -339,8 +338,8 @@ advance_windowaggregate(WindowAggState *winstate,
numArguments + 1,
perfuncstate->winCollation,
(void *) winstate, NULL);
- fcinfo->arg[0] = peraggstate->transValue;
- fcinfo->argnull[0] = peraggstate->transValueIsNull;
+ fcinfo->args[0].value = peraggstate->transValue;
+ fcinfo->args[0].isnull = peraggstate->transValueIsNull;
winstate->curaggcontext = peraggstate->aggcontext;
newVal = FunctionCallInvoke(fcinfo);
winstate->curaggcontext = NULL;
@@ -418,10 +417,9 @@ advance_windowaggregate_base(WindowAggState *winstate,
WindowStatePerFunc perfuncstate,
WindowStatePerAgg peraggstate)
{
+ LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
WindowFuncExprState *wfuncstate = perfuncstate->wfuncstate;
int numArguments = perfuncstate->numArguments;
- FunctionCallInfoData fcinfodata;
- FunctionCallInfo fcinfo = &fcinfodata;
Datum newVal;
ListCell *arg;
int i;
@@ -450,8 +448,8 @@ advance_windowaggregate_base(WindowAggState *winstate,
{
ExprState *argstate = (ExprState *) lfirst(arg);
- fcinfo->arg[i] = ExecEvalExpr(argstate, econtext,
- &fcinfo->argnull[i]);
+ fcinfo->args[i].value = ExecEvalExpr(argstate, econtext,
+ &fcinfo->args[i].isnull);
i++;
}
@@ -464,7 +462,7 @@ advance_windowaggregate_base(WindowAggState *winstate,
*/
for (i = 1; i <= numArguments; i++)
{
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
{
MemoryContextSwitchTo(oldContext);
return true;
@@ -510,8 +508,8 @@ advance_windowaggregate_base(WindowAggState *winstate,
numArguments + 1,
perfuncstate->winCollation,
(void *) winstate, NULL);
- fcinfo->arg[0] = peraggstate->transValue;
- fcinfo->argnull[0] = peraggstate->transValueIsNull;
+ fcinfo->args[0].value = peraggstate->transValue;
+ fcinfo->args[0].isnull = peraggstate->transValueIsNull;
winstate->curaggcontext = peraggstate->aggcontext;
newVal = FunctionCallInvoke(fcinfo);
winstate->curaggcontext = NULL;
@@ -591,30 +589,31 @@ finalize_windowaggregate(WindowAggState *winstate,
*/
if (OidIsValid(peraggstate->finalfn_oid))
{
+ LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
int numFinalArgs = peraggstate->numFinalArgs;
- FunctionCallInfoData fcinfo;
bool anynull;
int i;
- InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn),
+ InitFunctionCallInfoData(fcinfodata.fcinfo, &(peraggstate->finalfn),
numFinalArgs,
perfuncstate->winCollation,
(void *) winstate, NULL);
- fcinfo.arg[0] = MakeExpandedObjectReadOnly(peraggstate->transValue,
- peraggstate->transValueIsNull,
- peraggstate->transtypeLen);
- fcinfo.argnull[0] = peraggstate->transValueIsNull;
+ fcinfo->args[0].value =
+ MakeExpandedObjectReadOnly(peraggstate->transValue,
+ peraggstate->transValueIsNull,
+ peraggstate->transtypeLen);
+ fcinfo->args[0].isnull = peraggstate->transValueIsNull;
anynull = peraggstate->transValueIsNull;
/* Fill any remaining argument positions with nulls */
for (i = 1; i < numFinalArgs; i++)
{
- fcinfo.arg[i] = (Datum) 0;
- fcinfo.argnull[i] = true;
+ fcinfo->args[i].value = (Datum) 0;
+ fcinfo->args[i].isnull = true;
anynull = true;
}
- if (fcinfo.flinfo->fn_strict && anynull)
+ if (fcinfo->flinfo->fn_strict && anynull)
{
/* don't call a strict function with NULL inputs */
*result = (Datum) 0;
@@ -623,9 +622,9 @@ finalize_windowaggregate(WindowAggState *winstate,
else
{
winstate->curaggcontext = peraggstate->aggcontext;
- *result = FunctionCallInvoke(&fcinfo);
+ *result = FunctionCallInvoke(fcinfo);
winstate->curaggcontext = NULL;
- *isnull = fcinfo.isnull;
+ *isnull = fcinfo->isnull;
}
}
else
@@ -1032,7 +1031,7 @@ static void
eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate,
Datum *result, bool *isnull)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
MemoryContext oldContext;
oldContext = MemoryContextSwitchTo(winstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
@@ -1043,24 +1042,25 @@ eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate,
* implementations to support varying numbers of arguments. The real info
* goes through the WindowObject, which is passed via fcinfo->context.
*/
- InitFunctionCallInfoData(fcinfo, &(perfuncstate->flinfo),
+ InitFunctionCallInfoData(*fcinfo, &(perfuncstate->flinfo),
perfuncstate->numArguments,
perfuncstate->winCollation,
(void *) perfuncstate->winobj, NULL);
/* Just in case, make all the regular argument slots be null */
- memset(fcinfo.argnull, true, perfuncstate->numArguments);
+ for (int argno = 0; argno < perfuncstate->numArguments; argno++)
+ fcinfo->args[argno].isnull = true;
/* Window functions don't have a current aggregate context, either */
winstate->curaggcontext = NULL;
- *result = FunctionCallInvoke(&fcinfo);
- *isnull = fcinfo.isnull;
+ *result = FunctionCallInvoke(fcinfo);
+ *isnull = fcinfo->isnull;
/*
* Make sure pass-by-ref data is allocated in the appropriate context. (We
* need this in case the function returns a pointer into some short-lived
* tuple, as is entirely possible.)
*/
- if (!perfuncstate->resulttypeByVal && !fcinfo.isnull &&
+ if (!perfuncstate->resulttypeByVal && !fcinfo->isnull &&
!MemoryContextContains(CurrentMemoryContext,
DatumGetPointer(*result)))
*result = datumCopy(*result,