From: | Joe Conway <mail(at)joeconway(dot)com> |
---|---|
To: | pgsql-hackers <pgsql-hackers(at)postgreSQL(dot)org> |
Subject: | revised sample SRF C function; proposed SRF API |
Date: | 2002-05-27 01:30:32 |
Message-ID: | 3CF18C38.9050200@joeconway.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers pgsql-patches |
Here is a revised patch for a sample C function returning setof
composite. (Same comments as last time -- It is a clone of SHOW ALL as
an SRF. For the moment, the function is implemented as contrib/showguc,
although a few minor changes to guc.c and guc.h were required to support
it.)
This version includes pieces that may be appropriate for fmgr.c and
fmgr.h, to hide some of the ugliness and facilitate writing C functions
which return setof composite. The API is something like this:
An SRF written in C must define a variable of type (FuncCallContext *).
The structure of FuncCallContext looks like:
typedef struct
{
/* Number of times we've been called before */
uint call_cntr;
/* Maximum number of calls */
uint max_calls;
/* pointer to result slot */
TupleTableSlot *slot;
/* pointer to misc context info */
void *fctx;
/* pointer to array of attribute "type"in finfo */
FmgrInfo *att_in_funcinfo;
/* pointer to array of attribute type typelem */
Oid *elements;
/* memory context used to initialize structure */
MemoryContext fmctx;
} FuncCallContext;
The first line after the function declarations should be:
FUNC_MULTIPLE_RESULT(funcctx, relname, max_calls, misc_ctx);
where
funcctx is the pointer to FuncCallContext. This is required.
relname is the relation name for the composite type the function
returns. This is required.
max_calls is the maximum number of times the function is expected
to return results. You don't have to provide or use this.
misc_ctx is a pointer available for the user to store anything needed
to retain context from call to call (i.e. this is what you
previously might have assigned to fcinfo->flinfo->fn_extra).
You don't have to provide or use this.
Next, use funcctx->call_cntr and funcctx->max_calls (or whatever method
you want) to determine whether or not the function is done returning
results. If not, prepare an array of C strings representing the
attribute values of your return tuple, and call:
FUNC_BUILD_SLOT(values, funcctx);
This applies the attribute "in" functions to your values, and stores the
results in a TupleTableSlot.
Next, clean up as appropriate, and call:
FUNC_RETURN_NEXT(funcctx);
This increments funcctx->call_cntr in preparation for the next call,
sets rsi->isDone = ExprMultipleResult to let the caller know we're not
done yet, and returns the slot.
Finally, when funcctx->call_cntr = funcctx->max_calls, call:
FUNC_RETURN_DONE(funcctx);
This does some cleanup, sets rsi->isDone = ExprEndResult, and returns a
NULL slot.
I made some changes to pull as much into the first call initialization
as possible to save redundant work on subsequent calls. For the 96 rows
returned by this function, EXPLAIN ANALYZE time went from ~1.6 msec
using the first patch, to ~0.9 msec using this one.
Comments? Should this (maybe with a few tweaks) go into fmgr.c and
fmgr.h as the SRF API?
Thanks,
Joe
Attachment | Content-Type | Size |
---|---|---|
showguc.2002.05.26.1.patch | text/plain | 24.1 KB |
From | Date | Subject | |
---|---|---|---|
Next Message | Joe Conway | 2002-05-27 02:26:36 | Re: revised sample SRF C function; proposed SRF API |
Previous Message | Tatsuo Ishii | 2002-05-27 01:11:40 | Re: pgstatindex |
From | Date | Subject | |
---|---|---|---|
Next Message | Joe Conway | 2002-05-27 02:26:36 | Re: revised sample SRF C function; proposed SRF API |
Previous Message | Joe Conway | 2002-05-26 16:55:06 | Re: SRF rescan testing |