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 return a 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_extra for my pointer to the data. This 
> is now used by the FuncCallContext structure. This structure is destroyed 
> 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
-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general

Reply via email to