]> granicus.if.org Git - postgresql/blob - src/backend/utils/fmgr/funcapi.c
Adjust nodeFunctionscan.c to reset transient memory context between calls
[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  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/fmgr/funcapi.c,v 1.4 2002/08/29 17:14:33 tgl 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                 elog(ERROR, "function called in context that does not accept a set result");
37
38         if (fcinfo->flinfo->fn_extra == NULL)
39         {
40                 /*
41                  * First call
42                  *
43                  * Allocate suitably long-lived space and zero it
44                  */
45                 retval = (FuncCallContext *)
46                         MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
47                                                            sizeof(FuncCallContext));
48                 MemSet(retval, 0, sizeof(FuncCallContext));
49
50                 /*
51                  * initialize the elements
52                  */
53                 retval->call_cntr = 0;
54                 retval->max_calls = 0;
55                 retval->slot = NULL;
56                 retval->user_fctx = NULL;
57                 retval->attinmeta = NULL;
58                 retval->multi_call_memory_ctx = fcinfo->flinfo->fn_mcxt;
59
60                 /*
61                  * save the pointer for cross-call use
62                  */
63                 fcinfo->flinfo->fn_extra = retval;
64         }
65         else    /* second and subsequent calls */
66         {
67                 elog(ERROR, "init_MultiFuncCall may not be called more than once");
68
69                 /* never reached, but keep compiler happy */
70                 retval = NULL;
71         }
72
73         return retval;
74 }
75
76 /*
77  * per_MultiFuncCall
78  * 
79  * Do Multi-function per-call setup
80  */
81 FuncCallContext *
82 per_MultiFuncCall(PG_FUNCTION_ARGS)
83 {
84         FuncCallContext *retval = (FuncCallContext *) fcinfo->flinfo->fn_extra;
85
86         /* make sure we start with a fresh slot */
87         if(retval->slot != NULL)
88                 ExecClearTuple(retval->slot);
89
90         return retval;
91 }
92
93 /*
94  * end_MultiFuncCall
95  * Clean up after init_MultiFuncCall
96  */
97 void
98 end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
99 {
100         /* unbind from fcinfo */
101         fcinfo->flinfo->fn_extra = NULL;
102
103         /*
104          * Caller is responsible to free up memory for individual
105          * struct elements other than att_in_funcinfo and elements.
106          */
107         if (funcctx->attinmeta != NULL)
108                 pfree(funcctx->attinmeta);
109
110         pfree(funcctx);
111 }