]> granicus.if.org Git - postgresql/blob - src/include/funcapi.h
A visit from the message-style police ...
[postgresql] / src / include / funcapi.h
1 /*-------------------------------------------------------------------------
2  *
3  * funcapi.h
4  *        Definitions for functions which return composite type and/or sets
5  *
6  * This file must be included by all Postgres modules that either define
7  * or call FUNCAPI-callable functions or macros.
8  *
9  *
10  * Copyright (c) 2002, PostgreSQL Global Development Group
11  *
12  * $Id: funcapi.h,v 1.8 2002/09/04 20:31:36 momjian Exp $
13  *
14  *-------------------------------------------------------------------------
15  */
16 #ifndef FUNCAPI_H
17 #define FUNCAPI_H
18
19 #include "fmgr.h"
20 #include "access/tupdesc.h"
21 #include "executor/executor.h"
22 #include "executor/tuptable.h"
23
24
25 /*-------------------------------------------------------------------------
26  *      Support to ease writing Functions returning composite types
27  *-------------------------------------------------------------------------
28  *
29  * This struct holds arrays of individual attribute information
30  * needed to create a tuple from raw C strings. It also requires
31  * a copy of the TupleDesc. The information carried here
32  * is derived from the TupleDesc, but it is stored here to
33  * avoid redundant cpu cycles on each call to an SRF.
34  */
35 typedef struct AttInMetadata
36 {
37         /* full TupleDesc */
38         TupleDesc       tupdesc;
39
40         /* array of attribute type input function finfo */
41         FmgrInfo   *attinfuncs;
42
43         /* array of attribute type typelem */
44         Oid                *attelems;
45
46         /* array of attribute typmod */
47         int32      *atttypmods;
48 } AttInMetadata;
49
50 /*-------------------------------------------------------------------------
51  *              Support struct to ease writing Set Returning Functions (SRFs)
52  *-------------------------------------------------------------------------
53  *
54  * This struct holds function context for Set Returning Functions.
55  * Use fn_extra to hold a pointer to it across calls
56  */
57 typedef struct FuncCallContext
58 {
59         /*
60          * Number of times we've been called before.
61          *
62          * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and
63          * incremented for you every time SRF_RETURN_NEXT() is called.
64          */
65         uint32          call_cntr;
66
67         /*
68          * OPTIONAL maximum number of calls
69          *
70          * max_calls is here for convenience ONLY and setting it is OPTIONAL. If
71          * not set, you must provide alternative means to know when the
72          * function is done.
73          */
74         uint32          max_calls;
75
76         /*
77          * OPTIONAL pointer to result slot
78          *
79          * slot is for use when returning tuples (i.e. composite data types) and
80          * is not needed when returning base (i.e. scalar) data types.
81          */
82         TupleTableSlot *slot;
83
84         /*
85          * OPTIONAL pointer to misc user provided context info
86          *
87          * user_fctx is for use as a pointer to your own struct to retain
88          * arbitrary context information between calls for your function.
89          */
90         void       *user_fctx;
91
92         /*
93          * OPTIONAL pointer to struct containing arrays of attribute type
94          * input metainfo
95          *
96          * attinmeta is for use when returning tuples (i.e. composite data types)
97          * and is not needed when returning base (i.e. scalar) data types. It
98          * is ONLY needed if you intend to use BuildTupleFromCStrings() to
99          * create the return tuple.
100          */
101         AttInMetadata *attinmeta;
102
103         /*
104          * memory context used for structures which must live for multiple
105          * calls
106          *
107          * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used
108          * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory
109          * context for any memory that is to be re-used across multiple calls
110          * of the SRF.
111          */
112         MemoryContext multi_call_memory_ctx;
113
114 } FuncCallContext;
115
116 /*----------
117  *      Support to ease writing Functions returning composite types
118  *
119  * External declarations:
120  * TupleDesc RelationNameGetTupleDesc(const char *relname) - Use to get a
121  *              TupleDesc based on a specified relation.
122  * TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases) - Use to get a
123  *              TupleDesc based on a type OID. This can be used to get
124  *              a TupleDesc for a base (scalar) or composite (relation) type.
125  * TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc) - Initialize a slot
126  *              given a TupleDesc.
127  * AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc) - Build an
128  *              AttInMetadata struct based on the given TupleDesc. AttInMetadata can
129  *              be used in conjunction with C strings to produce a properly formed
130  *              tuple. Store the metadata here for use across calls to avoid redundant
131  *              work.
132  * HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) -
133  *              build a HeapTuple given user data in C string form. values is an array
134  *              of C strings, one for each attribute of the return tuple.
135  *
136  * Macro declarations:
137  * TupleGetDatum(TupleTableSlot *slot, HeapTuple tuple) - get a Datum
138  *              given a tuple and a slot.
139  *----------
140  */
141
142 /* from tupdesc.c */
143 extern TupleDesc RelationNameGetTupleDesc(const char *relname);
144 extern TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases);
145
146 /* from execTuples.c */
147 extern TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc);
148 extern AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc);
149 extern HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values);
150
151 /*
152  * Note we pass shouldFree = false; this is needed because the tuple will
153  * typically be in a shorter-lived memory context than the TupleTableSlot.
154  */
155 #define TupleGetDatum(_slot, _tuple) \
156         PointerGetDatum(ExecStoreTuple(_tuple, _slot, InvalidBuffer, false))
157
158
159 /*----------
160  *              Support for Set Returning Functions (SRFs)
161  *
162  * The basic API for SRFs looks something like:
163  *
164  * Datum
165  * my_Set_Returning_Function(PG_FUNCTION_ARGS)
166  * {
167  *      FuncCallContext    *funcctx;
168  *      Datum                           result;
169  *      MemoryContext           oldcontext;
170  *      <user defined declarations>
171  *
172  *      if (SRF_IS_FIRSTCALL())
173  *      {
174  *              funcctx = SRF_FIRSTCALL_INIT();
175  *              // switch context when allocating stuff to be used in later calls
176  *              oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
177  *              <user defined code>
178  *              <if returning composite>
179  *                      <obtain slot>
180  *                      funcctx->slot = slot;
181  *              <endif returning composite>
182  *              <user defined code>
183  *              // return to original context when allocating transient memory
184  *              MemoryContextSwitchTo(oldcontext);
185  *      }
186  *      <user defined code>
187  *      funcctx = SRF_PERCALL_SETUP();
188  *      <user defined code>
189  *
190  *      if (funcctx->call_cntr < funcctx->max_calls)
191  *      {
192  *              <user defined code>
193  *              <obtain result Datum>
194  *              SRF_RETURN_NEXT(funcctx, result);
195  *      }
196  *      else
197  *              SRF_RETURN_DONE(funcctx);
198  * }
199  *
200  *----------
201  */
202
203 /* from funcapi.c */
204 extern FuncCallContext *init_MultiFuncCall(PG_FUNCTION_ARGS);
205 extern FuncCallContext *per_MultiFuncCall(PG_FUNCTION_ARGS);
206 extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx);
207
208 #define SRF_IS_FIRSTCALL() (fcinfo->flinfo->fn_extra == NULL)
209
210 #define SRF_FIRSTCALL_INIT() init_MultiFuncCall(fcinfo)
211
212 #define SRF_PERCALL_SETUP() per_MultiFuncCall(fcinfo)
213
214 #define SRF_RETURN_NEXT(_funcctx, _result) \
215         do { \
216                 ReturnSetInfo      *rsi; \
217                 (_funcctx)->call_cntr++; \
218                 rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
219                 rsi->isDone = ExprMultipleResult; \
220                 PG_RETURN_DATUM(_result); \
221         } while (0)
222
223 #define  SRF_RETURN_DONE(_funcctx) \
224         do { \
225                 ReturnSetInfo      *rsi; \
226                 end_MultiFuncCall(fcinfo, _funcctx); \
227                 rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
228                 rsi->isDone = ExprEndResult; \
229                 PG_RETURN_NULL(); \
230         } while (0)
231
232 #endif   /* FUNCAPI_H */