~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/utils/fmgr/funcapi.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-2005, PostgreSQL Global Development Group
 
8
 *
 
9
 * IDENTIFICATION
 
10
 *        $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.18 2005-01-01 05:43:08 momjian 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
static void shutdown_MultiFuncCall(Datum arg);
 
21
 
 
22
/*
 
23
 * init_MultiFuncCall
 
24
 * Create an empty FuncCallContext data structure
 
25
 * and do some other basic Multi-function call setup
 
26
 * and error checking
 
27
 */
 
28
FuncCallContext *
 
29
init_MultiFuncCall(PG_FUNCTION_ARGS)
 
30
{
 
31
        FuncCallContext *retval;
 
32
 
 
33
        /*
 
34
         * Bail if we're called in the wrong context
 
35
         */
 
36
        if (fcinfo->resultinfo == NULL || !IsA(fcinfo->resultinfo, ReturnSetInfo))
 
37
                ereport(ERROR,
 
38
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
39
                                 errmsg("set-valued function called in context that cannot accept a set")));
 
40
 
 
41
        if (fcinfo->flinfo->fn_extra == NULL)
 
42
        {
 
43
                /*
 
44
                 * First call
 
45
                 */
 
46
                ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
 
47
 
 
48
                /*
 
49
                 * Allocate suitably long-lived space and zero it
 
50
                 */
 
51
                retval = (FuncCallContext *)
 
52
                        MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt,
 
53
                                                                   sizeof(FuncCallContext));
 
54
 
 
55
                /*
 
56
                 * initialize the elements
 
57
                 */
 
58
                retval->call_cntr = 0;
 
59
                retval->max_calls = 0;
 
60
                retval->slot = NULL;
 
61
                retval->user_fctx = NULL;
 
62
                retval->attinmeta = NULL;
 
63
                retval->tuple_desc = NULL;
 
64
                retval->multi_call_memory_ctx = fcinfo->flinfo->fn_mcxt;
 
65
 
 
66
                /*
 
67
                 * save the pointer for cross-call use
 
68
                 */
 
69
                fcinfo->flinfo->fn_extra = retval;
 
70
 
 
71
                /*
 
72
                 * Ensure we will get shut down cleanly if the exprcontext is not
 
73
                 * run to completion.
 
74
                 */
 
75
                RegisterExprContextCallback(rsi->econtext,
 
76
                                                                        shutdown_MultiFuncCall,
 
77
                                                                        PointerGetDatum(fcinfo->flinfo));
 
78
        }
 
79
        else
 
80
        {
 
81
                /* second and subsequent calls */
 
82
                elog(ERROR, "init_MultiFuncCall may not be called more than once");
 
83
 
 
84
                /* never reached, but keep compiler happy */
 
85
                retval = NULL;
 
86
        }
 
87
 
 
88
        return retval;
 
89
}
 
90
 
 
91
/*
 
92
 * per_MultiFuncCall
 
93
 *
 
94
 * Do Multi-function per-call setup
 
95
 */
 
96
FuncCallContext *
 
97
per_MultiFuncCall(PG_FUNCTION_ARGS)
 
98
{
 
99
        FuncCallContext *retval = (FuncCallContext *) fcinfo->flinfo->fn_extra;
 
100
 
 
101
        /*
 
102
         * Clear the TupleTableSlot, if present.  This is for safety's sake:
 
103
         * the Slot will be in a long-lived context (it better be, if the
 
104
         * FuncCallContext is pointing to it), but in most usage patterns the
 
105
         * tuples stored in it will be in the function's per-tuple context. So
 
106
         * at the beginning of each call, the Slot will hold a dangling
 
107
         * pointer to an already-recycled tuple.  We clear it out here.
 
108
         *
 
109
         * Note: use of retval->slot is obsolete as of 8.0, and we expect that it
 
110
         * will always be NULL.  This is just here for backwards compatibility
 
111
         * in case someone creates a slot anyway.
 
112
         */
 
113
        if (retval->slot != NULL)
 
114
                ExecClearTuple(retval->slot);
 
115
 
 
116
        return retval;
 
117
}
 
118
 
 
119
/*
 
120
 * end_MultiFuncCall
 
121
 * Clean up after init_MultiFuncCall
 
122
 */
 
123
void
 
124
end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
 
125
{
 
126
        ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
 
127
 
 
128
        /* Deregister the shutdown callback */
 
129
        UnregisterExprContextCallback(rsi->econtext,
 
130
                                                                  shutdown_MultiFuncCall,
 
131
                                                                  PointerGetDatum(fcinfo->flinfo));
 
132
 
 
133
        /* But use it to do the real work */
 
134
        shutdown_MultiFuncCall(PointerGetDatum(fcinfo->flinfo));
 
135
}
 
136
 
 
137
/*
 
138
 * shutdown_MultiFuncCall
 
139
 * Shutdown function to clean up after init_MultiFuncCall
 
140
 */
 
141
static void
 
142
shutdown_MultiFuncCall(Datum arg)
 
143
{
 
144
        FmgrInfo   *flinfo = (FmgrInfo *) DatumGetPointer(arg);
 
145
        FuncCallContext *funcctx = (FuncCallContext *) flinfo->fn_extra;
 
146
 
 
147
        /* unbind from flinfo */
 
148
        flinfo->fn_extra = NULL;
 
149
 
 
150
        /*
 
151
         * Caller is responsible to free up memory for individual struct
 
152
         * elements other than att_in_funcinfo and elements.
 
153
         */
 
154
        if (funcctx->attinmeta != NULL)
 
155
                pfree(funcctx->attinmeta);
 
156
 
 
157
        pfree(funcctx);
 
158
}