]> granicus.if.org Git - postgresql/blob - src/backend/utils/fmgr/funcapi.c
OK, some of these syntax errors should be given other codes.
[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-2003, PostgreSQL Global Development Group
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/fmgr/funcapi.c,v 1.11 2003/09/15 20:03:37 petere Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include "funcapi.h"
17 #include "catalog/pg_type.h"
18 #include "utils/syscache.h"
19
20
21 /*
22  * init_MultiFuncCall
23  * Create an empty FuncCallContext data structure
24  * and do some other basic Multi-function call setup
25  * and error checking
26  */
27 FuncCallContext *
28 init_MultiFuncCall(PG_FUNCTION_ARGS)
29 {
30         FuncCallContext *retval;
31
32         /*
33          * Bail if we're called in the wrong context
34          */
35         if (fcinfo->resultinfo == NULL || !IsA(fcinfo->resultinfo, ReturnSetInfo))
36                 ereport(ERROR,
37                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
38                                  errmsg("set-valued function called in context that cannot accept a set")));
39
40         if (fcinfo->flinfo->fn_extra == NULL)
41         {
42                 /*
43                  * First call
44                  *
45                  * Allocate suitably long-lived space and zero it
46                  */
47                 retval = (FuncCallContext *)
48                         MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
49                                                            sizeof(FuncCallContext));
50                 MemSet(retval, 0, sizeof(FuncCallContext));
51
52                 /*
53                  * initialize the elements
54                  */
55                 retval->call_cntr = 0;
56                 retval->max_calls = 0;
57                 retval->slot = NULL;
58                 retval->user_fctx = NULL;
59                 retval->attinmeta = NULL;
60                 retval->multi_call_memory_ctx = fcinfo->flinfo->fn_mcxt;
61
62                 /*
63                  * save the pointer for cross-call use
64                  */
65                 fcinfo->flinfo->fn_extra = retval;
66         }
67         else
68         {
69                 /* second and subsequent calls */
70                 elog(ERROR, "init_MultiFuncCall may not be called more than once");
71
72                 /* never reached, but keep compiler happy */
73                 retval = NULL;
74         }
75
76         return retval;
77 }
78
79 /*
80  * per_MultiFuncCall
81  *
82  * Do Multi-function per-call setup
83  */
84 FuncCallContext *
85 per_MultiFuncCall(PG_FUNCTION_ARGS)
86 {
87         FuncCallContext *retval = (FuncCallContext *) fcinfo->flinfo->fn_extra;
88
89         /*
90          * Clear the TupleTableSlot, if present.  This is for safety's sake:
91          * the Slot will be in a long-lived context (it better be, if the
92          * FuncCallContext is pointing to it), but in most usage patterns the
93          * tuples stored in it will be in the function's per-tuple context. So
94          * at the beginning of each call, the Slot will hold a dangling
95          * pointer to an already-recycled tuple.  We clear it out here.  (See
96          * also the definition of TupleGetDatum() in funcapi.h!)
97          */
98         if (retval->slot != NULL)
99                 ExecClearTuple(retval->slot);
100
101         return retval;
102 }
103
104 /*
105  * end_MultiFuncCall
106  * Clean up after init_MultiFuncCall
107  */
108 void
109 end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
110 {
111         /* unbind from fcinfo */
112         fcinfo->flinfo->fn_extra = NULL;
113
114         /*
115          * Caller is responsible to free up memory for individual struct
116          * elements other than att_in_funcinfo and elements.
117          */
118         if (funcctx->attinmeta != NULL)
119                 pfree(funcctx->attinmeta);
120
121         pfree(funcctx);
122 }