revised sample SRF C function; proposed SRF API

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

Responses

Browse pgsql-hackers by date

  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

Browse pgsql-patches by date

  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