static void
setup_firstcall(FuncCallContext *funcctx, HStore *hs,
- FunctionCallInfoData *fcinfo)
+ FunctionCallInfo fcinfo)
{
MemoryContext oldcontext;
HStore *st;
<para>
The call handler is called in the same way as any other function:
It receives a pointer to a
- <structname>FunctionCallInfoData</structname> <type>struct</type> containing
+ <structname>FunctionCallInfoBaseData</structname> <type>struct</type> containing
argument values and information about the called function, and it
is expected to return a <type>Datum</type> result (and possibly
set the <structfield>isnull</structfield> field of the
- <structname>FunctionCallInfoData</structname> structure, if it wishes
+ <structname>FunctionCallInfoBaseData</structname> structure, if it wishes
to return an SQL null result). The difference between a call
handler and an ordinary callee function is that the
<structfield>flinfo->fn_oid</structfield> field of the
- <structname>FunctionCallInfoData</structname> structure will contain
+ <structname>FunctionCallInfoBaseData</structname> structure will contain
the OID of the actual function to be called, not of the call
handler itself. The call handler must use this field to determine
which function to execute. Also, the passed argument list has
<para>
When a procedural-language function is invoked as a trigger, no arguments
are passed in the usual way, but the
- <structname>FunctionCallInfoData</structname>'s
+ <structname>FunctionCallInfoBaseData</structname>'s
<structfield>context</structfield> field points at a
<structname>TriggerData</structname> structure, rather than being <symbol>NULL</symbol>
as it is in a plain function call. A language handler should
/* Call each event trigger. */
foreach(lc, fn_oid_list)
{
+ LOCAL_FCINFO(fcinfo, 0);
Oid fnoid = lfirst_oid(lc);
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
PgStat_FunctionCallUsage fcusage;
elog(DEBUG1, "EventTriggerInvoke %u", fnoid);
fmgr_info(fnoid, &flinfo);
/* Call the function, passing no arguments but setting a context. */
- InitFunctionCallInfoData(fcinfo, &flinfo, 0,
+ InitFunctionCallInfoData(*fcinfo, &flinfo, 0,
InvalidOid, (Node *) trigdata, NULL);
- pgstat_init_function_usage(&fcinfo, &fcusage);
- FunctionCallInvoke(&fcinfo);
+ pgstat_init_function_usage(fcinfo, &fcusage);
+ FunctionCallInvoke(fcinfo);
pgstat_end_function_usage(&fcusage, true);
/* Reclaim memory. */
void
ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest)
{
+ LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
ListCell *lc;
FuncExpr *fexpr;
int nargs;
int i;
AclResult aclresult;
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
CallContext *callcontext;
EState *estate;
ExprContext *econtext;
InvokeFunctionExecuteHook(fexpr->funcid);
fmgr_info(fexpr->funcid, &flinfo);
fmgr_info_set_expr((Node *) fexpr, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, nargs, fexpr->inputcollid, (Node *) callcontext, NULL);
+ InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
+ (Node *) callcontext, NULL);
/*
* Evaluate procedure arguments inside a suitable execution context. Note
val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
- fcinfo.arg[i] = val;
- fcinfo.argnull[i] = isnull;
+ fcinfo->args[i].value = val;
+ fcinfo->args[i].isnull = isnull;
i++;
}
- pgstat_init_function_usage(&fcinfo, &fcusage);
- retval = FunctionCallInvoke(&fcinfo);
+ pgstat_init_function_usage(fcinfo, &fcusage);
+ retval = FunctionCallInvoke(fcinfo);
pgstat_end_function_usage(&fcusage, true);
if (fexpr->funcresulttype == VOIDOID)
TupOutputState *tstate;
TupleTableSlot *slot;
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "procedure returned null record");
td = DatumGetHeapTupleHeader(retval);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 0);
TriggerData trigdata;
/*
*
* No parameters are passed, but we do set a context
*/
- MemSet(&fcinfo, 0, sizeof(fcinfo));
+ MemSet(fcinfo, 0, SizeForFunctionCallInfo(0));
/*
* We assume RI_FKey_check_ins won't look at flinfo...
trigdata.tg_trigtuplebuf = scan->rs_cbuf;
trigdata.tg_newtuplebuf = InvalidBuffer;
- fcinfo.context = (Node *) &trigdata;
+ fcinfo->context = (Node *) &trigdata;
- RI_FKey_check_ins(&fcinfo);
+ RI_FKey_check_ins(fcinfo);
}
heap_endscan(scan);
Instrumentation *instr,
MemoryContext per_tuple_context)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 0);
PgStat_FunctionCallUsage fcusage;
Datum result;
MemoryContext oldContext;
/*
* Call the function, passing no arguments but setting a context.
*/
- InitFunctionCallInfoData(fcinfo, finfo, 0,
+ InitFunctionCallInfoData(*fcinfo, finfo, 0,
InvalidOid, (Node *) trigdata, NULL);
- pgstat_init_function_usage(&fcinfo, &fcusage);
+ pgstat_init_function_usage(fcinfo, &fcusage);
MyTriggerDepth++;
PG_TRY();
{
- result = FunctionCallInvoke(&fcinfo);
+ result = FunctionCallInvoke(fcinfo);
}
PG_CATCH();
{
* Trigger protocol allows function to return a null pointer, but NOT to
* set the isnull result flag.
*/
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
ereport(ERROR,
(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
errmsg("trigger function %u returned null value",
- fcinfo.flinfo->fn_oid)));
+ fcinfo->flinfo->fn_oid)));
/*
* If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
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.
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
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.
/* 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,
/* 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
/* 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);
/* 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);
* 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;
/* 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,
/* 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;
/* 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,
/* 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;
*/
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++;
}
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;
/*
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);
/*
* 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
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,
/*
* Normal transition function without ORDER BY / DISTINCT.
*/
- strictnulls = trans_fcinfo->argnull + 1;
+ strictargs = trans_fcinfo->args + 1;
foreach(arg, pertrans->aggref->args)
{
* 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++;
}
}
*/
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);
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;
*/
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,
/* 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,
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 */
&&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,
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;
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));
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;
{
/*
* 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);
{
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;
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;
}
/* 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();
}
/* 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);
/* 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 */
* 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;
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.
*/
Assert(pertrans->transtypeByVal);
- fcinfo = &pertrans->transfn_fcinfo;
+ fcinfo = pertrans->transfn_fcinfo;
/* cf. select_current_set() */
aggstate->curaggcontext = op->d.agg_trans.aggcontext;
/* 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);
Assert(!pertrans->transtypeByVal);
- fcinfo = &pertrans->transfn_fcinfo;
+ fcinfo = pertrans->transfn_fcinfo;
/* cf. select_current_set() */
aggstate->curaggcontext = op->d.agg_trans.aggcontext;
/* 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);
{
ExprEvalStep *op = &state->steps[0];
FunctionCallInfo fcinfo;
- bool *argnull;
+ NullableDatum *args;
int argno;
Datum d;
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;
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;
void
ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
{
+ LOCAL_FCINFO(fcinfo, 0);
SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
- FunctionCallInfoData fcinfo;
*op->resnull = false;
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;
}
}
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;
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));
* 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
* 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;
/* 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;
void
ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup)
{
- FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+ FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
MemoryContext oldContext;
/*
*/
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;
Oid funcrettype;
bool returnsTuple;
bool returnsSet = false;
- FunctionCallInfoData fcinfo;
+ FunctionCallInfo fcinfo;
PgStat_FunctionCallUsage fcusage;
ReturnSetInfo rsinfo;
HeapTupleData tmptup;
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
* 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);
/*
*/
MemoryContextReset(argContext);
oldcontext = MemoryContextSwitchTo(argContext);
- ExecEvalFuncArgs(&fcinfo, setexpr->args, econtext);
+ ExecEvalFuncArgs(fcinfo, setexpr->args, econtext);
MemoryContextSwitchTo(oldcontext);
/*
{
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;
}
}
else
{
/* Treat setexpr as a generic expression */
- InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
}
/*
/* 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);
else
{
result =
- ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo.isnull);
+ ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo->isnull);
rsinfo.isDone = ExprSingleResult;
}
*/
if (returnsTuple)
{
- if (!fcinfo.isnull)
+ if (!fcinfo->isnull)
{
HeapTupleHeader td = DatumGetHeapTupleHeader(result);
else
{
/* Scalar-type case: just store the function result */
- tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull);
+ tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo->isnull);
}
/*
* 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)
{
{
for (i = 0; i < fcinfo->nargs; i++)
{
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
{
callit = false;
break;
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);
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 */
{
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++;
}
{
ParamExternData *prm = ¶mLI->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];
}
AggStatePerTrans pertrans,
AggStatePerGroup pergroupstate)
{
- FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+ FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
MemoryContext oldContext;
Datum newVal;
for (i = 1; i <= numTransInputs; i++)
{
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
return;
}
if (pergroupstate->noTransValue)
*/
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;
/*
* 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);
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;
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
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;
/* 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);
AggStatePerGroup pergroupstate,
Datum *resultVal, bool *resultIsNull)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
bool anynull = false;
MemoryContext oldContext;
int i;
{
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++;
}
/* 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;
}
else
{
- *resultVal = FunctionCallInvoke(&fcinfo);
- *resultIsNull = fcinfo.isnull;
+ *resultVal = FunctionCallInvoke(fcinfo);
+ *resultIsNull = fcinfo->isnull;
}
aggstate->curperagg = NULL;
}
}
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;
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,
else
{
Expr *transfnexpr;
+ size_t numInputs = pertrans->numTransInputs + 1;
/*
* Set up infrastructure for calling the transfn. Note that invtrans
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);
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,
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,
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;
{
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++;
}
*/
for (i = 1; i <= numArguments; i++)
{
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
{
MemoryContextSwitchTo(oldContext);
return;
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;
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;
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;
{
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++;
}
*/
for (i = 1; i <= numArguments; i++)
{
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
{
MemoryContextSwitchTo(oldContext);
return true;
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;
*/
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;
else
{
winstate->curaggcontext = peraggstate->aggcontext;
- *result = FunctionCallInvoke(&fcinfo);
+ *result = FunctionCallInvoke(fcinfo);
winstate->curaggcontext = NULL;
- *isnull = fcinfo.isnull;
+ *isnull = fcinfo->isnull;
}
}
else
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);
* 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,
LLVMTypeRef TypeParamBool;
LLVMTypeRef TypeStorageBool;
LLVMTypeRef TypePGFunction;
+LLVMTypeRef StructNullableDatum;
LLVMTypeRef StructHeapTupleFieldsField3;
LLVMTypeRef StructHeapTupleFields;
LLVMTypeRef StructHeapTupleHeaderData;
TypeParamBool = load_return_type(mod, "FunctionReturningBool");
TypeStorageBool = load_type(mod, "TypeStorageBool");
TypePGFunction = load_type(mod, "TypePGFunction");
+ StructNullableDatum = load_type(mod, "StructNullableDatum");
StructExprContext = load_type(mod, "StructExprContext");
StructExprEvalStep = load_type(mod, "StructExprEvalStep");
StructExprState = load_type(mod, "StructExprState");
LLVMBasicBlockRef b_nonull;
int argno;
LLVMValueRef v_fcinfo;
- LLVMValueRef v_argnullp;
LLVMBasicBlockRef *b_checkargnulls;
/*
v_fcinfo =
l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
- v_argnullp =
- LLVMBuildStructGEP(b,
- v_fcinfo,
- FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
- "v_argnullp");
-
/*
* set resnull to true, if the function is actually
* called, it'll be reset
b_argnotnull = b_checkargnulls[argno + 1];
/* and finally load & check NULLness of arg */
- v_argisnull = l_load_struct_gep(b, v_argnullp,
- argno, "");
+ v_argisnull = l_funcnull(b, v_fcinfo, argno);
LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ,
v_argisnull,
LLVMValueRef v_fn_addr_out,
v_fn_addr_in;
LLVMValueRef v_fcinfo_in_isnullp;
- LLVMValueRef v_in_argp,
- v_out_argp;
- LLVMValueRef v_in_argnullp,
- v_out_argnullp;
LLVMValueRef v_retval;
LLVMValueRef v_resvalue;
LLVMValueRef v_resnull;
LLVMBuildStructGEP(b, v_fcinfo_in,
FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
"v_fcinfo_in_isnull");
- v_out_argnullp =
- LLVMBuildStructGEP(b, v_fcinfo_out,
- FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
- "v_fcinfo_out_argnullp");
- v_in_argnullp =
- LLVMBuildStructGEP(b, v_fcinfo_in,
- FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
- "v_fcinfo_in_argnullp");
- v_out_argp =
- LLVMBuildStructGEP(b, v_fcinfo_out,
- FIELDNO_FUNCTIONCALLINFODATA_ARG,
- "v_fcinfo_out_argp");
- v_in_argp =
- LLVMBuildStructGEP(b, v_fcinfo_in,
- FIELDNO_FUNCTIONCALLINFODATA_ARG,
- "v_fcinfo_in_argp");
/* output functions are not called on nulls */
v_resnull = LLVMBuildLoad(b, v_resnullp, "");
/* set arg[0] */
LLVMBuildStore(b,
v_resvalue,
- LLVMBuildStructGEP(b, v_out_argp, 0, ""));
+ l_funcvaluep(b, v_fcinfo_out, 0));
LLVMBuildStore(b,
l_sbool_const(0),
- LLVMBuildStructGEP(b, v_out_argnullp,
- 0, ""));
+ l_funcnullp(b, v_fcinfo_out, 0));
/* and call output function (can never return NULL) */
v_output = LLVMBuildCall(b, v_fn_addr_out, &v_fcinfo_out,
1, "funccall_coerce_out");
/* set arguments */
/* arg0: output */
LLVMBuildStore(b, v_output,
- LLVMBuildStructGEP(b, v_in_argp, 0, ""));
+ l_funcvaluep(b, v_fcinfo_in, 0));
LLVMBuildStore(b, v_resnull,
- LLVMBuildStructGEP(b, v_in_argnullp, 0, ""));
+ l_funcnullp(b, v_fcinfo_in, 0));
/* arg1: ioparam: preset in execExpr.c */
/* arg2: typmod: preset in execExpr.c */
LLVMValueRef v_fcinfo;
LLVMValueRef v_fcinfo_isnull;
- LLVMValueRef v_argnullp;
LLVMValueRef v_argnull0,
v_argisnull0;
LLVMValueRef v_argnull1,
v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
- v_argnullp =
- LLVMBuildStructGEP(b,
- v_fcinfo,
- FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
- "v_argnullp");
-
- /* load argnull[0|1] for both arguments */
- v_argnull0 = l_load_struct_gep(b, v_argnullp, 0, "");
+ /* load args[0|1].isnull for both arguments */
+ v_argnull0 = l_funcnull(b, v_fcinfo, 0);
v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
l_sbool_const(1), "");
-
- v_argnull1 = l_load_struct_gep(b, v_argnullp, 1, "");
+ v_argnull1 = l_funcnull(b, v_fcinfo, 1);
v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
l_sbool_const(1), "");
LLVMValueRef v_fcinfo;
LLVMValueRef v_fcinfo_isnull;
- LLVMValueRef v_argnullp;
LLVMValueRef v_argnull0;
LLVMValueRef v_argnull1;
LLVMValueRef v_anyargisnull;
- LLVMValueRef v_argp;
LLVMValueRef v_arg0;
LLVMBasicBlockRef b_hasnull;
LLVMBasicBlockRef b_nonull;
v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
- v_argnullp =
- LLVMBuildStructGEP(b,
- v_fcinfo,
- FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
- "v_argnullp");
-
- v_argp =
- LLVMBuildStructGEP(b,
- v_fcinfo,
- FIELDNO_FUNCTIONCALLINFODATA_ARG,
- "v_argp");
-
/* if either argument is NULL they can't be equal */
- v_argnull0 = l_load_struct_gep(b, v_argnullp, 0, "");
- v_argnull1 = l_load_struct_gep(b, v_argnullp, 1, "");
+ v_argnull0 = l_funcnull(b, v_fcinfo, 0);
+ v_argnull1 = l_funcnull(b, v_fcinfo, 1);
v_anyargisnull =
LLVMBuildOr(b,
/* one (or both) of the arguments are null, return arg[0] */
LLVMPositionBuilderAtEnd(b, b_hasnull);
- v_arg0 = l_load_struct_gep(b, v_argp, 0, "");
+ v_arg0 = l_funcvalue(b, v_fcinfo, 0);
LLVMBuildStore(b, v_argnull0, v_resnullp);
LLVMBuildStore(b, v_arg0, v_resvaluep);
LLVMBuildBr(b, opblocks[i + 1]);
if (op->d.rowcompare_step.finfo->fn_strict)
{
LLVMValueRef v_fcinfo;
- LLVMValueRef v_argnullp;
LLVMValueRef v_argnull0;
LLVMValueRef v_argnull1;
LLVMValueRef v_anyargisnull;
v_fcinfo = l_ptr_const(fcinfo,
l_ptr(StructFunctionCallInfoData));
- v_argnullp =
- LLVMBuildStructGEP(b, v_fcinfo,
- FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
- "v_argnullp");
-
- v_argnull0 = l_load_struct_gep(b, v_argnullp, 0, "");
- v_argnull1 = l_load_struct_gep(b, v_argnullp, 1, "");
+ v_argnull0 = l_funcnull(b, v_fcinfo, 0);
+ v_argnull1 = l_funcnull(b, v_fcinfo, 1);
v_anyargisnull =
LLVMBuildOr(b,
{
FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
LLVMValueRef v_fcinfo;
- LLVMValueRef v_argnullp;
LLVMValueRef v_argnull0;
LLVMBasicBlockRef b_deserialize;
v_fcinfo = l_ptr_const(fcinfo,
l_ptr(StructFunctionCallInfoData));
-
- v_argnullp =
- LLVMBuildStructGEP(b,
- v_fcinfo,
- FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
- "v_argnullp");
- v_argnull0 =
- l_load_struct_gep(b, v_argnullp, 0, "v_argnull0");
+ v_argnull0 = l_funcnull(b, v_fcinfo, 0);
LLVMBuildCondBr(b,
LLVMBuildICmp(b,
break;
}
- case EEOP_AGG_STRICT_INPUT_CHECK:
+ case EEOP_AGG_STRICT_INPUT_CHECK_NULLS:
+ case EEOP_AGG_STRICT_INPUT_CHECK_ARGS:
{
int nargs = op->d.agg_strict_input_check.nargs;
+ NullableDatum *args = op->d.agg_strict_input_check.args;
bool *nulls = op->d.agg_strict_input_check.nulls;
int jumpnull;
int argno;
- LLVMValueRef v_nullp;
+ LLVMValueRef v_argsp;
+ LLVMValueRef v_nullsp;
LLVMBasicBlockRef *b_checknulls;
Assert(nargs > 0);
jumpnull = op->d.agg_strict_input_check.jumpnull;
- v_nullp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
+ v_argsp = l_ptr_const(args, l_ptr(StructNullableDatum));
+ v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
/* create blocks for checking args */
b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
else
b_argnotnull = b_checknulls[argno + 1];
- v_argisnull = l_load_gep1(b, v_nullp, v_argno, "");
+ if (opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
+ v_argisnull = l_load_gep1(b, v_nullsp, v_argno, "");
+ else
+ {
+ LLVMValueRef v_argn;
+
+ v_argn = LLVMBuildGEP(b, v_argsp, &v_argno, 1, "");
+ v_argisnull =
+ l_load_struct_gep(b, v_argn,
+ FIELDNO_NULLABLE_DATUM_ISNULL,
+ "");
+ }
LLVMBuildCondBr(b,
LLVMBuildICmp(b,
LLVMValueRef v_aggstatep;
LLVMValueRef v_fcinfo;
LLVMValueRef v_fcinfo_isnull;
- LLVMValueRef v_argp,
- v_argnullp;
LLVMValueRef v_transvaluep;
LLVMValueRef v_transnullp;
aggstate = op->d.agg_trans.aggstate;
pertrans = op->d.agg_trans.pertrans;
- fcinfo = &pertrans->transfn_fcinfo;
+ fcinfo = pertrans->transfn_fcinfo;
v_aggstatep = l_ptr_const(aggstate,
l_ptr(StructAggState));
v_fcinfo = l_ptr_const(fcinfo,
l_ptr(StructFunctionCallInfoData));
-
- v_argnullp =
- LLVMBuildStructGEP(b,
- v_fcinfo,
- FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
- "v_argnullp");
- v_argp =
- LLVMBuildStructGEP(b,
- v_fcinfo,
- FIELDNO_FUNCTIONCALLINFODATA_ARG,
- "v_argp");
-
v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
l_ptr(StructExprContext));
l_ptr(StructMemoryContextData));
v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
- /* store transvalue in fcinfo->arg/argnull[0] */
+ /* store transvalue in fcinfo->args[0] */
v_transvaluep =
LLVMBuildStructGEP(b, v_pergroupp,
FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE,
LLVMBuildStore(b,
LLVMBuildLoad(b, v_transvaluep,
"transvalue"),
- LLVMBuildStructGEP(b, v_argp, 0, ""));
+ l_funcvaluep(b, v_fcinfo, 0));
LLVMBuildStore(b,
LLVMBuildLoad(b, v_transnullp, "transnull"),
- LLVMBuildStructGEP(b, v_argnullp, 0, ""));
+ l_funcnullp(b, v_fcinfo, 0));
/* and invoke transition function */
v_retval = BuildV1Call(context, b, mod, fcinfo,
LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
LLVMValueRef params[2];
- params[0] = l_int64_const(sizeof(fcinfo->arg));
- params[1] = l_ptr_const(fcinfo->arg, l_ptr(LLVMInt8Type()));
- LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
-
- params[0] = l_int64_const(sizeof(fcinfo->argnull));
- params[1] = l_ptr_const(fcinfo->argnull, l_ptr(LLVMInt8Type()));
+ params[0] = l_int64_const(sizeof(NullableDatum) * fcinfo->nargs);
+ params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8Type()));
LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
params[0] = l_int64_const(sizeof(fcinfo->isnull));
size_t TypeSizeT;
bool TypeStorageBool;
+NullableDatum StructNullableDatum;
AggState StructAggState;
AggStatePerGroupData StructAggStatePerGroupData;
AggStatePerTransData StructAggStatePerTransData;
ExprContext StructExprContext;
ExprEvalStep StructExprEvalStep;
ExprState StructExprState;
-FunctionCallInfoData StructFunctionCallInfoData;
+FunctionCallInfoBaseData StructFunctionCallInfoData;
HeapTupleData StructHeapTupleData;
MemoryContextData StructMemoryContextData;
TupleTableSlot StructTupleTableSlot;
* Called by the executor before invoking a function.
*/
void
-pgstat_init_function_usage(FunctionCallInfoData *fcinfo,
+pgstat_init_function_usage(FunctionCallInfo fcinfo,
PgStat_FunctionCallUsage *fcu)
{
PgStat_BackendFunctionEntry *htabent;
void
HandleFunctionRequest(StringInfo msgBuf)
{
+ LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
Oid fid;
AclResult aclresult;
- FunctionCallInfoData fcinfo;
int16 rformat;
Datum retval;
struct fp_info my_fp;
* functions can't be called this way. Perhaps we should pass
* DEFAULT_COLLATION_OID, instead?
*/
- InitFunctionCallInfoData(fcinfo, &fip->flinfo, 0, InvalidOid, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, &fip->flinfo, 0, InvalidOid, NULL, NULL);
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
- rformat = parse_fcall_arguments(msgBuf, fip, &fcinfo);
+ rformat = parse_fcall_arguments(msgBuf, fip, fcinfo);
else
- rformat = parse_fcall_arguments_20(msgBuf, fip, &fcinfo);
+ rformat = parse_fcall_arguments_20(msgBuf, fip, fcinfo);
/* Verify we reached the end of the message where expected. */
pq_getmsgend(msgBuf);
{
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)
{
callit = false;
break;
if (callit)
{
/* Okay, do it ... */
- retval = FunctionCallInvoke(&fcinfo);
+ retval = FunctionCallInvoke(fcinfo);
}
else
{
- fcinfo.isnull = true;
+ fcinfo->isnull = true;
retval = (Datum) 0;
}
/* ensure we do at least one CHECK_FOR_INTERRUPTS per function call */
CHECK_FOR_INTERRUPTS();
- SendFunctionResult(retval, fcinfo.isnull, fip->rettype, rformat);
+ SendFunctionResult(retval, fcinfo->isnull, fip->rettype, rformat);
/* We no longer need the snapshot */
PopActiveSnapshot();
argsize = pq_getmsgint(msgBuf, 4);
if (argsize == -1)
{
- fcinfo->argnull[i] = true;
+ fcinfo->args[i].isnull = true;
}
else
{
- fcinfo->argnull[i] = false;
+ fcinfo->args[i].isnull = false;
if (argsize < 0)
ereport(ERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
else
pstring = pg_client_to_server(abuf.data, argsize);
- fcinfo->arg[i] = OidInputFunctionCall(typinput, pstring,
- typioparam, -1);
+ fcinfo->args[i].value = OidInputFunctionCall(typinput, pstring,
+ typioparam, -1);
/* Free result of encoding conversion, if any */
if (pstring && pstring != abuf.data)
pfree(pstring);
else
bufptr = &abuf;
- fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, bufptr,
- typioparam, -1);
+ fcinfo->args[i].value = OidReceiveFunctionCall(typreceive, bufptr,
+ typioparam, -1);
/* Trouble if it didn't eat the whole buffer */
if (argsize != -1 && abuf.cursor != abuf.len)
argsize = pq_getmsgint(msgBuf, 4);
if (argsize == -1)
{
- fcinfo->argnull[i] = true;
- fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, NULL,
- typioparam, -1);
+ fcinfo->args[i].isnull = true;
+ fcinfo->args[i].value = OidReceiveFunctionCall(typreceive, NULL,
+ typioparam, -1);
continue;
}
- fcinfo->argnull[i] = false;
+ fcinfo->args[i].isnull = false;
if (argsize < 0)
ereport(ERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
pq_getmsgbytes(msgBuf, argsize),
argsize);
- fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, &abuf,
- typioparam, -1);
+ fcinfo->args[i].value = OidReceiveFunctionCall(typreceive, &abuf,
+ typioparam, -1);
/* Trouble if it didn't eat the whole buffer */
if (abuf.cursor != abuf.len)
Datum
array_eq(PG_FUNCTION_ARGS)
{
+ LOCAL_FCINFO(locfcinfo, 2);
AnyArrayType *array1 = PG_GETARG_ANY_ARRAY_P(0);
AnyArrayType *array2 = PG_GETARG_ANY_ARRAY_P(1);
Oid collation = PG_GET_COLLATION();
array_iter it1;
array_iter it2;
int i;
- FunctionCallInfoData locfcinfo;
if (element_type != AARR_ELEMTYPE(array2))
ereport(ERROR,
/*
* apply the operator to each pair of array elements.
*/
- InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
+ InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
collation, NULL, NULL);
/* Loop over source data */
/*
* 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));
+ locfcinfo->args[0].value = elt1;
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = elt2;
+ locfcinfo->args[1].isnull = false;
+ locfcinfo->isnull = false;
+ oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
if (!oprresult)
{
result = false;
static int
array_cmp(FunctionCallInfo fcinfo)
{
+ LOCAL_FCINFO(locfcinfo, 2);
AnyArrayType *array1 = PG_GETARG_ANY_ARRAY_P(0);
AnyArrayType *array2 = PG_GETARG_ANY_ARRAY_P(1);
Oid collation = PG_GET_COLLATION();
array_iter it1;
array_iter it2;
int i;
- FunctionCallInfoData locfcinfo;
if (element_type != AARR_ELEMTYPE(array2))
ereport(ERROR,
/*
* apply the operator to each pair of array elements.
*/
- InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
+ InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2,
collation, NULL, NULL);
/* Loop over source data */
}
/* Compare the pair of elements */
- locfcinfo.arg[0] = elt1;
- locfcinfo.arg[1] = elt2;
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.isnull = false;
- cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
+ locfcinfo->args[0].value = elt1;
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = elt2;
+ locfcinfo->args[1].isnull = false;
+ locfcinfo->isnull = false;
+ cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo));
if (cmpresult == 0)
continue; /* equal */
Datum
hash_array(PG_FUNCTION_ARGS)
{
+ LOCAL_FCINFO(locfcinfo, 1);
AnyArrayType *array = PG_GETARG_ANY_ARRAY_P(0);
int ndims = AARR_NDIM(array);
int *dims = AARR_DIMS(array);
char typalign;
int i;
array_iter iter;
- FunctionCallInfoData locfcinfo;
/*
* We arrange to look up the hash function only once per series of calls,
/*
* apply the hash function to each array element.
*/
- InitFunctionCallInfoData(locfcinfo, &typentry->hash_proc_finfo, 1,
+ InitFunctionCallInfoData(*locfcinfo, &typentry->hash_proc_finfo, 1,
InvalidOid, NULL, NULL);
/* Loop over source data */
else
{
/* Apply the hash function */
- locfcinfo.arg[0] = elt;
- locfcinfo.argnull[0] = false;
- locfcinfo.isnull = false;
- elthash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo));
+ locfcinfo->args[0].value = elt;
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->isnull = false;
+ elthash = DatumGetUInt32(FunctionCallInvoke(locfcinfo));
}
/*
Datum
hash_array_extended(PG_FUNCTION_ARGS)
{
+ LOCAL_FCINFO(locfcinfo, 2);
AnyArrayType *array = PG_GETARG_ANY_ARRAY_P(0);
uint64 seed = PG_GETARG_INT64(1);
int ndims = AARR_NDIM(array);
char typalign;
int i;
array_iter iter;
- FunctionCallInfoData locfcinfo;
typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
if (typentry == NULL ||
typbyval = typentry->typbyval;
typalign = typentry->typalign;
- InitFunctionCallInfoData(locfcinfo, &typentry->hash_extended_proc_finfo, 2,
+ InitFunctionCallInfoData(*locfcinfo, &typentry->hash_extended_proc_finfo, 2,
InvalidOid, NULL, NULL);
/* Loop over source data */
else
{
/* Apply the hash function */
- locfcinfo.arg[0] = elt;
- locfcinfo.arg[1] = Int64GetDatum(seed);
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.isnull = false;
- elthash = DatumGetUInt64(FunctionCallInvoke(&locfcinfo));
+ locfcinfo->args[0].value = elt;
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = Int64GetDatum(seed);
+ locfcinfo->args[1].isnull = false;
+ elthash = DatumGetUInt64(FunctionCallInvoke(locfcinfo));
}
result = (result << 5) - result + elthash;
array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation,
bool matchall, void **fn_extra)
{
+ LOCAL_FCINFO(locfcinfo, 2);
bool result = matchall;
Oid element_type = AARR_ELEMTYPE(array1);
TypeCacheEntry *typentry;
int i;
int j;
array_iter it1;
- FunctionCallInfoData locfcinfo;
if (element_type != AARR_ELEMTYPE(array2))
ereport(ERROR,
/*
* Apply the comparison operator to each pair of array elements.
*/
- InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
+ InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
collation, NULL, NULL);
/* Loop over source data */
/*
* 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));
+ locfcinfo->args[0].value = elt1;
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = elt2;
+ locfcinfo->args[1].isnull = false;
+ locfcinfo->isnull = false;
+ oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
if (oprresult)
break;
}
bool remove, Oid collation,
FunctionCallInfo fcinfo)
{
+ LOCAL_FCINFO(locfcinfo, 2);
ArrayType *result;
Oid element_type;
Datum *values;
int bitmask;
bool changed = false;
TypeCacheEntry *typentry;
- FunctionCallInfoData locfcinfo;
element_type = ARR_ELEMTYPE(array);
ndim = ARR_NDIM(array);
}
/* Prepare to apply the comparison operator */
- InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
+ InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
collation, NULL, NULL);
/* Allocate temporary arrays for new values */
/*
* Apply the operator to the element pair
*/
- locfcinfo.arg[0] = elt;
- locfcinfo.arg[1] = search;
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.isnull = false;
- oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
+ locfcinfo->args[0].value = elt;
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = search;
+ locfcinfo->args[1].isnull = false;
+ locfcinfo->isnull = false;
+ oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
if (!oprresult)
{
/* no match, keep element */
Oid collation,
TypeCacheEntry *typentry)
{
+ LOCAL_FCINFO(locfcinfo, 2);
char *thresholds_data;
int typlen = typentry->typlen;
bool typbyval = typentry->typbyval;
- FunctionCallInfoData locfcinfo;
int left;
int right;
*/
thresholds_data = (char *) ARR_DATA_PTR(thresholds);
- InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
+ InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2,
collation, NULL, NULL);
/* Find the bucket */
ptr = thresholds_data + mid * typlen;
- locfcinfo.arg[0] = operand;
- locfcinfo.arg[1] = fetch_att(ptr, typbyval, typlen);
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.isnull = false;
+ locfcinfo->args[0].value = operand;
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = fetch_att(ptr, typbyval, typlen);
+ locfcinfo->args[1].isnull = false;
+ locfcinfo->isnull = false;
- cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
+ cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo));
if (cmpresult < 0)
right = mid;
Oid collation,
TypeCacheEntry *typentry)
{
+ LOCAL_FCINFO(locfcinfo, 2);
char *thresholds_data;
int typlen = typentry->typlen;
bool typbyval = typentry->typbyval;
char typalign = typentry->typalign;
- FunctionCallInfoData locfcinfo;
int left;
int right;
thresholds_data = (char *) ARR_DATA_PTR(thresholds);
- InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
+ InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2,
collation, NULL, NULL);
/* Find the bucket */
ptr = (char *) att_align_nominal(ptr, typalign);
}
- locfcinfo.arg[0] = operand;
- locfcinfo.arg[1] = fetch_att(ptr, typbyval, typlen);
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.isnull = false;
+ locfcinfo->args[0].value = operand;
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = fetch_att(ptr, typbyval, typlen);
+ locfcinfo->args[1].isnull = false;
- cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
+ cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo));
if (cmpresult < 0)
right = mid;
Datum
int2vectorrecv(PG_FUNCTION_ARGS)
{
+ LOCAL_FCINFO(locfcinfo, 3);
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
- FunctionCallInfoData locfcinfo;
int2vector *result;
/*
* fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
* parameter.
*/
- InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
+ InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3,
InvalidOid, NULL, NULL);
- locfcinfo.arg[0] = PointerGetDatum(buf);
- locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID);
- locfcinfo.arg[2] = Int32GetDatum(-1);
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.argnull[2] = false;
+ locfcinfo->args[0].value = PointerGetDatum(buf);
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = ObjectIdGetDatum(INT2OID);
+ locfcinfo->args[1].isnull = false;
+ locfcinfo->args[2].value = Int32GetDatum(-1);
+ locfcinfo->args[2].isnull = false;
- result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo));
+ result = (int2vector *) DatumGetPointer(array_recv(locfcinfo));
- Assert(!locfcinfo.isnull);
+ Assert(!locfcinfo->isnull);
/* sanity checks: int2vector must be 1-D, 0-based, no nulls */
if (ARR_NDIM(result) != 1 ||
Datum
oidvectorrecv(PG_FUNCTION_ARGS)
{
+ LOCAL_FCINFO(locfcinfo, 3);
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
- FunctionCallInfoData locfcinfo;
oidvector *result;
/*
* fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
* parameter.
*/
- InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
+ InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3,
InvalidOid, NULL, NULL);
- locfcinfo.arg[0] = PointerGetDatum(buf);
- locfcinfo.arg[1] = ObjectIdGetDatum(OIDOID);
- locfcinfo.arg[2] = Int32GetDatum(-1);
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.argnull[2] = false;
+ locfcinfo->args[0].value = PointerGetDatum(buf);
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = ObjectIdGetDatum(OIDOID);
+ locfcinfo->args[1].isnull = false;
+ locfcinfo->args[2].value = Int32GetDatum(-1);
+ locfcinfo->args[2].isnull = false;
- result = (oidvector *) DatumGetPointer(array_recv(&locfcinfo));
+ result = (oidvector *) DatumGetPointer(array_recv(locfcinfo));
- Assert(!locfcinfo.isnull);
+ Assert(!locfcinfo->isnull);
/* sanity checks: oidvector must be 1-D, 0-based, no nulls */
if (ARR_NDIM(result) != 1 ||
*/
if (!nulls1[i1] || !nulls2[i2])
{
- FunctionCallInfoData locfcinfo;
+ LOCAL_FCINFO(locfcinfo, 2);
int32 cmpresult;
if (nulls1[i1])
}
/* Compare the pair of elements */
- InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
+ InitFunctionCallInfoData(*locfcinfo, &typentry->cmp_proc_finfo, 2,
collation, NULL, NULL);
- locfcinfo.arg[0] = values1[i1];
- locfcinfo.arg[1] = values2[i2];
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.isnull = false;
- cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
+ locfcinfo->args[0].value = values1[i1];
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = values2[i2];
+ locfcinfo->args[1].isnull = false;
+ locfcinfo->isnull = false;
+ cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo));
if (cmpresult < 0)
{
i1 = i2 = j = 0;
while (i1 < ncolumns1 || i2 < ncolumns2)
{
+ LOCAL_FCINFO(locfcinfo, 2);
Form_pg_attribute att1;
Form_pg_attribute att2;
TypeCacheEntry *typentry;
Oid collation;
- FunctionCallInfoData locfcinfo;
bool oprresult;
/*
}
/* Compare the pair of elements */
- InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
+ InitFunctionCallInfoData(*locfcinfo, &typentry->eq_opr_finfo, 2,
collation, NULL, NULL);
- locfcinfo.arg[0] = values1[i1];
- locfcinfo.arg[1] = values2[i2];
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.isnull = false;
- oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
+ locfcinfo->args[0].value = values1[i1];
+ locfcinfo->args[0].isnull = false;
+ locfcinfo->args[1].value = values2[i2];
+ locfcinfo->args[1].isnull = false;
+ locfcinfo->isnull = false;
+ oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo));
if (!oprresult)
{
result = false;
to extract parse-time knowledge about the actual arguments. Note that this
field really is information about the arguments rather than information
about the function, but it's proven to be more convenient to keep it in
-FmgrInfo than in FunctionCallInfoData where it might more logically go.
+FmgrInfo than in FunctionCallInfoBaseData where it might more logically go.
During a call of a function, the following data structure is created
Oid fncollation; /* collation for function to use */
bool isnull; /* function must set true if result is NULL */
short nargs; /* # arguments actually passed */
- Datum arg[FUNC_MAX_ARGS]; /* Arguments passed to function */
- bool argnull[FUNC_MAX_ARGS]; /* T if arg[i] is actually NULL */
-} FunctionCallInfoData;
-typedef FunctionCallInfoData* FunctionCallInfo;
+ NullableDatum args[]; /* Arguments passed to function */
+} FunctionCallInfoBaseData;
+typedef FunctionCallInfoBaseData* FunctionCallInfo;
flinfo points to the lookup info used to make the call. Ordinary functions
will probably ignore this field, but function class handlers will need it
collation. This is effectively a hidden additional argument, which
collation-sensitive functions can use to determine their behavior.
-nargs, arg[], and argnull[] hold the arguments being passed to the function.
+nargs and args[] hold the arguments being passed to the function.
Notice that all the arguments passed to a function (as well as its result
value) will now uniformly be of type Datum. As discussed below, callers
and callees should apply the standard Datum-to-and-from-whatever macros
to convert to the actual argument types of a particular function. The
-value in arg[i] is unspecified when argnull[i] is true.
+value in args[i].value is unspecified when args[i].isnull is true.
It is generally the responsibility of the caller to ensure that the
number of arguments passed matches what the callee is expecting; except
for callees that take a variable number of arguments, the callee will
-typically ignore the nargs field and just grab values from arg[].
+typically ignore the nargs field and just grab values from args[].
The isnull field will be initialized to "false" before the call. On
return from the function, isnull is the null flag for the function result:
if it is true the function's result is NULL, regardless of the actual
function return value. Note that simple "strict" functions can ignore
-both isnull and argnull[], since they won't even get called when there
-are any TRUE values in argnull[].
+both isnull and args[i].isnull, since they won't even get called when there
+are any TRUE values in args[].isnull.
FunctionCallInfo replaces FmgrValues plus a bunch of ad-hoc parameter
conventions, global variables (fmgr_pl_finfo and CurrentTriggerData at
A nonstrict function is responsible for checking whether each individual
argument is null or not, which it can do with PG_ARGISNULL(n) (which is
-just "fcinfo->argnull[n]"). It should avoid trying to fetch the value
+just "fcinfo->args[n].isnull"). It should avoid trying to fetch the value
of any argument that is null.
Both strict and nonstrict functions can return NULL, if needed, with
For float4, float8, and int8, the PG_GETARG macros will hide whether the
types are pass-by-value or pass-by-reference. For example, if float8 is
pass-by-reference then PG_GETARG_FLOAT8 expands to
- (* (float8 *) DatumGetPointer(fcinfo->arg[number]))
+ (* (float8 *) DatumGetPointer(fcinfo->args[number].value))
and would typically be called like this:
float8 arg = PG_GETARG_FLOAT8(0);
For what are now historical reasons, the float-related typedefs and macros
Datum
DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 1);
Datum result;
- InitFunctionCallInfoData(fcinfo, NULL, 1, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, NULL, 1, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.argnull[0] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
- result = (*func) (&fcinfo);
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
Datum
DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 2);
Datum result;
- InitFunctionCallInfoData(fcinfo, NULL, 2, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, NULL, 2, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
- result = (*func) (&fcinfo);
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
Datum arg3)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 3);
Datum result;
- InitFunctionCallInfoData(fcinfo, NULL, 3, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, NULL, 3, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
- result = (*func) (&fcinfo);
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
Datum arg3, Datum arg4)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 4);
Datum result;
- InitFunctionCallInfoData(fcinfo, NULL, 4, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, NULL, 4, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
- result = (*func) (&fcinfo);
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 5);
Datum result;
- InitFunctionCallInfoData(fcinfo, NULL, 5, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, NULL, 5, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
+ fcinfo->args[4].value = arg5;
+ fcinfo->args[4].isnull = false;
- result = (*func) (&fcinfo);
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
Datum arg3, Datum arg4, Datum arg5,
Datum arg6)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 6);
Datum result;
- InitFunctionCallInfoData(fcinfo, NULL, 6, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, NULL, 6, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
+ fcinfo->args[4].value = arg5;
+ fcinfo->args[4].isnull = false;
+ fcinfo->args[5].value = arg6;
+ fcinfo->args[5].isnull = false;
- result = (*func) (&fcinfo);
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 7);
Datum result;
- InitFunctionCallInfoData(fcinfo, NULL, 7, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.arg[6] = arg7;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
- fcinfo.argnull[6] = false;
-
- result = (*func) (&fcinfo);
+ InitFunctionCallInfoData(*fcinfo, NULL, 7, collation, NULL, NULL);
+
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
+ fcinfo->args[4].value = arg5;
+ fcinfo->args[4].isnull = false;
+ fcinfo->args[5].value = arg6;
+ fcinfo->args[5].isnull = false;
+ fcinfo->args[6].value = arg7;
+ fcinfo->args[6].isnull = false;
+
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 8);
Datum result;
- InitFunctionCallInfoData(fcinfo, NULL, 8, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.arg[6] = arg7;
- fcinfo.arg[7] = arg8;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
- fcinfo.argnull[6] = false;
- fcinfo.argnull[7] = false;
-
- result = (*func) (&fcinfo);
+ InitFunctionCallInfoData(*fcinfo, NULL, 8, collation, NULL, NULL);
+
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
+ fcinfo->args[4].value = arg5;
+ fcinfo->args[4].isnull = false;
+ fcinfo->args[5].value = arg6;
+ fcinfo->args[5].isnull = false;
+ fcinfo->args[6].value = arg7;
+ fcinfo->args[6].isnull = false;
+ fcinfo->args[7].value = arg8;
+ fcinfo->args[7].isnull = false;
+
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
Datum arg6, Datum arg7, Datum arg8,
Datum arg9)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 9);
Datum result;
- InitFunctionCallInfoData(fcinfo, NULL, 9, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.arg[6] = arg7;
- fcinfo.arg[7] = arg8;
- fcinfo.arg[8] = arg9;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
- fcinfo.argnull[6] = false;
- fcinfo.argnull[7] = false;
- fcinfo.argnull[8] = false;
-
- result = (*func) (&fcinfo);
+ InitFunctionCallInfoData(*fcinfo, NULL, 9, collation, NULL, NULL);
+
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
+ fcinfo->args[4].value = arg5;
+ fcinfo->args[4].isnull = false;
+ fcinfo->args[5].value = arg6;
+ fcinfo->args[5].isnull = false;
+ fcinfo->args[6].value = arg7;
+ fcinfo->args[6].isnull = false;
+ fcinfo->args[7].value = arg8;
+ fcinfo->args[7].isnull = false;
+ fcinfo->args[8].value = arg9;
+ fcinfo->args[8].isnull = false;
+
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
Datum
CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 1);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 1, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.argnull[0] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
- result = (*func) (&fcinfo);
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
Datum
CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 2);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 2, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
- result = (*func) (&fcinfo);
+ result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
* directly-computed parameter list. Note that neither arguments nor result
* are allowed to be NULL.
*/
+Datum
+FunctionCall0Coll(FmgrInfo *flinfo, Oid collation)
+{
+ LOCAL_FCINFO(fcinfo, 0);
+ Datum result;
+
+ InitFunctionCallInfoData(*fcinfo, flinfo, 0, collation, NULL, NULL);
+
+ result = FunctionCallInvoke(fcinfo);
+
+ /* Check for null result, since caller is clearly not expecting one */
+ if (fcinfo->isnull)
+ elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
+
+ return result;
+}
+
Datum
FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 1);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 1, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.argnull[0] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
- result = FunctionCallInvoke(&fcinfo);
+ result = FunctionCallInvoke(fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+ if (fcinfo->isnull)
+ elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
return result;
}
Datum
FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 2);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 2, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
- result = FunctionCallInvoke(&fcinfo);
+ result = FunctionCallInvoke(fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+ if (fcinfo->isnull)
+ elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
return result;
}
FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
Datum arg3)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 3);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 3, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 3, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
- result = FunctionCallInvoke(&fcinfo);
+ result = FunctionCallInvoke(fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+ if (fcinfo->isnull)
+ elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
return result;
}
FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
Datum arg3, Datum arg4)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 4);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 4, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 4, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
- result = FunctionCallInvoke(&fcinfo);
+ result = FunctionCallInvoke(fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+ if (fcinfo->isnull)
+ elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
return result;
}
FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 5);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 5, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 5, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
+ fcinfo->args[4].value = arg5;
+ fcinfo->args[4].isnull = false;
- result = FunctionCallInvoke(&fcinfo);
+ result = FunctionCallInvoke(fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+ if (fcinfo->isnull)
+ elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
return result;
}
Datum arg3, Datum arg4, Datum arg5,
Datum arg6)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 6);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 6, collation, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 6, collation, NULL, NULL);
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
+ fcinfo->args[4].value = arg5;
+ fcinfo->args[4].isnull = false;
+ fcinfo->args[5].value = arg6;
+ fcinfo->args[5].isnull = false;
- result = FunctionCallInvoke(&fcinfo);
+ result = FunctionCallInvoke(fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+ if (fcinfo->isnull)
+ elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
return result;
}
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 7);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 7, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.arg[6] = arg7;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
- fcinfo.argnull[6] = false;
-
- result = FunctionCallInvoke(&fcinfo);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 7, collation, NULL, NULL);
+
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
+ fcinfo->args[4].value = arg5;
+ fcinfo->args[4].isnull = false;
+ fcinfo->args[5].value = arg6;
+ fcinfo->args[5].isnull = false;
+ fcinfo->args[6].value = arg7;
+ fcinfo->args[6].isnull = false;
+
+ result = FunctionCallInvoke(fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+ if (fcinfo->isnull)
+ elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
return result;
}
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 8);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 8, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.arg[6] = arg7;
- fcinfo.arg[7] = arg8;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
- fcinfo.argnull[6] = false;
- fcinfo.argnull[7] = false;
-
- result = FunctionCallInvoke(&fcinfo);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 8, collation, NULL, NULL);
+
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
+ fcinfo->args[4].value = arg5;
+ fcinfo->args[4].isnull = false;
+ fcinfo->args[5].value = arg6;
+ fcinfo->args[5].isnull = false;
+ fcinfo->args[6].value = arg7;
+ fcinfo->args[6].isnull = false;
+ fcinfo->args[7].value = arg8;
+ fcinfo->args[7].isnull = false;
+
+ result = FunctionCallInvoke(fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+ if (fcinfo->isnull)
+ elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
return result;
}
Datum arg6, Datum arg7, Datum arg8,
Datum arg9)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 9);
Datum result;
- InitFunctionCallInfoData(fcinfo, flinfo, 9, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.arg[6] = arg7;
- fcinfo.arg[7] = arg8;
- fcinfo.arg[8] = arg9;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
- fcinfo.argnull[6] = false;
- fcinfo.argnull[7] = false;
- fcinfo.argnull[8] = false;
-
- result = FunctionCallInvoke(&fcinfo);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 9, collation, NULL, NULL);
+
+ fcinfo->args[0].value = arg1;
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = arg2;
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = arg3;
+ fcinfo->args[2].isnull = false;
+ fcinfo->args[3].value = arg4;
+ fcinfo->args[3].isnull = false;
+ fcinfo->args[4].value = arg5;
+ fcinfo->args[4].isnull = false;
+ fcinfo->args[5].value = arg6;
+ fcinfo->args[5].isnull = false;
+ fcinfo->args[6].value = arg7;
+ fcinfo->args[6].isnull = false;
+ fcinfo->args[7].value = arg8;
+ fcinfo->args[7].isnull = false;
+ fcinfo->args[8].value = arg9;
+ fcinfo->args[8].isnull = false;
+
+ result = FunctionCallInvoke(fcinfo);
/* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+ if (fcinfo->isnull)
+ elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
return result;
}
OidFunctionCall0Coll(Oid functionId, Oid collation)
{
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
- Datum result;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 0, collation, NULL, NULL);
-
- result = FunctionCallInvoke(&fcinfo);
-
- /* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
- return result;
+ return FunctionCall0Coll(&flinfo, collation);
}
Datum
OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
{
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
- Datum result;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 1, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.argnull[0] = false;
-
- result = FunctionCallInvoke(&fcinfo);
-
- /* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
- return result;
+ return FunctionCall1Coll(&flinfo, collation, arg1);
}
Datum
OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2)
{
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
- Datum result;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 2, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
-
- result = FunctionCallInvoke(&fcinfo);
-
- /* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
- return result;
+ return FunctionCall2Coll(&flinfo, collation, arg1, arg2);
}
Datum
Datum arg3)
{
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
- Datum result;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 3, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
-
- result = FunctionCallInvoke(&fcinfo);
-
- /* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
- return result;
+ return FunctionCall3Coll(&flinfo, collation, arg1, arg2, arg3);
}
Datum
Datum arg3, Datum arg4)
{
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
- Datum result;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 4, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
-
- result = FunctionCallInvoke(&fcinfo);
-
- /* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
- return result;
+ return FunctionCall4Coll(&flinfo, collation, arg1, arg2, arg3, arg4);
}
Datum
Datum arg3, Datum arg4, Datum arg5)
{
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
- Datum result;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 5, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
-
- result = FunctionCallInvoke(&fcinfo);
-
- /* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
- return result;
+ return FunctionCall5Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5);
}
Datum
Datum arg6)
{
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
- Datum result;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 6, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
-
- result = FunctionCallInvoke(&fcinfo);
-
- /* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
- return result;
+ return FunctionCall6Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
+ arg6);
}
Datum
Datum arg6, Datum arg7)
{
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
- Datum result;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 7, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.arg[6] = arg7;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
- fcinfo.argnull[6] = false;
-
- result = FunctionCallInvoke(&fcinfo);
-
- /* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
- return result;
+ return FunctionCall7Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
+ arg6, arg7);
}
Datum
Datum arg6, Datum arg7, Datum arg8)
{
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
- Datum result;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 8, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.arg[6] = arg7;
- fcinfo.arg[7] = arg8;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
- fcinfo.argnull[6] = false;
- fcinfo.argnull[7] = false;
-
- result = FunctionCallInvoke(&fcinfo);
-
- /* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
- return result;
+ return FunctionCall8Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
+ arg6, arg7, arg8);
}
Datum
Datum arg9)
{
FmgrInfo flinfo;
- FunctionCallInfoData fcinfo;
- Datum result;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 9, collation, NULL, NULL);
-
- fcinfo.arg[0] = arg1;
- fcinfo.arg[1] = arg2;
- fcinfo.arg[2] = arg3;
- fcinfo.arg[3] = arg4;
- fcinfo.arg[4] = arg5;
- fcinfo.arg[5] = arg6;
- fcinfo.arg[6] = arg7;
- fcinfo.arg[7] = arg8;
- fcinfo.arg[8] = arg9;
- fcinfo.argnull[0] = false;
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
- fcinfo.argnull[3] = false;
- fcinfo.argnull[4] = false;
- fcinfo.argnull[5] = false;
- fcinfo.argnull[6] = false;
- fcinfo.argnull[7] = false;
- fcinfo.argnull[8] = false;
-
- result = FunctionCallInvoke(&fcinfo);
-
- /* Check for null result, since caller is clearly not expecting one */
- if (fcinfo.isnull)
- elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
- return result;
+ return FunctionCall9Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
+ arg6, arg7, arg8, arg9);
}
Datum
InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 3);
Datum result;
if (str == NULL && flinfo->fn_strict)
return (Datum) 0; /* just return null result */
- InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
- fcinfo.arg[0] = CStringGetDatum(str);
- fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
- fcinfo.arg[2] = Int32GetDatum(typmod);
- fcinfo.argnull[0] = (str == NULL);
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
+ fcinfo->args[0].value = CStringGetDatum(str);
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = Int32GetDatum(typmod);
+ fcinfo->args[2].isnull = false;
- result = FunctionCallInvoke(&fcinfo);
+ result = FunctionCallInvoke(fcinfo);
/* Should get null result if and only if str is NULL */
if (str == NULL)
{
- if (!fcinfo.isnull)
+ if (!fcinfo->isnull)
elog(ERROR, "input function %u returned non-NULL",
- fcinfo.flinfo->fn_oid);
+ flinfo->fn_oid);
}
else
{
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "input function %u returned NULL",
- fcinfo.flinfo->fn_oid);
+ flinfo->fn_oid);
}
return result;
ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
Oid typioparam, int32 typmod)
{
- FunctionCallInfoData fcinfo;
+ LOCAL_FCINFO(fcinfo, 3);
Datum result;
if (buf == NULL && flinfo->fn_strict)
return (Datum) 0; /* just return null result */
- InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
+ InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
- fcinfo.arg[0] = PointerGetDatum(buf);
- fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
- fcinfo.arg[2] = Int32GetDatum(typmod);
- fcinfo.argnull[0] = (buf == NULL);
- fcinfo.argnull[1] = false;
- fcinfo.argnull[2] = false;
+ fcinfo->args[0].value = PointerGetDatum(buf);
+ fcinfo->args[0].isnull = false;
+ fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
+ fcinfo->args[1].isnull = false;
+ fcinfo->args[2].value = Int32GetDatum(typmod);
+ fcinfo->args[2].isnull = false;
- result = FunctionCallInvoke(&fcinfo);
+ result = FunctionCallInvoke(fcinfo);
/* Should get null result if and only if buf is NULL */
if (buf == NULL)
{
- if (!fcinfo.isnull)
+ if (!fcinfo->isnull)
elog(ERROR, "receive function %u returned non-NULL",
- fcinfo.flinfo->fn_oid);
+ flinfo->fn_oid);
}
else
{
- if (fcinfo.isnull)
+ if (fcinfo->isnull)
elog(ERROR, "receive function %u returned NULL",
- fcinfo.flinfo->fn_oid);
+ flinfo->fn_oid);
}
return result;
/* Info needed to use an old-style comparison function as a sort comparator */
typedef struct
{
- FunctionCallInfoData fcinfo; /* reusable callinfo structure */
FmgrInfo flinfo; /* lookup data for comparison function */
+ FunctionCallInfoBaseData fcinfo; /* reusable callinfo structure */
} SortShimExtra;
+#define SizeForSortShimExtra(nargs) (offsetof(SortShimExtra, fcinfo) + SizeForFunctionCallInfo(nargs))
/*
* Shim function for calling an old-style comparator
*
* This is essentially an inlined version of FunctionCall2Coll(), except
- * we assume that the FunctionCallInfoData was already mostly set up by
+ * we assume that the FunctionCallInfoBaseData was already mostly set up by
* PrepareSortSupportComparisonShim.
*/
static int
SortShimExtra *extra = (SortShimExtra *) ssup->ssup_extra;
Datum result;
- extra->fcinfo.arg[0] = x;
- extra->fcinfo.arg[1] = y;
+ extra->fcinfo.args[0].value = x;
+ extra->fcinfo.args[1].value = y;
/* just for paranoia's sake, we reset isnull each time */
extra->fcinfo.isnull = false;
SortShimExtra *extra;
extra = (SortShimExtra *) MemoryContextAlloc(ssup->ssup_cxt,
- sizeof(SortShimExtra));
+ SizeForSortShimExtra(2));
/* Lookup the comparison function */
fmgr_info_cxt(cmpFunc, &extra->flinfo, ssup->ssup_cxt);
/* We can initialize the callinfo just once and re-use it */
InitFunctionCallInfoData(extra->fcinfo, &extra->flinfo, 2,
ssup->ssup_collation, NULL, NULL);
- extra->fcinfo.argnull[0] = false;
- extra->fcinfo.argnull[1] = false;
+ extra->fcinfo.args[0].isnull = false;
+ extra->fcinfo.args[1].isnull = false;
ssup->ssup_extra = extra;
ssup->comparator = comparison_shim;
/* aggregation related nodes */
EEOP_AGG_STRICT_DESERIALIZE,
EEOP_AGG_DESERIALIZE,
- EEOP_AGG_STRICT_INPUT_CHECK,
+ EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
+ EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
EEOP_AGG_INIT_TRANS,
EEOP_AGG_STRICT_TRANS_CHECK,
EEOP_AGG_PLAIN_TRANS_BYVAL,
int jumpnull;
} agg_deserialize;
- /* for EEOP_AGG_STRICT_INPUT_CHECK */
- struct
- {
+ /* for EEOP_AGG_STRICT_INPUT_CHECK_NULLS / STRICT_INPUT_CHECK_ARGS */
+ struct
+ {
+ /*
+ * For EEOP_AGG_STRICT_INPUT_CHECK_ARGS args contains pointers to
+ * the NullableDatums that need to be checked for NULLs.
+ *
+ * For EEOP_AGG_STRICT_INPUT_CHECK_NULLS nulls contains pointers
+ * to booleans that need to be checked for NULLs.
+ *
+ * Both cases currently need to exist because sometimes the
+ * to-be-checked nulls are in TupleTableSlot.isnull array, and
+ * sometimes in FunctionCallInfoBaseData.args[i].isnull.
+ */
+ NullableDatum *args;
bool *nulls;
int nargs;
int jumpnull;
* re-initializing the unchanging fields; which isn't much, but it seems
* worth the extra space consumption.
*/
- FunctionCallInfoData transfn_fcinfo;
+ FunctionCallInfo transfn_fcinfo;
/* Likewise for serialization and deserialization functions */
- FunctionCallInfoData serialfn_fcinfo;
+ FunctionCallInfo serialfn_fcinfo;
- FunctionCallInfoData deserialfn_fcinfo;
+ FunctionCallInfo deserialfn_fcinfo;
} AggStatePerTransData;
/*
* signature.)
*/
-typedef struct FunctionCallInfoData *FunctionCallInfo;
+typedef struct FunctionCallInfoBaseData *FunctionCallInfo;
typedef Datum (*PGFunction) (FunctionCallInfo fcinfo);
* info struct saved for re-use.
*
* Note that fn_expr really is parse-time-determined information about the
- * arguments, rather than about the function itself. But it's convenient
- * to store it here rather than in FunctionCallInfoData, where it might more
+ * arguments, rather than about the function itself. But it's convenient to
+ * store it here rather than in FunctionCallInfoBaseData, where it might more
* logically belong.
*
* fn_extra is available for use by the called function; all other fields
* fields in whatever resultinfo points to. It should not change any other
* fields. (In particular, scribbling on the argument arrays is a bad idea,
* since some callers assume they can re-call with the same arguments.)
+ *
+ * Note that enough space for arguments needs to be provided, either by using
+ * SizeForFunctionCallInfo() in dynamic allocations, or by using
+ * LOCAL_FCINFO() for on-stack allocations.
+ *
+ * This struct is named *BaseData, rather than *Data, to break pre v12 code
+ * that allocated FunctionCallInfoData itself, as it'd often silently break
+ * old code due to no space for arguments being provided.
*/
-typedef struct FunctionCallInfoData
+typedef struct FunctionCallInfoBaseData
{
FmgrInfo *flinfo; /* ptr to lookup info used for this call */
fmNodePtr context; /* pass info about context of call */
#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL 4
bool isnull; /* function must set true if result is NULL */
short nargs; /* # arguments actually passed */
-#define FIELDNO_FUNCTIONCALLINFODATA_ARG 6
- Datum arg[FUNC_MAX_ARGS]; /* Arguments passed to function */
-#define FIELDNO_FUNCTIONCALLINFODATA_ARGNULL 7
- bool argnull[FUNC_MAX_ARGS]; /* T if arg[i] is actually NULL */
-} FunctionCallInfoData;
+#define FIELDNO_FUNCTIONCALLINFODATA_ARGS 6
+ NullableDatum args[FLEXIBLE_ARRAY_MEMBER];
+} FunctionCallInfoBaseData;
+
+/*
+ * Space needed for for a FunctionCallInfoBaseData struct with sufficient space
+ * for `nargs` arguments.
+ */
+#define SizeForFunctionCallInfo(nargs) \
+ (offsetof(FunctionCallInfoBaseData, args) + \
+ sizeof(NullableDatum) * (nargs))
+
+/*
+ * This macro ensures that `name` points to a stack-allocated
+ * FunctionCallInfoBaseData struct with sufficient space for `nargs` arguments.
+ */
+#define LOCAL_FCINFO(name, nargs) \
+ /* use union with FunctionCallInfoBaseData to guarantee alignment */ \
+ union \
+ { \
+ FunctionCallInfoBaseData fcinfo; \
+ /* ensure enough space for nargs args is available */ \
+ char fcinfo_data[SizeForFunctionCallInfo(nargs)]; \
+ } name##data; \
+ FunctionCallInfo name = &name##data.fcinfo
/*
* This routine fills a FmgrInfo struct, given the OID
extern void fmgr_symbol(Oid functionId, char **mod, char **fn);
/*
- * This macro initializes all the fields of a FunctionCallInfoData except
- * for the arg[] and argnull[] arrays. Performance testing has shown that
- * the fastest way to set up argnull[] for small numbers of arguments is to
- * explicitly set each required element to false, so we don't try to zero
- * out the argnull[] array in the macro.
+ * This macro initializes all the fields of a FunctionCallInfoBaseData except
+ * for the args[] array.
*/
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo) \
do { \
} while (0)
/*
- * This macro invokes a function given a filled-in FunctionCallInfoData
+ * This macro invokes a function given a filled-in FunctionCallInfoBaseData
* struct. The macro result is the returned Datum --- but note that
* caller must still check fcinfo->isnull! Also, if function is strict,
* it is caller's responsibility to verify that no null arguments are present
* If function is not marked "proisstrict" in pg_proc, it must check for
* null arguments using this macro. Do not try to GETARG a null argument!
*/
-#define PG_ARGISNULL(n) (fcinfo->argnull[n])
+#define PG_ARGISNULL(n) (fcinfo->args[n].isnull)
/*
* Support for fetching detoasted copies of toastable datatypes (all of
/* Macros for fetching arguments of standard types */
-#define PG_GETARG_DATUM(n) (fcinfo->arg[n])
+#define PG_GETARG_DATUM(n) (fcinfo->args[n].value)
#define PG_GETARG_INT32(n) DatumGetInt32(PG_GETARG_DATUM(n))
#define PG_GETARG_UINT32(n) DatumGetUInt32(PG_GETARG_DATUM(n))
#define PG_GETARG_INT16(n) DatumGetInt16(PG_GETARG_DATUM(n))
* directly-computed parameter list. Note that neither arguments nor result
* are allowed to be NULL.
*/
+extern Datum FunctionCall0Coll(FmgrInfo *flinfo, Oid collation);
extern Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation,
Datum arg1);
extern Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation,
extern LLVMTypeRef TypeSizeT;
extern LLVMTypeRef TypeStorageBool;
+extern LLVMTypeRef StructNullableDatum;
extern LLVMTypeRef StructTupleDescData;
extern LLVMTypeRef StructHeapTupleData;
extern LLVMTypeRef StructTupleTableSlot;
return ret;
}
+
+/*
+ * Return pointer to the the argno'th argument nullness.
+ */
+static inline LLVMValueRef
+l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+{
+ LLVMValueRef v_args;
+ LLVMValueRef v_argn;
+
+ v_args = LLVMBuildStructGEP(b,
+ v_fcinfo,
+ FIELDNO_FUNCTIONCALLINFODATA_ARGS,
+ "");
+ v_argn = LLVMBuildStructGEP(b, v_args, argno, "");
+
+ return LLVMBuildStructGEP(b, v_argn, FIELDNO_NULLABLE_DATUM_ISNULL, "");
+}
+
+/*
+ * Return pointer to the the argno'th argument datum.
+ */
+static inline LLVMValueRef
+l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+{
+ LLVMValueRef v_args;
+ LLVMValueRef v_argn;
+
+ v_args = LLVMBuildStructGEP(b,
+ v_fcinfo,
+ FIELDNO_FUNCTIONCALLINFODATA_ARGS,
+ "");
+ v_argn = LLVMBuildStructGEP(b, v_args, argno, "");
+
+ return LLVMBuildStructGEP(b, v_argn, FIELDNO_NULLABLE_DATUM_DATUM, "");
+}
+
+/*
+ * Return argno'th argument nullness.
+ */
+static inline LLVMValueRef
+l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+{
+ return LLVMBuildLoad(b, l_funcnullp(b, v_fcinfo, argno), "");
+}
+
+/*
+ * Return argno'th argument datum.
+ */
+static inline LLVMValueRef
+l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+{
+ return LLVMBuildLoad(b, l_funcvaluep(b, v_fcinfo, argno), "");
+}
+
#endif
* (by InitFunctionCallInfoData) if func.fn_oid is valid. It also saves
* argument values between calls, when setArgsValid is true.
*/
- FunctionCallInfoData fcinfo_data;
+ FunctionCallInfo fcinfo;
} SetExprState;
/* ----------------
extern void pgstat_count_truncate(Relation rel);
extern void pgstat_update_heap_dead_tuples(Relation rel, int delta);
-extern void pgstat_init_function_usage(FunctionCallInfoData *fcinfo,
+extern void pgstat_init_function_usage(FunctionCallInfo fcinfo,
PgStat_FunctionCallUsage *fcu);
extern void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu,
bool finalize);
typedef uintptr_t Datum;
+/*
+ * A NullableDatum is used in places where both a Datum and its nullness needs
+ * to be stored. This can be more efficient than storing datums and nullness
+ * in separate arrays, due to better spatial locality, even if more space may
+ * be wasted due to padding.
+ */
+typedef struct NullableDatum
+{
+#define FIELDNO_NULLABLE_DATUM_DATUM 0
+ Datum value;
+#define FIELDNO_NULLABLE_DATUM_ISNULL 1
+ bool isnull;
+ /* due to alignment padding this could be used for flags for free */
+} NullableDatum;
+
#define SIZEOF_DATUM SIZEOF_VOID_P
/*
Datum
plperl_inline_handler(PG_FUNCTION_ARGS)
{
+ LOCAL_FCINFO(fake_fcinfo, 0);
InlineCodeBlock *codeblock = (InlineCodeBlock *) PG_GETARG_POINTER(0);
- FunctionCallInfoData fake_fcinfo;
FmgrInfo flinfo;
plperl_proc_desc desc;
plperl_call_data *volatile save_call_data = current_call_data;
* plperl_call_perl_func(). In particular note that this sets things up
* with no arguments passed, and a result type of VOID.
*/
- MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
+ MemSet(fake_fcinfo, 0, SizeForFunctionCallInfo(0));
MemSet(&flinfo, 0, sizeof(flinfo));
MemSet(&desc, 0, sizeof(desc));
- fake_fcinfo.flinfo = &flinfo;
+ fake_fcinfo->flinfo = &flinfo;
flinfo.fn_oid = InvalidOid;
flinfo.fn_mcxt = CurrentMemoryContext;
desc.nargs = 0;
desc.reference = NULL;
- this_call_data.fcinfo = &fake_fcinfo;
+ this_call_data.fcinfo = fake_fcinfo;
this_call_data.prodesc = &desc;
/* we do not bother with refcounting the fake prodesc */
if (!desc.reference) /* can this happen? */
elog(ERROR, "could not create internal procedure for anonymous code block");
- perlret = plperl_call_perl_func(&desc, &fake_fcinfo);
+ perlret = plperl_call_perl_func(&desc, fake_fcinfo);
SvREFCNT_dec_current(perlret);
for (i = 0; i < desc->nargs; i++)
{
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
PUSHs(&PL_sv_undef);
else if (desc->arg_is_rowtype[i])
{
- SV *sv = plperl_hash_from_datum(fcinfo->arg[i]);
+ SV *sv = plperl_hash_from_datum(fcinfo->args[i].value);
PUSHs(sv_2mortal(sv));
}
Oid funcid;
if (OidIsValid(desc->arg_arraytype[i]))
- sv = plperl_ref_from_pg_array(fcinfo->arg[i], desc->arg_arraytype[i]);
+ sv = plperl_ref_from_pg_array(fcinfo->args[i].value, desc->arg_arraytype[i]);
else if ((funcid = get_transform_fromsql(argtypes[i], current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes)))
- sv = (SV *) DatumGetPointer(OidFunctionCall1(funcid, fcinfo->arg[i]));
+ sv = (SV *) DatumGetPointer(OidFunctionCall1(funcid, fcinfo->args[i].value));
else
{
char *tmp;
tmp = OutputFunctionCall(&(desc->arg_out_func[i]),
- fcinfo->arg[i]);
+ fcinfo->args[i].value);
sv = cstr2sv(tmp);
pfree(tmp);
}
PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
assign_simple_var(&estate, var,
- fcinfo->arg[i],
- fcinfo->argnull[i],
+ fcinfo->args[i].value,
+ fcinfo->args[i].isnull,
false);
/*
{
PLpgSQL_rec *rec = (PLpgSQL_rec *) estate.datums[n];
- if (!fcinfo->argnull[i])
+ if (!fcinfo->args[i].isnull)
{
/* Assign row value from composite datum */
exec_move_row_from_datum(&estate,
(PLpgSQL_variable *) rec,
- fcinfo->arg[i]);
+ fcinfo->args[i].value);
}
else
{
Datum
plpgsql_inline_handler(PG_FUNCTION_ARGS)
{
+ LOCAL_FCINFO(fake_fcinfo, 0);
InlineCodeBlock *codeblock = castNode(InlineCodeBlock, DatumGetPointer(PG_GETARG_DATUM(0)));
PLpgSQL_function *func;
- FunctionCallInfoData fake_fcinfo;
FmgrInfo flinfo;
EState *simple_eval_estate;
Datum retval;
* plpgsql_exec_function(). In particular note that this sets things up
* with no arguments passed.
*/
- MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
+ MemSet(fake_fcinfo, 0, SizeForFunctionCallInfo(0));
MemSet(&flinfo, 0, sizeof(flinfo));
- fake_fcinfo.flinfo = &flinfo;
+ fake_fcinfo->flinfo = &flinfo;
flinfo.fn_oid = InvalidOid;
flinfo.fn_mcxt = CurrentMemoryContext;
/* And run the function */
PG_TRY();
{
- retval = plpgsql_exec_function(func, &fake_fcinfo, simple_eval_estate, codeblock->atomic);
+ retval = plpgsql_exec_function(func, fake_fcinfo, simple_eval_estate, codeblock->atomic);
}
PG_CATCH();
{
/* Postpone body checks if !check_function_bodies */
if (check_function_bodies)
{
- FunctionCallInfoData fake_fcinfo;
+ LOCAL_FCINFO(fake_fcinfo, 0);
FmgrInfo flinfo;
int rc;
TriggerData trigdata;
* Set up a fake fcinfo with just enough info to satisfy
* plpgsql_compile().
*/
- MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
+ MemSet(fake_fcinfo, 0, SizeForFunctionCallInfo(0));
MemSet(&flinfo, 0, sizeof(flinfo));
- fake_fcinfo.flinfo = &flinfo;
+ fake_fcinfo->flinfo = &flinfo;
flinfo.fn_oid = funcoid;
flinfo.fn_mcxt = CurrentMemoryContext;
if (is_dml_trigger)
{
MemSet(&trigdata, 0, sizeof(trigdata));
trigdata.type = T_TriggerData;
- fake_fcinfo.context = (Node *) &trigdata;
+ fake_fcinfo->context = (Node *) &trigdata;
}
else if (is_event_trigger)
{
MemSet(&etrigdata, 0, sizeof(etrigdata));
etrigdata.type = T_EventTriggerData;
- fake_fcinfo.context = (Node *) &etrigdata;
+ fake_fcinfo->context = (Node *) &etrigdata;
}
/* Test-compile the function */
- plpgsql_compile(&fake_fcinfo, true);
+ plpgsql_compile(fake_fcinfo, true);
/*
* Disconnect from SPI manager
{
PLyDatumToOb *arginfo = &proc->args[i];
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
arg = NULL;
else
- arg = PLy_input_convert(arginfo, fcinfo->arg[i]);
+ arg = PLy_input_convert(arginfo, fcinfo->args[i].value);
if (arg == NULL)
{
Datum
plpython_inline_handler(PG_FUNCTION_ARGS)
{
+ LOCAL_FCINFO(fake_fcinfo, 0);
InlineCodeBlock *codeblock = (InlineCodeBlock *) DatumGetPointer(PG_GETARG_DATUM(0));
- FunctionCallInfoData fake_fcinfo;
FmgrInfo flinfo;
PLyProcedure proc;
PLyExecutionContext *exec_ctx;
if (SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC) != SPI_OK_CONNECT)
elog(ERROR, "SPI_connect failed");
- MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
+ MemSet(fcinfo, 0, SizeForFunctionCallInfo(0));
MemSet(&flinfo, 0, sizeof(flinfo));
- fake_fcinfo.flinfo = &flinfo;
+ fake_fcinfo->flinfo = &flinfo;
flinfo.fn_oid = InvalidOid;
flinfo.fn_mcxt = CurrentMemoryContext;
PLy_procedure_compile(&proc, codeblock->source_text);
exec_ctx->curr_proc = &proc;
- PLy_exec_function(&fake_fcinfo, &proc);
+ PLy_exec_function(fake_fcinfo, &proc);
}
PG_CATCH();
{
static void
call_pltcl_start_proc(Oid prolang, bool pltrusted)
{
+ LOCAL_FCINFO(fcinfo, 0);
char *start_proc;
const char *gucname;
ErrorContextCallback errcallback;
Form_pg_proc procStruct;
AclResult aclresult;
FmgrInfo finfo;
- FunctionCallInfoData fcinfo;
PgStat_FunctionCallUsage fcusage;
/* select appropriate GUC */
*/
InvokeFunctionExecuteHook(procOid);
fmgr_info(procOid, &finfo);
- InitFunctionCallInfoData(fcinfo, &finfo,
+ InitFunctionCallInfoData(*fcinfo, &finfo,
0,
InvalidOid, NULL, NULL);
- pgstat_init_function_usage(&fcinfo, &fcusage);
- (void) FunctionCallInvoke(&fcinfo);
+ pgstat_init_function_usage(fcinfo, &fcusage);
+ (void) FunctionCallInvoke(fcinfo);
pgstat_end_function_usage(&fcusage, true);
/* Pop the error context stack */
/**************************************************
* For tuple values, add a list for 'array set ...'
**************************************************/
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
Tcl_ListObjAppendElement(NULL, tcl_cmd, Tcl_NewObj());
else
{
HeapTupleData tmptup;
Tcl_Obj *list_tmp;
- td = DatumGetHeapTupleHeader(fcinfo->arg[i]);
+ td = DatumGetHeapTupleHeader(fcinfo->args[i].value);
/* Extract rowtype info and find a tupdesc */
tupType = HeapTupleHeaderGetTypeId(td);
tupTypmod = HeapTupleHeaderGetTypMod(td);
* Single values are added as string element
* of their external representation
**************************************************/
- if (fcinfo->argnull[i])
+ if (fcinfo->args[i].isnull)
Tcl_ListObjAppendElement(NULL, tcl_cmd, Tcl_NewObj());
else
{
char *tmp;
tmp = OutputFunctionCall(&prodesc->arg_out_func[i],
- fcinfo->arg[i]);
+ fcinfo->args[i].value);
UTF_BEGIN;
Tcl_ListObjAppendElement(NULL, tcl_cmd,
Tcl_NewStringObj(UTF_E2U(tmp), -1));
FuncInfo
Function
FunctionCallInfo
-FunctionCallInfoData
+FunctionCallInfoBaseData
FunctionParameter
FunctionParameterMode
FunctionScan
Notification
NotifyStmt
Nsrt
+NullableDatum
NullIfExpr
NullTest
NullTestType