Add missing SRF file.

This commit is contained in:
Bruce Momjian 2002-06-20 20:37:00 +00:00
parent 95712b15b1
commit 27bce57766
1 changed files with 122 additions and 0 deletions

View File

@ -0,0 +1,122 @@
/*-------------------------------------------------------------------------
*
* funcapi.c
* Utility and convenience functions for fmgr functions that return
* sets and/or composite types.
*
* Copyright (c) 2002, PostgreSQL Global Development Group
*
*-------------------------------------------------------------------------
*/
#include "funcapi.h"
#include "catalog/pg_type.h"
#include "utils/syscache.h"
/*
* init_MultiFuncCall
* Create an empty FuncCallContext data structure
* and do some other basic Multi-function call setup
* and error checking
*/
FuncCallContext *
init_MultiFuncCall(PG_FUNCTION_ARGS)
{
FuncCallContext *retval;
/*
* Bail if we're called in the wrong context
*/
if (fcinfo->resultinfo == NULL || !IsA(fcinfo->resultinfo, ReturnSetInfo))
elog(ERROR, "function called in context that does not accept a set result");
if (fcinfo->flinfo->fn_extra == NULL)
{
/*
* First call
*/
MemoryContext oldcontext;
/* switch to the appropriate memory context */
oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
/*
* allocate space and zero it
*/
retval = (FuncCallContext *) palloc(sizeof(FuncCallContext));
MemSet(retval, 0, sizeof(FuncCallContext));
/*
* initialize the elements
*/
retval->call_cntr = 0;
retval->max_calls = 0;
retval->slot = NULL;
retval->fctx = NULL;
retval->attinmeta = NULL;
retval->fmctx = fcinfo->flinfo->fn_mcxt;
/*
* save the pointer for cross-call use
*/
fcinfo->flinfo->fn_extra = retval;
/* back to the original memory context */
MemoryContextSwitchTo(oldcontext);
}
else /* second and subsequent calls */
{
elog(ERROR, "init_MultiFuncCall may not be called more than once");
/* never reached, but keep compiler happy */
retval = NULL;
}
return retval;
}
/*
* end_MultiFuncCall
* Clean up after init_MultiFuncCall
*/
void
end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
{
MemoryContext oldcontext;
/* unbind from fcinfo */
fcinfo->flinfo->fn_extra = NULL;
/*
* Caller is responsible to free up memory for individual
* struct elements other than att_in_funcinfo and elements.
*/
oldcontext = MemoryContextSwitchTo(funcctx->fmctx);
if (funcctx->attinmeta != NULL)
pfree(funcctx->attinmeta);
pfree(funcctx);
MemoryContextSwitchTo(oldcontext);
}
void
get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem)
{
HeapTuple typeTuple;
Form_pg_type typtup;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeid),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "get_type_metadata: Cache lookup of type %u failed", typeid);
typtup = (Form_pg_type) GETSTRUCT(typeTuple);
*attinfuncid = typtup->typinput;
*attelem = typtup->typelem;
ReleaseSysCache(typeTuple);
}