]> granicus.if.org Git - postgresql/blob - src/backend/utils/fmgr/funcapi.c
Add missing SRF file.
[postgresql] / src / backend / utils / fmgr / funcapi.c
1 /*-------------------------------------------------------------------------
2  *
3  * funcapi.c
4  *        Utility and convenience functions for fmgr functions that return
5  *        sets and/or composite types.
6  *
7  * Copyright (c) 2002, PostgreSQL Global Development Group
8  *
9  *-------------------------------------------------------------------------
10  */
11
12 #include "funcapi.h"
13 #include "catalog/pg_type.h"
14 #include "utils/syscache.h"
15
16 /*
17  * init_MultiFuncCall
18  * Create an empty FuncCallContext data structure
19  * and do some other basic Multi-function call setup
20  * and error checking
21  */
22 FuncCallContext *
23 init_MultiFuncCall(PG_FUNCTION_ARGS)
24 {
25         FuncCallContext *retval;
26
27         /*
28          * Bail if we're called in the wrong context
29          */
30         if (fcinfo->resultinfo == NULL || !IsA(fcinfo->resultinfo, ReturnSetInfo))
31                 elog(ERROR, "function called in context that does not accept a set result");
32
33         if (fcinfo->flinfo->fn_extra == NULL)
34         {
35                 /*
36                  * First call
37                  */
38                 MemoryContext oldcontext;
39
40                 /* switch to the appropriate memory context */
41                 oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
42
43                 /*
44                  * allocate space and zero it
45                  */
46                 retval = (FuncCallContext *) palloc(sizeof(FuncCallContext));
47                 MemSet(retval, 0, sizeof(FuncCallContext));
48
49                 /*
50                  * initialize the elements
51                  */
52                 retval->call_cntr = 0;
53                 retval->max_calls = 0;
54                 retval->slot = NULL;
55                 retval->fctx = NULL;
56                 retval->attinmeta = NULL;
57                 retval->fmctx = fcinfo->flinfo->fn_mcxt;
58
59                 /*
60                  * save the pointer for cross-call use
61                  */
62                 fcinfo->flinfo->fn_extra = retval;
63
64                 /* back to the original memory context */
65                 MemoryContextSwitchTo(oldcontext);
66         }
67         else    /* second and subsequent calls */
68         {
69                 elog(ERROR, "init_MultiFuncCall may not be called more than once");
70
71                 /* never reached, but keep compiler happy */
72                 retval = NULL;
73         }
74
75         return retval;
76 }
77
78 /*
79  * end_MultiFuncCall
80  * Clean up after init_MultiFuncCall
81  */
82 void
83 end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
84 {
85         MemoryContext oldcontext;
86
87         /* unbind from fcinfo */
88         fcinfo->flinfo->fn_extra = NULL;
89
90         /*
91          * Caller is responsible to free up memory for individual
92          * struct elements other than att_in_funcinfo and elements.
93          */
94         oldcontext = MemoryContextSwitchTo(funcctx->fmctx);
95
96         if (funcctx->attinmeta != NULL)
97                 pfree(funcctx->attinmeta);
98
99         pfree(funcctx);
100
101         MemoryContextSwitchTo(oldcontext);
102 }
103
104 void
105 get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem)
106 {
107         HeapTuple               typeTuple;
108         Form_pg_type    typtup;
109
110         typeTuple = SearchSysCache(TYPEOID,
111                                                            ObjectIdGetDatum(typeid),
112                                                            0, 0, 0);
113         if (!HeapTupleIsValid(typeTuple))
114                 elog(ERROR, "get_type_metadata: Cache lookup of type %u failed", typeid);
115
116         typtup = (Form_pg_type) GETSTRUCT(typeTuple);
117
118         *attinfuncid = typtup->typinput;
119         *attelem = typtup->typelem;
120
121         ReleaseSysCache(typeTuple);
122 }