Re: Set Returning C-Function with cache over multiple calls (with different arguments)

From: Thilo Schneider <kontakt(at)thiloschneider(dot)net>
To: pgsql-general(at)postgresql(dot)org
Subject: Re: Set Returning C-Function with cache over multiple calls (with different arguments)
Date: 2010-01-11 13:33:03
Message-ID: 0B1C85E5-77BF-4318-AFAE-E1C1E596AFFB@thiloschneider.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

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

In response to

Browse pgsql-general by date

  From Date Subject
Next Message A. Kretschmer 2010-01-11 13:44:55 Re: How to get DATE in server locale format
Previous Message Scott Marlowe 2010-01-11 13:31:14 Re: Huge iowait during checkpoint finish