aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2002-06-20 20:37:00 +0000
committerBruce Momjian <bruce@momjian.us>2002-06-20 20:37:00 +0000
commit27bce577669a958fe557f62bf051fa0f4ed4ecfb (patch)
treedd5ea4cce4f04e84afc417ba4fb6a287186281dc /src
parent95712b15b11e3cdb553b544c450c46af1078bca9 (diff)
downloadpostgresql-27bce577669a958fe557f62bf051fa0f4ed4ecfb.tar.gz
postgresql-27bce577669a958fe557f62bf051fa0f4ed4ecfb.zip
Add missing SRF file.
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/fmgr/funcapi.c122
1 files changed, 122 insertions, 0 deletions
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);
+}