1 /*-------------------------------------------------------------------------
4 * Utility and convenience functions for fmgr functions that return
5 * sets and/or composite types.
7 * Copyright (c) 2002, PostgreSQL Global Development Group
9 *-------------------------------------------------------------------------
13 #include "catalog/pg_type.h"
14 #include "utils/syscache.h"
18 * Create an empty FuncCallContext data structure
19 * and do some other basic Multi-function call setup
23 init_MultiFuncCall(PG_FUNCTION_ARGS)
25 FuncCallContext *retval;
28 * Bail if we're called in the wrong context
30 if (fcinfo->resultinfo == NULL || !IsA(fcinfo->resultinfo, ReturnSetInfo))
31 elog(ERROR, "function called in context that does not accept a set result");
33 if (fcinfo->flinfo->fn_extra == NULL)
38 MemoryContext oldcontext;
40 /* switch to the appropriate memory context */
41 oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
44 * allocate space and zero it
46 retval = (FuncCallContext *) palloc(sizeof(FuncCallContext));
47 MemSet(retval, 0, sizeof(FuncCallContext));
50 * initialize the elements
52 retval->call_cntr = 0;
53 retval->max_calls = 0;
55 retval->user_fctx = NULL;
56 retval->attinmeta = NULL;
57 retval->fmctx = fcinfo->flinfo->fn_mcxt;
60 * save the pointer for cross-call use
62 fcinfo->flinfo->fn_extra = retval;
64 /* back to the original memory context */
65 MemoryContextSwitchTo(oldcontext);
67 else /* second and subsequent calls */
69 elog(ERROR, "init_MultiFuncCall may not be called more than once");
71 /* never reached, but keep compiler happy */
81 * Do Multi-function per-call setup
84 per_MultiFuncCall(PG_FUNCTION_ARGS)
86 FuncCallContext *retval = (FuncCallContext *) fcinfo->flinfo->fn_extra;
88 /* make sure we start with a fresh slot */
89 if(retval->slot != NULL)
90 ExecClearTuple(retval->slot);
97 * Clean up after init_MultiFuncCall
100 end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
102 MemoryContext oldcontext;
104 /* unbind from fcinfo */
105 fcinfo->flinfo->fn_extra = NULL;
108 * Caller is responsible to free up memory for individual
109 * struct elements other than att_in_funcinfo and elements.
111 oldcontext = MemoryContextSwitchTo(funcctx->fmctx);
113 if (funcctx->attinmeta != NULL)
114 pfree(funcctx->attinmeta);
118 MemoryContextSwitchTo(oldcontext);
122 get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem)
127 typeTuple = SearchSysCache(TYPEOID,
128 ObjectIdGetDatum(typeid),
130 if (!HeapTupleIsValid(typeTuple))
131 elog(ERROR, "get_type_metadata: Cache lookup of type %u failed", typeid);
133 typtup = (Form_pg_type) GETSTRUCT(typeTuple);
135 *attinfuncid = typtup->typinput;
136 *attelem = typtup->typelem;
138 ReleaseSysCache(typeTuple);