Add missing SRF file.
authorBruce Momjian
Thu, 20 Jun 2002 20:37:00 +0000 (20:37 +0000)
committerBruce Momjian
Thu, 20 Jun 2002 20:37:00 +0000 (20:37 +0000)
src/backend/utils/fmgr/funcapi.c [new file with mode: 0644]

diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
new file mode 100644 (file)
index 0000000..bd65c39
--- /dev/null
@@ -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);
+}