From 27bce577669a958fe557f62bf051fa0f4ed4ecfb Mon Sep 17 00:00:00 2001 From: Bruce Momjian <bruce@momjian.us> Date: Thu, 20 Jun 2002 20:37:00 +0000 Subject: [PATCH] Add missing SRF file. --- src/backend/utils/fmgr/funcapi.c | 122 +++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 src/backend/utils/fmgr/funcapi.c diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c new file mode 100644 index 00000000000..bd65c3911c7 --- /dev/null +++ b/src/backend/utils/fmgr/funcapi.c @@ -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); +} -- GitLab