From: Andres Freund Date: Tue, 5 Jun 2018 10:24:31 -0700 Subject: [PATCH v2 1/2] Variable length FunctionCallInfoData. Author: Andres Freund Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/backend/commands/event_trigger.c | 8 +- src/backend/commands/functioncmds.c | 14 +- src/backend/commands/tablecmds.c | 8 +- src/backend/commands/trigger.c | 12 +- src/backend/executor/execExpr.c | 81 +-- src/backend/executor/execExprInterp.c | 127 ++-- src/backend/executor/execSRF.c | 39 +- src/backend/executor/functions.c | 4 +- src/backend/executor/nodeAgg.c | 74 +-- src/backend/executor/nodeWindowAgg.c | 65 +- src/backend/jit/llvm/llvmjit_expr.c | 20 +- src/backend/tcop/fastpath.c | 43 +- src/backend/utils/adt/arrayfuncs.c | 123 ++-- src/backend/utils/adt/int.c | 20 +- src/backend/utils/adt/oid.c | 20 +- src/backend/utils/adt/rowtypes.c | 32 +- src/backend/utils/fmgr/fmgr.c | 848 ++++++++++---------------- src/backend/utils/sort/sortsupport.c | 13 +- src/include/executor/execExpr.h | 6 +- src/include/executor/nodeAgg.h | 6 +- src/include/fmgr.h | 30 +- src/include/nodes/execnodes.h | 2 +- src/include/postgres.h | 7 + src/pl/plperl/plperl.c | 20 +- src/pl/plpgsql/src/pl_exec.c | 8 +- src/pl/plpython/plpy_exec.c | 4 +- src/pl/tcl/pltcl.c | 17 +- 27 files changed, 764 insertions(+), 887 deletions(-) diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 9a702e4097e..6564cd7fe11 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -1050,7 +1050,7 @@ EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata) { Oid fnoid = lfirst_oid(lc); FmgrInfo flinfo; - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 0); PgStat_FunctionCallUsage fcusage; elog(DEBUG1, "EventTriggerInvoke %u", fnoid); @@ -1070,10 +1070,10 @@ EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata) 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. */ diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 3fd73a69f04..1eaf8011a96 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -2215,7 +2215,7 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver int i; AclResult aclresult; FmgrInfo flinfo; - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 3); CallContext *callcontext; EState *estate; ExprContext *econtext; @@ -2277,7 +2277,7 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver 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 @@ -2298,14 +2298,14 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull); - fcinfo.arg[i] = val; - fcinfo.argnull[i] = isnull; + fcinfo->args[i].datum = 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) @@ -2326,7 +2326,7 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver TupOutputState *tstate; TupleTableSlot *slot; - if (fcinfo.isnull) + if (fcinfo->isnull) elog(ERROR, "procedure returned null record"); td = DatumGetHeapTupleHeader(retval); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index e10d3dbf3dd..9a1a3895522 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8600,7 +8600,7 @@ validateForeignKeyConstraint(char *conname, while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 0); TriggerData trigdata; /* @@ -8608,7 +8608,7 @@ validateForeignKeyConstraint(char *conname, * * No parameters are passed, but we do set a context */ - MemSet(&fcinfo, 0, sizeof(fcinfo)); + MemSet(&fcinfodata, 0, sizeof(fcinfodata)); /* * We assume RI_FKey_check_ins won't look at flinfo... @@ -8622,9 +8622,9 @@ validateForeignKeyConstraint(char *conname, 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); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 240e85e3910..19fcd543caf 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -2358,7 +2358,7 @@ ExecCallTriggerFunc(TriggerData *trigdata, Instrumentation *instr, MemoryContext per_tuple_context) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 0); PgStat_FunctionCallUsage fcusage; Datum result; MemoryContext oldContext; @@ -2403,15 +2403,15 @@ ExecCallTriggerFunc(TriggerData *trigdata, /* * 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(); { @@ -2429,11 +2429,11 @@ ExecCallTriggerFunc(TriggerData *trigdata, * 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 diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index e284fd71d75..a39c3eabf35 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -965,7 +965,7 @@ ExecInitExprRec(Expr *node, ExprState *state, /* Set up the primary fmgr lookup information */ finfo = palloc0(sizeof(FmgrInfo)); - fcinfo = palloc0(sizeof(FunctionCallInfoData)); + fcinfo = palloc0(SizeForFunctionCallInfoData(2)); fmgr_info(opexpr->opfuncid, finfo); fmgr_info_set_expr((Node *) node, finfo); InitFunctionCallInfoData(*fcinfo, finfo, 2, @@ -973,7 +973,7 @@ ExecInitExprRec(Expr *node, ExprState *state, /* Evaluate scalar directly into left function argument */ ExecInitExprRec(scalararg, state, - &fcinfo->arg[0], &fcinfo->argnull[0]); + &fcinfo->args[0].datum, &fcinfo->args[0].isnull); /* * Evaluate array argument into our return value. There's no @@ -1262,7 +1262,7 @@ ExecInitExprRec(Expr *node, ExprState *state, /* lookup the source type's output function */ scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo)); - scratch.d.iocoerce.fcinfo_data_out = palloc0(sizeof(FunctionCallInfoData)); + scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfoData(1)); getTypeOutputInfo(exprType((Node *) iocoerce->arg), &iofunc, &typisvarlena); @@ -1274,7 +1274,7 @@ ExecInitExprRec(Expr *node, ExprState *state, /* lookup the result type's input function */ scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo)); - scratch.d.iocoerce.fcinfo_data_in = palloc0(sizeof(FunctionCallInfoData)); + scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfoData(3)); getTypeInputInfo(iocoerce->resulttype, &iofunc, &typioparam); @@ -1289,10 +1289,10 @@ ExecInitExprRec(Expr *node, ExprState *state, * function, since they're constants. */ fcinfo_in = scratch.d.iocoerce.fcinfo_data_in; - fcinfo_in->arg[1] = ObjectIdGetDatum(typioparam); - fcinfo_in->argnull[1] = false; - fcinfo_in->arg[2] = Int32GetDatum(-1); - fcinfo_in->argnull[2] = false; + fcinfo_in->args[1].datum = ObjectIdGetDatum(typioparam); + fcinfo_in->args[1].isnull = false; + fcinfo_in->args[2].datum = Int32GetDatum(-1); + fcinfo_in->args[2].isnull = false; ExprEvalPushStep(state, &scratch); break; @@ -1733,7 +1733,7 @@ ExecInitExprRec(Expr *node, ExprState *state, /* Set up the primary fmgr lookup information */ finfo = palloc0(sizeof(FmgrInfo)); - fcinfo = palloc0(sizeof(FunctionCallInfoData)); + fcinfo = palloc0(SizeForFunctionCallInfoData(2)); fmgr_info(proc, finfo); fmgr_info_set_expr((Node *) node, finfo); InitFunctionCallInfoData(*fcinfo, finfo, 2, @@ -1748,9 +1748,9 @@ ExecInitExprRec(Expr *node, ExprState *state, /* evaluate left and right args directly into fcinfo */ ExecInitExprRec(left_expr, state, - &fcinfo->arg[0], &fcinfo->argnull[0]); + &fcinfo->args[0].datum, &fcinfo->args[0].isnull); ExecInitExprRec(right_expr, state, - &fcinfo->arg[1], &fcinfo->argnull[1]); + &fcinfo->args[1].datum, &fcinfo->args[1].isnull); scratch.opcode = EEOP_ROWCOMPARE_STEP; scratch.d.rowcompare_step.finfo = finfo; @@ -1876,7 +1876,7 @@ ExecInitExprRec(Expr *node, ExprState *state, /* Perform function lookup */ finfo = palloc0(sizeof(FmgrInfo)); - fcinfo = palloc0(sizeof(FunctionCallInfoData)); + fcinfo = palloc0(SizeForFunctionCallInfoData(2)); fmgr_info(typentry->cmp_proc, finfo); fmgr_info_set_expr((Node *) node, finfo); InitFunctionCallInfoData(*fcinfo, finfo, 2, @@ -2185,7 +2185,7 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, /* Allocate function lookup data and parameter workspace for this call */ scratch->d.func.finfo = palloc0(sizeof(FmgrInfo)); - scratch->d.func.fcinfo_data = palloc0(sizeof(FunctionCallInfoData)); + scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfoData(nargs)); flinfo = scratch->d.func.finfo; fcinfo = scratch->d.func.fcinfo_data; @@ -2224,13 +2224,14 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, */ Const *con = (Const *) arg; - fcinfo->arg[argno] = con->constvalue; - fcinfo->argnull[argno] = con->constisnull; + fcinfo->args[argno].datum = con->constvalue; + fcinfo->args[argno].isnull = con->constisnull; } else { ExecInitExprRec(arg, state, - &fcinfo->arg[argno], &fcinfo->argnull[argno]); + &fcinfo->args[argno].datum, + &fcinfo->args[argno].isnull); } argno++; } @@ -2863,10 +2864,11 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, int numInputs = pertrans->numInputs; 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; /* @@ -2904,7 +2906,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, Assert(pertrans->numSortCols == 0); Assert(list_length(pertrans->aggref->args) == 1); - strictnulls = trans_fcinfo->argnull + 1; + strictargs = trans_fcinfo->args + 1; source_tle = (TargetEntry *) linitial(pertrans->aggref->args); /* @@ -2918,21 +2920,21 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, * value */ ExecInitExprRec(source_tle->expr, state, - &trans_fcinfo->arg[argno + 1], - &trans_fcinfo->argnull[argno + 1]); + &trans_fcinfo->args[argno + 1].datum, + &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].datum, + &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].datum = PointerGetDatum(NULL); + ds_fcinfo->args[1].isnull = false; /* * Don't call a strict deserialization function with NULL @@ -2946,8 +2948,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, scratch.d.agg_deserialize.aggstate = aggstate; scratch.d.agg_deserialize.fcinfo_data = ds_fcinfo; scratch.d.agg_deserialize.jumpnull = -1; /* adjust later */ - scratch.resvalue = &trans_fcinfo->arg[argno + 1]; - scratch.resnull = &trans_fcinfo->argnull[argno + 1]; + scratch.resvalue = &trans_fcinfo->args[argno + 1].datum; + scratch.resnull = &trans_fcinfo->args[argno + 1].isnull; ExprEvalPushStep(state, &scratch); adjust_bailout = lappend_int(adjust_bailout, @@ -2964,7 +2966,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, /* * Normal transition function without ORDER BY / DISTINCT. */ - strictnulls = trans_fcinfo->argnull + 1; + strictargs = trans_fcinfo->args + 1; foreach(arg, pertrans->aggref->args) { @@ -2975,8 +2977,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, * value */ ExecInitExprRec(source_tle->expr, state, - &trans_fcinfo->arg[argno + 1], - &trans_fcinfo->argnull[argno + 1]); + &trans_fcinfo->args[argno + 1].datum, + &trans_fcinfo->args[argno + 1].isnull); argno++; } } @@ -3024,8 +3026,12 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, */ if (trans_fcinfo->flinfo->fn_strict && numInputs > 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 = numInputs; ExprEvalPushStep(state, &scratch); @@ -3079,7 +3085,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, Assert(as->d.jump.jumpdone == -1); as->d.jump.jumpdone = state->steps_len; } - else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK) + else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS || + as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS) { Assert(as->d.agg_strict_input_check.jumpnull == -1); as->d.agg_strict_input_check.jumpnull = state->steps_len; @@ -3284,7 +3291,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, /* Set up the primary fmgr lookup information */ finfo = palloc0(sizeof(FmgrInfo)); - fcinfo = palloc0(sizeof(FunctionCallInfoData)); + fcinfo = palloc0(SizeForFunctionCallInfoData(2)); fmgr_info(foid, finfo); fmgr_info_set_expr(NULL, finfo); InitFunctionCallInfoData(*fcinfo, finfo, 2, @@ -3294,16 +3301,16 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, scratch.opcode = EEOP_INNER_VAR; scratch.d.var.attnum = attno - 1; scratch.d.var.vartype = latt->atttypid; - scratch.resvalue = &fcinfo->arg[0]; - scratch.resnull = &fcinfo->argnull[0]; + scratch.resvalue = &fcinfo->args[0].datum; + 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].datum; + scratch.resnull = &fcinfo->args[1].isnull; ExprEvalPushStep(state, &scratch); /* evaluate distinctness */ diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 1b0946b02f2..3716585901e 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -386,7 +386,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_ALTERNATIVE_SUBPLAN, &&CASE_EEOP_AGG_STRICT_DESERIALIZE, &&CASE_EEOP_AGG_DESERIALIZE, - &&CASE_EEOP_AGG_STRICT_INPUT_CHECK, + &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS, + &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS, &&CASE_EEOP_AGG_INIT_TRANS, &&CASE_EEOP_AGG_STRICT_TRANS_CHECK, &&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL, @@ -661,14 +662,14 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_CASE(EEOP_FUNCEXPR_STRICT) { FunctionCallInfo fcinfo = op->d.func.fcinfo_data; - bool *argnull = fcinfo->argnull; + NullableDatum *args = fcinfo->args; int argno; Datum d; /* strict function, so check for NULL args */ for (argno = 0; argno < op->d.func.nargs; argno++) { - if (argnull[argno]) + if (args[argno].isnull) { *op->resnull = true; goto strictfail; @@ -1084,8 +1085,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) FunctionCallInfo fcinfo_out; fcinfo_out = op->d.iocoerce.fcinfo_data_out; - fcinfo_out->arg[0] = *op->resvalue; - fcinfo_out->argnull[0] = false; + fcinfo_out->args[0].datum = *op->resvalue; + fcinfo_out->args[0].isnull = false; fcinfo_out->isnull = false; str = DatumGetCString(FunctionCallInvoke(fcinfo_out)); @@ -1101,8 +1102,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) Datum d; fcinfo_in = op->d.iocoerce.fcinfo_data_in; - fcinfo_in->arg[0] = PointerGetDatum(str); - fcinfo_in->argnull[0] = *op->resnull; + fcinfo_in->args[0].datum = PointerGetDatum(str); + fcinfo_in->args[0].isnull = *op->resnull; /* second and third arguments are already set up */ fcinfo_in->isnull = false; @@ -1139,13 +1140,13 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) 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); @@ -1171,12 +1172,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) { FunctionCallInfo fcinfo = op->d.func.fcinfo_data; - if (fcinfo->argnull[0] && fcinfo->argnull[1]) + if (fcinfo->args[0].isnull && fcinfo->args[1].isnull) { *op->resvalue = BoolGetDatum(true); *op->resnull = false; } - else if (fcinfo->argnull[0] || fcinfo->argnull[1]) + else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull) { *op->resvalue = BoolGetDatum(false); *op->resnull = false; @@ -1202,7 +1203,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) 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; @@ -1220,8 +1221,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) } /* Arguments aren't equal, so return the first one */ - *op->resvalue = fcinfo->arg[0]; - *op->resnull = fcinfo->argnull[0]; + *op->resvalue = fcinfo->args[0].datum; + *op->resnull = fcinfo->args[0].isnull; EEO_NEXT(); } @@ -1287,7 +1288,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) /* force NULL result if strict fn and NULL input */ if (op->d.rowcompare_step.finfo->fn_strict && - (fcinfo->argnull[0] || fcinfo->argnull[1])) + (fcinfo->args[0].isnull || fcinfo->args[1].isnull)) { *op->resnull = true; EEO_JUMP(op->d.rowcompare_step.jumpnull); @@ -1526,10 +1527,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) /* evaluate a strict aggregate deserialization function */ EEO_CASE(EEOP_AGG_STRICT_DESERIALIZE) { - bool *argnull = op->d.agg_deserialize.fcinfo_data->argnull; - /* Don't call a strict deserialization function with NULL input */ - if (argnull[0]) + if (op->d.agg_deserialize.fcinfo_data->args[0].isnull) EEO_JUMP(op->d.agg_deserialize.jumpnull); /* fallthrough */ @@ -1559,15 +1558,29 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) * Check that a strict aggregate transition / combination function's * input is not NULL. */ - EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK) + EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS) { int argno; - bool *nulls = op->d.agg_strict_input_check.nulls; + 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 (nulls[argno]) + if (args[argno].isnull) + EEO_JUMP(op->d.agg_strict_input_check.jumpnull); + } + EEO_NEXT(); + } + + EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_NULLS) + { + int argno; + bool *isnull = op->d.agg_strict_input_check.nulls; + int nargs = op->d.agg_strict_input_check.nargs; + + for (argno = 0; argno < nargs; argno++) + { + if (isnull[argno]) EEO_JUMP(op->d.agg_strict_input_check.jumpnull); } EEO_NEXT(); @@ -1643,7 +1656,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) Assert(pertrans->transtypeByVal); - fcinfo = &pertrans->transfn_fcinfo; + fcinfo = pertrans->transfn_fcinfo; /* cf. select_current_set() */ aggstate->curaggcontext = op->d.agg_trans.aggcontext; @@ -1655,8 +1668,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) /* invoke transition function in per-tuple context */ oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory); - fcinfo->arg[0] = pergroup->transValue; - fcinfo->argnull[0] = pergroup->transValueIsNull; + fcinfo->args[0].datum = pergroup->transValue; + fcinfo->args[0].isnull = pergroup->transValueIsNull; fcinfo->isnull = false; /* just in case transfn doesn't set it */ newVal = FunctionCallInvoke(fcinfo); @@ -1694,7 +1707,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) Assert(!pertrans->transtypeByVal); - fcinfo = &pertrans->transfn_fcinfo; + fcinfo = pertrans->transfn_fcinfo; /* cf. select_current_set() */ aggstate->curaggcontext = op->d.agg_trans.aggcontext; @@ -1706,8 +1719,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) /* invoke transition function in per-tuple context */ oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory); - fcinfo->arg[0] = pergroup->transValue; - fcinfo->argnull[0] = pergroup->transValueIsNull; + fcinfo->args[0].datum = pergroup->transValue; + fcinfo->args[0].isnull = pergroup->transValueIsNull; fcinfo->isnull = false; /* just in case transfn doesn't set it */ newVal = FunctionCallInvoke(fcinfo); @@ -2060,7 +2073,7 @@ ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull) { ExprEvalStep *op = &state->steps[0]; FunctionCallInfo fcinfo; - bool *argnull; + NullableDatum *args; int argno; Datum d; @@ -2074,12 +2087,12 @@ ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull) op++; fcinfo = op->d.func.fcinfo_data; - argnull = fcinfo->argnull; + args = fcinfo->args; /* strict function, so check for NULL args */ for (argno = 0; argno < op->d.func.nargs; argno++) { - if (argnull[argno]) + if (args[argno].isnull) { *isnull = true; return (Datum) 0; @@ -2205,14 +2218,14 @@ ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op, FunctionCallInfo fcinfo = op->d.func.fcinfo_data; PgStat_FunctionCallUsage fcusage; - bool *argnull = fcinfo->argnull; + NullableDatum *args = fcinfo->args; int argno; Datum d; /* strict function, so check for NULL args */ for (argno = 0; argno < op->d.func.nargs; argno++) { - if (argnull[argno]) + if (args[argno].isnull) { *op->resnull = true; return; @@ -2303,7 +2316,7 @@ void ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op) { SQLValueFunction *svf = op->d.sqlvaluefunction.svf; - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 0); *op->resnull = false; @@ -2335,24 +2348,24 @@ ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op) case SVFOP_CURRENT_ROLE: case SVFOP_CURRENT_USER: case SVFOP_USER: - InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL); - *op->resvalue = current_user(&fcinfo); - *op->resnull = fcinfo.isnull; + InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL); + *op->resvalue = current_user(fcinfo); + *op->resnull = fcinfo->isnull; break; case SVFOP_SESSION_USER: - InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL); - *op->resvalue = session_user(&fcinfo); - *op->resnull = fcinfo.isnull; + InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL); + *op->resvalue = session_user(fcinfo); + *op->resnull = fcinfo->isnull; break; case SVFOP_CURRENT_CATALOG: - InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL); - *op->resvalue = current_database(&fcinfo); - *op->resnull = fcinfo.isnull; + InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL); + *op->resvalue = current_database(fcinfo); + *op->resnull = fcinfo->isnull; break; case SVFOP_CURRENT_SCHEMA: - InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL); - *op->resvalue = current_schema(&fcinfo); - *op->resnull = fcinfo.isnull; + InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL); + *op->resvalue = current_schema(fcinfo); + *op->resnull = fcinfo->isnull; break; } } @@ -2785,8 +2798,8 @@ ExecEvalMinMax(ExprState *state, ExprEvalStep *op) int off; /* set at initialization */ - Assert(fcinfo->argnull[0] == false); - Assert(fcinfo->argnull[1] == false); + Assert(fcinfo->args[0].isnull == false); + Assert(fcinfo->args[1].isnull == false); /* default to null result */ *op->resnull = true; @@ -2808,8 +2821,8 @@ ExecEvalMinMax(ExprState *state, ExprEvalStep *op) int cmpresult; /* apply comparison function */ - fcinfo->arg[0] = *op->resvalue; - fcinfo->arg[1] = values[off]; + fcinfo->args[0].datum = *op->resvalue; + fcinfo->args[1].datum = values[off]; fcinfo->isnull = false; cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo)); @@ -3361,7 +3374,7 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op) * If the scalar is NULL, and the function is strict, return NULL; no * point in iterating the loop. */ - if (fcinfo->argnull[0] && strictfunc) + if (fcinfo->args[0].isnull && strictfunc) { *op->resnull = true; return; @@ -3401,20 +3414,20 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op) /* Get array element, checking for NULL */ if (bitmap && (*bitmap & bitmask) == 0) { - fcinfo->arg[1] = (Datum) 0; - fcinfo->argnull[1] = true; + fcinfo->args[1].datum = (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].datum = 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; @@ -4013,7 +4026,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext) void ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup) { - FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo; + FunctionCallInfo fcinfo = pertrans->transfn_fcinfo; MemoryContext oldContext; /* @@ -4024,7 +4037,7 @@ ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup */ oldContext = MemoryContextSwitchTo( aggstate->curaggcontext->ecxt_per_tuple_memory); - pergroup->transValue = datumCopy(fcinfo->arg[1], + pergroup->transValue = datumCopy(fcinfo->args[1].datum, pertrans->transtypeByVal, pertrans->transtypeLen); pergroup->transValueIsNull = false; diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c index b97b8d797ec..a50670f537a 100644 --- a/src/backend/executor/execSRF.c +++ b/src/backend/executor/execSRF.c @@ -109,7 +109,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr, Oid funcrettype; bool returnsTuple; bool returnsSet = false; - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 3); PgStat_FunctionCallUsage fcusage; ReturnSetInfo rsinfo; HeapTupleData tmptup; @@ -157,9 +157,9 @@ ExecMakeTableFunctionResult(SetExprState *setexpr, * This path is similar to ExecMakeFunctionResultSet. */ returnsSet = setexpr->funcReturnsSet; - InitFunctionCallInfoData(fcinfo, &(setexpr->func), + InitFunctionCallInfoData(*fcinfo, &(setexpr->func), list_length(setexpr->args), - setexpr->fcinfo_data.fncollation, + setexpr->fcinfo->fncollation, NULL, (Node *) &rsinfo); /* @@ -174,7 +174,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr, */ MemoryContextReset(argContext); oldcontext = MemoryContextSwitchTo(argContext); - ExecEvalFuncArgs(&fcinfo, setexpr->args, econtext); + ExecEvalFuncArgs(fcinfo, setexpr->args, econtext); MemoryContextSwitchTo(oldcontext); /* @@ -186,9 +186,9 @@ ExecMakeTableFunctionResult(SetExprState *setexpr, { int i; - for (i = 0; i < fcinfo.nargs; i++) + for (i = 0; i < fcinfo->nargs; i++) { - if (fcinfo.argnull[i]) + if (fcinfo->args[i].isnull) goto no_function_result; } } @@ -196,7 +196,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr, else { /* Treat setexpr as a generic expression */ - InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL); + InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL); } /* @@ -224,11 +224,11 @@ ExecMakeTableFunctionResult(SetExprState *setexpr, /* Call the function or expression one time */ if (!setexpr->elidedFuncState) { - pgstat_init_function_usage(&fcinfo, &fcusage); + pgstat_init_function_usage(fcinfo, &fcusage); - fcinfo.isnull = false; + fcinfo->isnull = false; rsinfo.isDone = ExprSingleResult; - result = FunctionCallInvoke(&fcinfo); + result = FunctionCallInvoke(fcinfo); pgstat_end_function_usage(&fcusage, rsinfo.isDone != ExprMultipleResult); @@ -236,7 +236,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr, else { result = - ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo.isnull); + ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo->isnull); rsinfo.isDone = ExprSingleResult; } @@ -277,7 +277,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr, */ if (returnsTuple) { - if (!fcinfo.isnull) + if (!fcinfo->isnull) { HeapTupleHeader td = DatumGetHeapTupleHeader(result); @@ -338,7 +338,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr, else { /* Scalar-type case: just store the function result */ - tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull); + tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo->isnull); } /* @@ -547,7 +547,7 @@ restart: * rows from this SRF have been returned, otherwise ValuePerCall SRFs * would reference freed memory after the first returned row. */ - fcinfo = &fcache->fcinfo_data; + fcinfo = fcache->fcinfo; arguments = fcache->args; if (!fcache->setArgsValid) { @@ -587,7 +587,7 @@ restart: { for (i = 0; i < fcinfo->nargs; i++) { - if (fcinfo->argnull[i]) + if (fcinfo->args[i].isnull) { callit = false; break; @@ -704,7 +704,8 @@ init_sexpr(Oid foid, Oid input_collation, Expr *node, fmgr_info_set_expr((Node *) sexpr->expr, &(sexpr->func)); /* Initialize the function call parameter struct as well */ - InitFunctionCallInfoData(sexpr->fcinfo_data, &(sexpr->func), + sexpr->fcinfo = (FunctionCallInfo) palloc(SizeForFunctionCallInfoData(list_length(sexpr->args))); + InitFunctionCallInfoData(*sexpr->fcinfo, &(sexpr->func), list_length(sexpr->args), input_collation, NULL, NULL); @@ -820,9 +821,9 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo, { ExprState *argstate = (ExprState *) lfirst(arg); - fcinfo->arg[i] = ExecEvalExpr(argstate, - econtext, - &fcinfo->argnull[i]); + fcinfo->args[i].datum = ExecEvalExpr(argstate, + econtext, + &fcinfo->args[i].isnull); i++; } diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 23545896d4d..672dcd981cd 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -933,8 +933,8 @@ postquel_sub_params(SQLFunctionCachePtr fcache, { ParamExternData *prm = ¶mLI->params[i]; - prm->value = fcinfo->arg[i]; - prm->isnull = fcinfo->argnull[i]; + prm->value = fcinfo->args[i].datum; + prm->isnull = fcinfo->args[i].isnull; prm->pflags = 0; prm->ptype = fcache->pinfo->argtypes[i]; } diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 98d8483b720..e9bea4a46a2 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -553,7 +553,7 @@ advance_transition_function(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate) { - FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo; + FunctionCallInfo fcinfo = pertrans->transfn_fcinfo; MemoryContext oldContext; Datum newVal; @@ -568,7 +568,7 @@ advance_transition_function(AggState *aggstate, for (i = 1; i <= numTransInputs; i++) { - if (fcinfo->argnull[i]) + if (fcinfo->args[i].isnull) return; } if (pergroupstate->noTransValue) @@ -584,7 +584,7 @@ advance_transition_function(AggState *aggstate, */ oldContext = MemoryContextSwitchTo( aggstate->curaggcontext->ecxt_per_tuple_memory); - pergroupstate->transValue = datumCopy(fcinfo->arg[1], + pergroupstate->transValue = datumCopy(fcinfo->args[1].datum, pertrans->transtypeByVal, pertrans->transtypeLen); pergroupstate->transValueIsNull = false; @@ -613,8 +613,8 @@ advance_transition_function(AggState *aggstate, /* * OK to call the transition function */ - fcinfo->arg[0] = pergroupstate->transValue; - fcinfo->argnull[0] = pergroupstate->transValueIsNull; + fcinfo->args[0].datum = pergroupstate->transValue; + fcinfo->args[0].isnull = pergroupstate->transValueIsNull; fcinfo->isnull = false; /* just in case transfn doesn't set it */ newVal = FunctionCallInvoke(fcinfo); @@ -717,7 +717,7 @@ process_ordered_aggregate_single(AggState *aggstate, bool isDistinct = (pertrans->numDistinctCols > 0); Datum newAbbrevVal = (Datum) 0; Datum oldAbbrevVal = (Datum) 0; - FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo; + FunctionCallInfo fcinfo = pertrans->transfn_fcinfo; Datum *newVal; bool *isNull; @@ -726,8 +726,8 @@ process_ordered_aggregate_single(AggState *aggstate, tuplesort_performsort(pertrans->sortstates[aggstate->current_set]); /* Load the column into argument 1 (arg 0 will be transition value) */ - newVal = fcinfo->arg + 1; - isNull = fcinfo->argnull + 1; + newVal = &fcinfo->args[1].datum; + isNull = &fcinfo->args[1].isnull; /* * Note: if input type is pass-by-ref, the datums returned by the sort are @@ -803,7 +803,7 @@ process_ordered_aggregate_multi(AggState *aggstate, AggStatePerGroup pergroupstate) { ExprContext *tmpcontext = aggstate->tmpcontext; - FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo; + FunctionCallInfo fcinfo = pertrans->transfn_fcinfo; TupleTableSlot *slot1 = pertrans->sortslot; TupleTableSlot *slot2 = pertrans->uniqslot; int numTransInputs = pertrans->numTransInputs; @@ -843,8 +843,8 @@ process_ordered_aggregate_multi(AggState *aggstate, /* Start from 1, since the 0th arg will be the transition value */ for (i = 0; i < numTransInputs; i++) { - fcinfo->arg[i + 1] = slot1->tts_values[i]; - fcinfo->argnull[i + 1] = slot1->tts_isnull[i]; + fcinfo->args[i + 1].datum = slot1->tts_values[i]; + fcinfo->args[i + 1].isnull = slot1->tts_isnull[i]; } advance_transition_function(aggstate, pertrans, pergroupstate); @@ -897,7 +897,7 @@ finalize_aggregate(AggState *aggstate, AggStatePerGroup pergroupstate, Datum *resultVal, bool *resultIsNull) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 3); bool anynull = false; MemoryContext oldContext; int i; @@ -917,10 +917,10 @@ finalize_aggregate(AggState *aggstate, { ExprState *expr = (ExprState *) lfirst(lc); - fcinfo.arg[i] = ExecEvalExpr(expr, - aggstate->ss.ps.ps_ExprContext, - &fcinfo.argnull[i]); - anynull |= fcinfo.argnull[i]; + fcinfo->args[i].datum = ExecEvalExpr(expr, + aggstate->ss.ps.ps_ExprContext, + &fcinfo->args[i].isnull); + anynull |= fcinfo->args[i].isnull; i++; } @@ -934,27 +934,27 @@ finalize_aggregate(AggState *aggstate, /* set up aggstate->curperagg for AggGetAggref() */ aggstate->curperagg = peragg; - InitFunctionCallInfoData(fcinfo, &peragg->finalfn, + InitFunctionCallInfoData(*fcinfo, &peragg->finalfn, numFinalArgs, pertrans->aggCollation, (void *) aggstate, NULL); /* Fill in the transition state value */ - fcinfo.arg[0] = MakeExpandedObjectReadOnly(pergroupstate->transValue, - pergroupstate->transValueIsNull, - pertrans->transtypeLen); - fcinfo.argnull[0] = pergroupstate->transValueIsNull; + fcinfo->args[0].datum = 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].datum = (Datum) 0; + fcinfo->args[i].isnull = true; anynull = true; } - if (fcinfo.flinfo->fn_strict && anynull) + if (fcinfo->flinfo->fn_strict && anynull) { /* don't call a strict function with NULL inputs */ *resultVal = (Datum) 0; @@ -962,8 +962,8 @@ finalize_aggregate(AggState *aggstate, } else { - *resultVal = FunctionCallInvoke(&fcinfo); - *resultIsNull = fcinfo.isnull; + *resultVal = FunctionCallInvoke(fcinfo); + *resultIsNull = fcinfo->isnull; } aggstate->curperagg = NULL; } @@ -1018,12 +1018,12 @@ finalize_partialaggregate(AggState *aggstate, } else { - FunctionCallInfo fcinfo = &pertrans->serialfn_fcinfo; + FunctionCallInfo fcinfo = pertrans->serialfn_fcinfo; - fcinfo->arg[0] = MakeExpandedObjectReadOnly(pergroupstate->transValue, - pergroupstate->transValueIsNull, - pertrans->transtypeLen); - fcinfo->argnull[0] = pergroupstate->transValueIsNull; + fcinfo->args[0].datum = MakeExpandedObjectReadOnly(pergroupstate->transValue, + pergroupstate->transValueIsNull, + pertrans->transtypeLen); + fcinfo->args[0].isnull = pergroupstate->transValueIsNull; *resultVal = FunctionCallInvoke(fcinfo); *resultIsNull = fcinfo->isnull; @@ -2925,7 +2925,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, fmgr_info(aggtransfn, &pertrans->transfn); fmgr_info_set_expr((Node *) combinefnexpr, &pertrans->transfn); - InitFunctionCallInfoData(pertrans->transfn_fcinfo, + pertrans->transfn_fcinfo = (FunctionCallInfo) palloc(SizeForFunctionCallInfoData(2)); + InitFunctionCallInfoData(*pertrans->transfn_fcinfo, &pertrans->transfn, 2, pertrans->aggCollation, @@ -2963,7 +2964,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, fmgr_info(aggtransfn, &pertrans->transfn); fmgr_info_set_expr((Node *) transfnexpr, &pertrans->transfn); - InitFunctionCallInfoData(pertrans->transfn_fcinfo, + pertrans->transfn_fcinfo = (FunctionCallInfo) palloc(SizeForFunctionCallInfoData(pertrans->numTransInputs + 1)); + InitFunctionCallInfoData(*pertrans->transfn_fcinfo, &pertrans->transfn, pertrans->numTransInputs + 1, pertrans->aggCollation, @@ -3001,7 +3003,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, fmgr_info(aggserialfn, &pertrans->serialfn); fmgr_info_set_expr((Node *) serialfnexpr, &pertrans->serialfn); - InitFunctionCallInfoData(pertrans->serialfn_fcinfo, + pertrans->serialfn_fcinfo = (FunctionCallInfo) palloc(SizeForFunctionCallInfoData(1)); + InitFunctionCallInfoData(*pertrans->serialfn_fcinfo, &pertrans->serialfn, 1, InvalidOid, @@ -3015,7 +3018,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, fmgr_info(aggdeserialfn, &pertrans->deserialfn); fmgr_info_set_expr((Node *) deserialfnexpr, &pertrans->deserialfn); - InitFunctionCallInfoData(pertrans->deserialfn_fcinfo, + pertrans->deserialfn_fcinfo = (FunctionCallInfo) palloc(SizeForFunctionCallInfoData(2)); + InitFunctionCallInfoData(*pertrans->deserialfn_fcinfo, &pertrans->deserialfn, 2, InvalidOid, diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 729c376d86b..032598bd5bb 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -243,8 +243,7 @@ advance_windowaggregate(WindowAggState *winstate, { WindowFuncExprState *wfuncstate = perfuncstate->wfuncstate; int numArguments = perfuncstate->numArguments; - FunctionCallInfoData fcinfodata; - FunctionCallInfo fcinfo = &fcinfodata; + STACK_FCINFO_FOR_ARGS(fcinfo, 3); Datum newVal; ListCell *arg; int i; @@ -273,8 +272,8 @@ advance_windowaggregate(WindowAggState *winstate, { ExprState *argstate = (ExprState *) lfirst(arg); - fcinfo->arg[i] = ExecEvalExpr(argstate, econtext, - &fcinfo->argnull[i]); + fcinfo->args[i].datum = ExecEvalExpr(argstate, econtext, + &fcinfo->args[i].isnull); i++; } @@ -287,7 +286,7 @@ advance_windowaggregate(WindowAggState *winstate, */ for (i = 1; i <= numArguments; i++) { - if (fcinfo->argnull[i]) + if (fcinfo->args[i].isnull) { MemoryContextSwitchTo(oldContext); return; @@ -306,7 +305,7 @@ advance_windowaggregate(WindowAggState *winstate, if (peraggstate->transValueCount == 0 && peraggstate->transValueIsNull) { MemoryContextSwitchTo(peraggstate->aggcontext); - peraggstate->transValue = datumCopy(fcinfo->arg[1], + peraggstate->transValue = datumCopy(fcinfo->args[1].datum, peraggstate->transtypeByVal, peraggstate->transtypeLen); peraggstate->transValueIsNull = false; @@ -339,8 +338,8 @@ advance_windowaggregate(WindowAggState *winstate, numArguments + 1, perfuncstate->winCollation, (void *) winstate, NULL); - fcinfo->arg[0] = peraggstate->transValue; - fcinfo->argnull[0] = peraggstate->transValueIsNull; + fcinfo->args[0].datum = peraggstate->transValue; + fcinfo->args[0].isnull = peraggstate->transValueIsNull; winstate->curaggcontext = peraggstate->aggcontext; newVal = FunctionCallInvoke(fcinfo); winstate->curaggcontext = NULL; @@ -420,8 +419,7 @@ advance_windowaggregate_base(WindowAggState *winstate, { WindowFuncExprState *wfuncstate = perfuncstate->wfuncstate; int numArguments = perfuncstate->numArguments; - FunctionCallInfoData fcinfodata; - FunctionCallInfo fcinfo = &fcinfodata; + STACK_FCINFO_FOR_ARGS(fcinfo, 3); Datum newVal; ListCell *arg; int i; @@ -450,8 +448,8 @@ advance_windowaggregate_base(WindowAggState *winstate, { ExprState *argstate = (ExprState *) lfirst(arg); - fcinfo->arg[i] = ExecEvalExpr(argstate, econtext, - &fcinfo->argnull[i]); + fcinfo->args[i].datum = ExecEvalExpr(argstate, econtext, + &fcinfo->args[i].isnull); i++; } @@ -464,7 +462,7 @@ advance_windowaggregate_base(WindowAggState *winstate, */ for (i = 1; i <= numArguments; i++) { - if (fcinfo->argnull[i]) + if (fcinfo->args[i].isnull) { MemoryContextSwitchTo(oldContext); return true; @@ -510,8 +508,8 @@ advance_windowaggregate_base(WindowAggState *winstate, numArguments + 1, perfuncstate->winCollation, (void *) winstate, NULL); - fcinfo->arg[0] = peraggstate->transValue; - fcinfo->argnull[0] = peraggstate->transValueIsNull; + fcinfo->args[0].datum = peraggstate->transValue; + fcinfo->args[0].isnull = peraggstate->transValueIsNull; winstate->curaggcontext = peraggstate->aggcontext; newVal = FunctionCallInvoke(fcinfo); winstate->curaggcontext = NULL; @@ -592,29 +590,29 @@ finalize_windowaggregate(WindowAggState *winstate, if (OidIsValid(peraggstate->finalfn_oid)) { int numFinalArgs = peraggstate->numFinalArgs; - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 3); 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].datum = 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].datum = (Datum) 0; + fcinfo->args[i].isnull = true; anynull = true; } - if (fcinfo.flinfo->fn_strict && anynull) + if (fcinfo->flinfo->fn_strict && anynull) { /* don't call a strict function with NULL inputs */ *result = (Datum) 0; @@ -623,9 +621,9 @@ finalize_windowaggregate(WindowAggState *winstate, else { winstate->curaggcontext = peraggstate->aggcontext; - *result = FunctionCallInvoke(&fcinfo); + *result = FunctionCallInvoke(fcinfo); winstate->curaggcontext = NULL; - *isnull = fcinfo.isnull; + *isnull = fcinfo->isnull; } } else @@ -1032,8 +1030,9 @@ static void eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate, Datum *result, bool *isnull) { - FunctionCallInfoData fcinfo; + FunctionCallInfo fcinfo; MemoryContext oldContext; + int argno; oldContext = MemoryContextSwitchTo(winstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory); @@ -1043,24 +1042,26 @@ eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate, * implementations to support varying numbers of arguments. The real info * goes through the WindowObject, which is passed via fcinfo->context. */ - InitFunctionCallInfoData(fcinfo, &(perfuncstate->flinfo), + fcinfo = palloc(SizeForFunctionCallInfoData(perfuncstate->numArguments)); + 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 (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, diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c index 99e0cee157f..13aedc93016 100644 --- a/src/backend/jit/llvm/llvmjit_expr.c +++ b/src/backend/jit/llvm/llvmjit_expr.c @@ -2117,15 +2117,16 @@ llvm_compile_expr(ExprState *state) case EEOP_AGG_STRICT_INPUT_CHECK: { int nargs = op->d.agg_strict_input_check.nargs; - bool *nulls = op->d.agg_strict_input_check.nulls; + NullableDatum *args = op->d.agg_strict_input_check.args; int jumpnull; int argno; - LLVMValueRef v_nullp; + LLVMValueRef v_argp; LLVMBasicBlockRef *b_checknulls; jumpnull = op->d.agg_strict_input_check.jumpnull; - v_nullp = l_ptr_const(nulls, l_ptr(TypeStorageBool)); + /* FIXME: This isn't correct, it's a NullableDatum now */ + v_argp = l_ptr_const(args, l_ptr(TypeStorageBool)); /* create blocks for checking args */ b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs); @@ -2153,7 +2154,8 @@ llvm_compile_expr(ExprState *state) else b_argnotnull = b_checknulls[argno + 1]; - v_argisnull = l_load_gep1(b, v_nullp, v_argno, ""); + /* FIXME: This isn't correct */ + v_argisnull = l_load_gep1(b, v_argp, v_argno, ""); LLVMBuildCondBr(b, LLVMBuildICmp(b, @@ -2352,7 +2354,7 @@ llvm_compile_expr(ExprState *state) 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)); @@ -2622,12 +2624,8 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b, 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)); diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c index d16ba5ec927..4d2b687fb1f 100644 --- a/src/backend/tcop/fastpath.c +++ b/src/backend/tcop/fastpath.c @@ -260,7 +260,7 @@ HandleFunctionRequest(StringInfo msgBuf) { Oid fid; AclResult aclresult; - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 3); int16 rformat; Datum retval; struct fp_info my_fp; @@ -332,12 +332,12 @@ HandleFunctionRequest(StringInfo msgBuf) * 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); @@ -350,9 +350,9 @@ HandleFunctionRequest(StringInfo 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; @@ -363,18 +363,18 @@ HandleFunctionRequest(StringInfo msgBuf) 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(); @@ -450,11 +450,11 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip, 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), @@ -494,8 +494,8 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip, else pstring = pg_client_to_server(abuf.data, argsize); - fcinfo->arg[i] = OidInputFunctionCall(typinput, pstring, - typioparam, -1); + fcinfo->args[i].datum = OidInputFunctionCall(typinput, pstring, + typioparam, -1); /* Free result of encoding conversion, if any */ if (pstring && pstring != abuf.data) pfree(pstring); @@ -514,8 +514,8 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip, else bufptr = &abuf; - fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, bufptr, - typioparam, -1); + fcinfo->args[i].datum = OidReceiveFunctionCall(typreceive, bufptr, + typioparam, -1); /* Trouble if it didn't eat the whole buffer */ if (argsize != -1 && abuf.cursor != abuf.len) @@ -579,12 +579,13 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info *fip, argsize = pq_getmsgint(msgBuf, 4); if (argsize == -1) { - fcinfo->argnull[i] = true; - fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, NULL, - typioparam, -1); + /* FIXME: huh? */ + fcinfo->args[i].isnull = true; + fcinfo->args[i].datum = OidReceiveFunctionCall(typreceive, NULL, + typioparam, -1); continue; } - fcinfo->argnull[i] = false; + fcinfo->args[i].isnull = false; if (argsize < 0) ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), @@ -597,8 +598,8 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info *fip, pq_getmsgbytes(msgBuf, argsize), argsize); - fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, &abuf, - typioparam, -1); + fcinfo->args[i].datum = OidReceiveFunctionCall(typreceive, &abuf, + typioparam, -1); /* Trouble if it didn't eat the whole buffer */ if (abuf.cursor != abuf.len) diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index ce1ded888f1..577e8637768 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -3590,7 +3590,7 @@ array_eq(PG_FUNCTION_ARGS) array_iter it1; array_iter it2; int i; - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 3); if (element_type != AARR_ELEMTYPE(array2)) ereport(ERROR, @@ -3630,7 +3630,7 @@ array_eq(PG_FUNCTION_ARGS) /* * 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 */ @@ -3666,12 +3666,12 @@ array_eq(PG_FUNCTION_ARGS) /* * 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].datum = elt1; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = elt2; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); if (!oprresult) { result = false; @@ -3761,7 +3761,7 @@ array_cmp(FunctionCallInfo fcinfo) array_iter it1; array_iter it2; int i; - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 2); if (element_type != AARR_ELEMTYPE(array2)) ereport(ERROR, @@ -3794,7 +3794,7 @@ array_cmp(FunctionCallInfo fcinfo) /* * 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 */ @@ -3833,12 +3833,12 @@ array_cmp(FunctionCallInfo fcinfo) } /* 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].datum = elt1; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = elt2; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); if (cmpresult == 0) continue; /* equal */ @@ -3925,7 +3925,7 @@ hash_array(PG_FUNCTION_ARGS) char typalign; int i; array_iter iter; - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 1); /* * We arrange to look up the hash function only once per series of calls, @@ -3953,7 +3953,7 @@ hash_array(PG_FUNCTION_ARGS) /* * 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 */ @@ -3977,10 +3977,10 @@ hash_array(PG_FUNCTION_ARGS) else { /* Apply the hash function */ - locfcinfo.arg[0] = elt; - locfcinfo.argnull[0] = false; - locfcinfo.isnull = false; - elthash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo)); + locfcinfo->args[0].datum = elt; + locfcinfo->args[0].isnull = false; + locfcinfo->isnull = false; + elthash = DatumGetUInt32(FunctionCallInvoke(locfcinfo)); } /* @@ -4023,7 +4023,7 @@ hash_array_extended(PG_FUNCTION_ARGS) char typalign; int i; array_iter iter; - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 2); typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra; if (typentry == NULL || @@ -4042,7 +4042,7 @@ hash_array_extended(PG_FUNCTION_ARGS) 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 */ @@ -4065,12 +4065,11 @@ hash_array_extended(PG_FUNCTION_ARGS) 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].datum = elt; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = Int64GetDatum(seed); + locfcinfo->args[1].isnull = false; + elthash = DatumGetUInt64(FunctionCallInvoke(locfcinfo)); } result = (result << 5) - result + elthash; @@ -4113,7 +4112,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, int i; int j; array_iter it1; - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 2); if (element_type != AARR_ELEMTYPE(array2)) ereport(ERROR, @@ -4164,7 +4163,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, /* * 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 */ @@ -4206,12 +4205,12 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, /* * 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].datum = elt1; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = elt2; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); if (oprresult) break; } @@ -6062,7 +6061,7 @@ array_replace_internal(ArrayType *array, int bitmask; bool changed = false; TypeCacheEntry *typentry; - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 2); element_type = ARR_ELEMTYPE(array); ndim = ARR_NDIM(array); @@ -6117,7 +6116,7 @@ array_replace_internal(ArrayType *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 */ @@ -6175,12 +6174,12 @@ array_replace_internal(ArrayType *array, /* * 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].datum = elt; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = search; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); if (!oprresult) { /* no match, keep element */ @@ -6460,7 +6459,8 @@ width_bucket_array_fixed(Datum operand, char *thresholds_data; int typlen = typentry->typlen; bool typbyval = typentry->typbyval; - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 2); + int left; int right; @@ -6470,7 +6470,7 @@ width_bucket_array_fixed(Datum operand, */ 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 */ @@ -6484,13 +6484,13 @@ width_bucket_array_fixed(Datum operand, 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].datum = operand; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = 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; @@ -6514,13 +6514,13 @@ width_bucket_array_variable(Datum operand, int typlen = typentry->typlen; bool typbyval = typentry->typbyval; char typalign = typentry->typalign; - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 2); 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 */ @@ -6541,13 +6541,12 @@ width_bucket_array_variable(Datum operand, 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].datum = operand; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = fetch_att(ptr, typbyval, typlen); + locfcinfo->args[1].isnull = false; - cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo)); + cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); if (cmpresult < 0) right = mid; diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index 8149dc1369b..cb92b0f98bb 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -202,7 +202,7 @@ Datum int2vectorrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 3); int2vector *result; /* @@ -211,19 +211,19 @@ int2vectorrecv(PG_FUNCTION_ARGS) * 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].datum = PointerGetDatum(buf); + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = ObjectIdGetDatum(INT2OID); + locfcinfo->args[1].isnull = false; + locfcinfo->args[2].datum = 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 || diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c index b0670e0d9f7..cf50f843115 100644 --- a/src/backend/utils/adt/oid.c +++ b/src/backend/utils/adt/oid.c @@ -257,7 +257,7 @@ Datum oidvectorrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 3); oidvector *result; /* @@ -266,19 +266,19 @@ oidvectorrecv(PG_FUNCTION_ARGS) * 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].datum = PointerGetDatum(buf); + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = ObjectIdGetDatum(OIDOID); + locfcinfo->args[1].isnull = false; + locfcinfo->args[2].datum = 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 || diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c index 5f729342f8d..de2bd560eea 100644 --- a/src/backend/utils/adt/rowtypes.c +++ b/src/backend/utils/adt/rowtypes.c @@ -942,7 +942,7 @@ record_cmp(FunctionCallInfo fcinfo) */ if (!nulls1[i1] || !nulls2[i2]) { - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 3); int32 cmpresult; if (nulls1[i1]) @@ -959,14 +959,14 @@ record_cmp(FunctionCallInfo fcinfo) } /* 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].datum = values1[i1]; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = values2[i2]; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + cmpresult = DatumGetInt32(FunctionCallInvoke(locfcinfo)); if (cmpresult < 0) { @@ -1123,7 +1123,7 @@ record_eq(PG_FUNCTION_ARGS) Form_pg_attribute att2; TypeCacheEntry *typentry; Oid collation; - FunctionCallInfoData locfcinfo; + STACK_FCINFO_FOR_ARGS(locfcinfo, 3); bool oprresult; /* @@ -1193,14 +1193,14 @@ record_eq(PG_FUNCTION_ARGS) } /* 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].datum = values1[i1]; + locfcinfo->args[0].isnull = false; + locfcinfo->args[1].datum = values2[i2]; + locfcinfo->args[1].isnull = false; + locfcinfo->isnull = false; + oprresult = DatumGetBool(FunctionCallInvoke(locfcinfo)); if (!oprresult) { result = false; diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 6cbbd5b78b0..86d5cef8108 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -782,7 +782,6 @@ fmgr_security_definer(PG_FUNCTION_ARGS) * Support routines for callers of fmgr-compatible functions *------------------------------------------------------------------------- */ - /* * These are for invocation of a specifically named function with a * directly-computed parameter list. Note that neither arguments nor result @@ -792,18 +791,18 @@ fmgr_security_definer(PG_FUNCTION_ARGS) Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = 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; @@ -812,20 +811,20 @@ DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1) Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = 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; @@ -835,22 +834,22 @@ Datum DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = 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; @@ -860,24 +859,24 @@ Datum DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = 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; @@ -887,26 +886,26 @@ Datum DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].datum = 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; @@ -917,28 +916,28 @@ DirectFunctionCall6Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].datum = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].datum = 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; @@ -949,30 +948,30 @@ DirectFunctionCall7Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 7); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 7, collation, NULL, NULL); + 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; + fcinfo->args[0].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].datum = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].datum = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].datum = arg7; + fcinfo->args[6].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; @@ -983,32 +982,32 @@ DirectFunctionCall8Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7, Datum arg8) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 8); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 8, collation, NULL, NULL); + 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; + fcinfo->args[0].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].datum = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].datum = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].datum = arg7; + fcinfo->args[6].isnull = false; + fcinfo->args[7].datum = arg8; + fcinfo->args[7].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; @@ -1020,34 +1019,34 @@ DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg6, Datum arg7, Datum arg8, Datum arg9) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 9); Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 9, collation, NULL, NULL); + 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; + fcinfo->args[0].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].datum = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].datum = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].datum = arg7; + fcinfo->args[6].isnull = false; + fcinfo->args[7].datum = arg8; + fcinfo->args[7].isnull = false; + fcinfo->args[8].datum = arg9; + fcinfo->args[8].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; @@ -1065,18 +1064,18 @@ DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = 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; @@ -1085,25 +1084,47 @@ CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum Datum CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = 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; } +/* + * These are for invocation of a previously-looked-up function with a + * directly-computed parameter list. Note that neither arguments nor result + * are allowed to be NULL. + */ +Datum +FunctionCall0Coll(FmgrInfo *flinfo, Oid collation) +{ + STACK_FCINFO_FOR_ARGS(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; +} + /* * These are for invocation of a previously-looked-up function with a * directly-computed parameter list. Note that neither arguments nor result @@ -1112,19 +1133,19 @@ CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = 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; } @@ -1132,21 +1153,21 @@ FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1) Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = 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; } @@ -1155,23 +1176,23 @@ Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = 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; } @@ -1180,25 +1201,25 @@ Datum FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = 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; } @@ -1207,27 +1228,27 @@ Datum FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].datum = 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; } @@ -1237,29 +1258,29 @@ FunctionCall6Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].datum = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].datum = 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; } @@ -1269,31 +1290,31 @@ FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 7); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 7, collation, NULL, NULL); + 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; + fcinfo->args[0].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].datum = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].datum = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].datum = arg7; + fcinfo->args[6].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; } @@ -1303,33 +1324,33 @@ FunctionCall8Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7, Datum arg8) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 8); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 8, collation, NULL, NULL); + 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; + fcinfo->args[0].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].datum = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].datum = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].datum = arg7; + fcinfo->args[6].isnull = false; + fcinfo->args[7].datum = arg8; + fcinfo->args[7].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; } @@ -1340,35 +1361,35 @@ FunctionCall9Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg6, Datum arg7, Datum arg8, Datum arg9) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 9); Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 9, collation, NULL, NULL); + 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; + fcinfo->args[0].datum = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].datum = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].datum = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].datum = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].datum = arg7; + fcinfo->args[6].isnull = false; + fcinfo->args[7].datum = arg8; + fcinfo->args[7].isnull = false; + fcinfo->args[8].datum = arg9; + fcinfo->args[8].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; } @@ -1385,68 +1406,30 @@ Datum 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 @@ -1454,27 +1437,10 @@ OidFunctionCall3Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, 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 @@ -1482,29 +1448,10 @@ OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, 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 @@ -1512,31 +1459,10 @@ OidFunctionCall5Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, 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 @@ -1545,33 +1471,11 @@ OidFunctionCall6Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, 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 @@ -1580,35 +1484,11 @@ OidFunctionCall7Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, 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 @@ -1617,37 +1497,11 @@ OidFunctionCall8Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, 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 @@ -1657,39 +1511,11 @@ OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, 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); } @@ -1708,35 +1534,35 @@ OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = CStringGetDatum(str); + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = ObjectIdGetDatum(typioparam); + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = 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; @@ -1767,35 +1593,35 @@ Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod) { - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(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].datum = PointerGetDatum(buf); + fcinfo->args[0].isnull = false; + fcinfo->args[1].datum = ObjectIdGetDatum(typioparam); + fcinfo->args[1].isnull = false; + fcinfo->args[2].datum = 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; diff --git a/src/backend/utils/sort/sortsupport.c b/src/backend/utils/sort/sortsupport.c index 8c09fe4a430..31aa4100d67 100644 --- a/src/backend/utils/sort/sortsupport.c +++ b/src/backend/utils/sort/sortsupport.c @@ -26,10 +26,11 @@ /* 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 */ + FunctionCallInfoData fcinfo; /* reusable callinfo structure */ } SortShimExtra; +#define SizeForSortShimExtra(nargs) (offsetof(SortShimExtra, fcinfo) + SizeForFunctionCallInfoData(nargs)) /* * Shim function for calling an old-style comparator @@ -44,8 +45,8 @@ comparison_shim(Datum x, Datum y, SortSupport ssup) SortShimExtra *extra = (SortShimExtra *) ssup->ssup_extra; Datum result; - extra->fcinfo.arg[0] = x; - extra->fcinfo.arg[1] = y; + extra->fcinfo.args[0].datum = x; + extra->fcinfo.args[1].datum = y; /* just for paranoia's sake, we reset isnull each time */ extra->fcinfo.isnull = false; @@ -69,7 +70,7 @@ PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup) 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); @@ -77,8 +78,8 @@ PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup) /* 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; diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h index 02af68f2c25..8233a465189 100644 --- a/src/include/executor/execExpr.h +++ b/src/include/executor/execExpr.h @@ -223,7 +223,8 @@ typedef enum ExprEvalOp /* 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, @@ -599,7 +600,8 @@ typedef struct ExprEvalStep /* for EEOP_AGG_STRICT_INPUT_CHECK */ struct { - bool *nulls; + NullableDatum *args; + bool *nulls; int nargs; int jumpnull; } agg_strict_input_check; diff --git a/src/include/executor/nodeAgg.h b/src/include/executor/nodeAgg.h index 8fb8c8fe802..51aec33fd8d 100644 --- a/src/include/executor/nodeAgg.h +++ b/src/include/executor/nodeAgg.h @@ -158,12 +158,12 @@ typedef struct AggStatePerTransData * 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; /* diff --git a/src/include/fmgr.h b/src/include/fmgr.h index 101f513ba67..ee1dbd5fcbb 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -83,12 +83,28 @@ typedef struct FunctionCallInfoData #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 */ +#define FIELDNO_FUNCTIONCALLINFODATA_ARGS 6 + + NullableDatum args[FLEXIBLE_ARRAY_MEMBER]; + } FunctionCallInfoData; +#define SizeForFunctionCallInfoData(nargs) (offsetof(FunctionCallInfoData, args) + sizeof(NullableDatum) * (nargs)) + +/* + * This macro ensures that `name` points to a stack-allocated + * FunctionCallInfoData struct with sufficient space for `nargs` arguments. + */ +#define STACK_FCINFO_FOR_ARGS(name, nargs) \ + union \ + { \ + FunctionCallInfoData fcinfo; \ + /* ensure enough space for nargs args is available */ \ + char *fcinfo_data[SizeForFunctionCallInfoData(nargs)]; \ + } name##data; \ + FunctionCallInfo name = &name##data.fcinfo + + /* * This routine fills a FmgrInfo struct, given the OID * of the function to be called. @@ -141,7 +157,6 @@ extern void fmgr_symbol(Oid functionId, char **mod, char **fn); */ #define FunctionCallInvoke(fcinfo) ((* (fcinfo)->flinfo->fn_addr) (fcinfo)) - /*------------------------------------------------------------------------- * Support macros to ease writing fmgr-compatible functions * @@ -176,7 +191,7 @@ extern void fmgr_symbol(Oid functionId, char **mod, char **fn); * 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 @@ -235,7 +250,7 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena *datum); /* Macros for fetching arguments of standard types */ -#define PG_GETARG_DATUM(n) (fcinfo->arg[n]) +#define PG_GETARG_DATUM(n) (fcinfo->args[n].datum) #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)) @@ -514,6 +529,7 @@ extern Datum CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, * 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, diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 834708944bf..e04573f11ae 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -828,7 +828,7 @@ typedef struct SetExprState * (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; /* ---------------- diff --git a/src/include/postgres.h b/src/include/postgres.h index b596fcb513e..b3ff25dc6e2 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -366,6 +366,13 @@ typedef struct typedef uintptr_t Datum; +typedef struct NullableDatum +{ + Datum datum; + bool isnull; + /* FIXME: space for flags? */ +} NullableDatum; + #define SIZEOF_DATUM SIZEOF_VOID_P /* diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index 4cfc5062531..3d4350a16c9 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -1877,7 +1877,7 @@ Datum plperl_inline_handler(PG_FUNCTION_ARGS) { InlineCodeBlock *codeblock = (InlineCodeBlock *) PG_GETARG_POINTER(0); - FunctionCallInfoData fake_fcinfo; + STACK_FCINFO_FOR_ARGS(fake_fcinfo, 0); FmgrInfo flinfo; plperl_proc_desc desc; plperl_call_data *volatile save_call_data = current_call_data; @@ -1899,10 +1899,10 @@ plperl_inline_handler(PG_FUNCTION_ARGS) * 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_fcinfodata, 0, sizeof(fake_fcinfodata)); 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; @@ -1920,7 +1920,7 @@ plperl_inline_handler(PG_FUNCTION_ARGS) 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 */ @@ -1940,7 +1940,7 @@ plperl_inline_handler(PG_FUNCTION_ARGS) 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); @@ -2194,11 +2194,11 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo) 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].datum); PUSHs(sv_2mortal(sv)); } @@ -2208,15 +2208,15 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo) 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].datum, 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].datum)); else { char *tmp; tmp = OutputFunctionCall(&(desc->arg_out_func[i]), - fcinfo->arg[i]); + fcinfo->args[i].datum); sv = cstr2sv(tmp); pfree(tmp); } diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 45526383f25..665118cfe82 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -489,8 +489,8 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n]; assign_simple_var(&estate, var, - fcinfo->arg[i], - fcinfo->argnull[i], + fcinfo->args[i].datum, + fcinfo->args[i].isnull, false); /* @@ -541,12 +541,12 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, { 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].datum); } else { diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c index 47ed95dcc60..d1a8c395ffd 100644 --- a/src/pl/plpython/plpy_exec.c +++ b/src/pl/plpython/plpy_exec.c @@ -436,10 +436,10 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc) { 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].datum); if (arg == NULL) { diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index e2fa43b890d..3ee2a7fd4a2 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -601,7 +601,8 @@ call_pltcl_start_proc(Oid prolang, bool pltrusted) Form_pg_proc procStruct; AclResult aclresult; FmgrInfo finfo; - FunctionCallInfoData fcinfo; + STACK_FCINFO_FOR_ARGS(fcinfo, 3); + PgStat_FunctionCallUsage fcusage; /* select appropriate GUC */ @@ -662,11 +663,11 @@ call_pltcl_start_proc(Oid prolang, bool pltrusted) */ 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 */ @@ -873,7 +874,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, /************************************************** * 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 { @@ -884,7 +885,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, HeapTupleData tmptup; Tcl_Obj *list_tmp; - td = DatumGetHeapTupleHeader(fcinfo->arg[i]); + td = DatumGetHeapTupleHeader(fcinfo->args[i].datum); /* Extract rowtype info and find a tupdesc */ tupType = HeapTupleHeaderGetTypeId(td); tupTypmod = HeapTupleHeaderGetTypMod(td); @@ -905,14 +906,14 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, * 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].datum); UTF_BEGIN; Tcl_ListObjAppendElement(NULL, tcl_cmd, Tcl_NewStringObj(UTF_E2U(tmp), -1)); -- 2.18.0.rc2.dirty --kkvoa4kudrvr5owc Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v2-0002-Replace-fmgr.-ch-duplication-with-macro-magic.patch"