Dear list,
I solved my own problem - as so often, once you write it down and press the send button you get the idea.
The problem was:
> Currently I am working on a user C-Function which should create a cache object on the first call and afterwards
returna set of computed values for each argument combination it is called with.
>
> My Problem is how to get the cache object saved over multiple calls. Without the SRF I could use
fcinfo->flinfo->fn_extrafor my pointer to the data. This is now used by the FuncCallContext structure. This structure
isdestroyed every time SRF_RETURN_DONE is called, thus user_fctx also is not the way to go.
My solution:
--------------------------------------------------- snip ---------------------------------------------------
struct myData {
FuncCallContext *funcctx;
// own Data
int cachedObject;
} myData
PG_FUNCTION_INFO_V1(test);
Datum test(PG_FUNCTION_ARGS)
{
MemoryContext old_context;
FuncCallContext *funcctx;
myData *str;
// Get fn_extra
str = fcinfo->flinfo->fn_extra;
if ( ! str) {
elog(NOTICE, "create new");
old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
// Fill str with data around here ...
MemoryContextSwitchTo(old_context);
str->funcctx = NULL;
}
// This is the situation the SRF-macros expect:
fcinfo->flinfo->fn_extra = str->funcctx;
if (SRF_IS_FIRSTCALL()) {
funcctx = SRF_FIRSTCALL_INIT();
// Your commands
}
funcctx = SRF_PERCALL_SETUP();
// This is the macro SRF_RETURN_DONE(funcctx);
// Before we finally return we save our str in fn_extra and fn_extra in str->funcctx.
do {
ReturnSetInfo *rsi;
end_MultiFuncCall(fcinfo, funcctx);
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
rsi->isDone = ExprEndResult;
// -- Modify macro here --
str->funcctx = fcinfo->flinfo->fn_extra;
fcinfo->flinfo->fn_extra = str;
// -- End modification --
PG_RETURN_NULL();
} while (0);
// Of course, SRF_RETURN_DATUM has to be adapted the same way!
}
--------------------------------------------------- snip ---------------------------------------------------
Regards,
Thilo Schneider