Skip to content

Commit 7ea5f1d

Browse files
committed
Here is a patch for the Table Function API. It fixes a bug found by Neil
Conway (BuildTupleFromCStrings sets NULL for pass-by-value types when intended value is 0). It also implements some other improvements suggested by Neil. Joe Conway
1 parent a5a8110 commit 7ea5f1d

File tree

3 files changed

+72
-25
lines changed

3 files changed

+72
-25
lines changed

src/backend/executor/execTuples.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.53 2002/06/20 20:29:27 momjian Exp $
18+
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.54 2002/07/18 04:40:30 momjian Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -759,6 +759,7 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
759759
natts = tupdesc->natts;
760760

761761
dvalues = (Datum *) palloc(natts * sizeof(Datum));
762+
nulls = (char *) palloc(natts * sizeof(char));
762763

763764
/* Call the "in" function for each attribute */
764765
for (i = 0; i < natts; i++)
@@ -772,22 +773,18 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
772773
dvalues[i] = FunctionCall3(&attinfuncinfo, CStringGetDatum(values[i]),
773774
ObjectIdGetDatum(attelem),
774775
Int32GetDatum(atttypmod));
776+
nulls[i] = ' ';
775777
}
776778
else
779+
{
777780
dvalues[i] = PointerGetDatum(NULL);
781+
nulls[i] = 'n';
782+
}
778783
}
779784

780785
/*
781786
* Form a tuple
782787
*/
783-
nulls = (char *) palloc(natts * sizeof(char));
784-
for (i = 0; i < natts; i++)
785-
{
786-
if (DatumGetPointer(dvalues[i]) != NULL)
787-
nulls[i] = ' ';
788-
else
789-
nulls[i] = 'n';
790-
}
791788
tuple = heap_formtuple(tupdesc, dvalues, nulls);
792789

793790
return tuple;

src/backend/utils/fmgr/funcapi.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
5252
retval->call_cntr = 0;
5353
retval->max_calls = 0;
5454
retval->slot = NULL;
55-
retval->fctx = NULL;
55+
retval->user_fctx = NULL;
5656
retval->attinmeta = NULL;
5757
retval->fmctx = fcinfo->flinfo->fn_mcxt;
5858

@@ -75,6 +75,23 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
7575
return retval;
7676
}
7777

78+
/*
79+
* per_MultiFuncCall
80+
*
81+
* Do Multi-function per-call setup
82+
*/
83+
FuncCallContext *
84+
per_MultiFuncCall(PG_FUNCTION_ARGS)
85+
{
86+
FuncCallContext *retval = (FuncCallContext *) fcinfo->flinfo->fn_extra;
87+
88+
/* make sure we start with a fresh slot */
89+
if(retval->slot != NULL)
90+
ExecClearTuple(retval->slot);
91+
92+
return retval;
93+
}
94+
7895
/*
7996
* end_MultiFuncCall
8097
* Clean up after init_MultiFuncCall

src/include/funcapi.h

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -65,22 +65,57 @@ typedef struct
6565
*/
6666
typedef struct
6767
{
68-
/* Number of times we've been called before */
68+
/*
69+
* Number of times we've been called before.
70+
*
71+
* call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and
72+
* incremented for you every time SRF_RETURN_NEXT() is called.
73+
*/
6974
uint32 call_cntr;
7075

71-
/* Maximum number of calls */
76+
/*
77+
* OPTIONAL maximum number of calls
78+
*
79+
* max_calls is here for convenience ONLY and setting it is OPTIONAL.
80+
* If not set, you must provide alternative means to know when the
81+
* function is done.
82+
*/
7283
uint32 max_calls;
7384

74-
/* pointer to result slot */
85+
/*
86+
* OPTIONAL pointer to result slot
87+
*
88+
* slot is for use when returning tuples (i.e. composite data types)
89+
* and is not needed when returning base (i.e. scalar) data types.
90+
*/
7591
TupleTableSlot *slot;
7692

77-
/* pointer to misc context info */
78-
void *fctx;
79-
80-
/* pointer to struct containing arrays of attribute type input metainfo */
93+
/*
94+
* OPTIONAL pointer to misc user provided context info
95+
*
96+
* user_fctx is for use as a pointer to your own struct to retain
97+
* arbitrary context information between calls for your function.
98+
*/
99+
void *user_fctx;
100+
101+
/*
102+
* OPTIONAL pointer to struct containing arrays of attribute type input
103+
* metainfo
104+
*
105+
* attinmeta is for use when returning tuples (i.e. composite data types)
106+
* and is not needed when returning base (i.e. scalar) data types. It
107+
* is ONLY needed if you intend to use BuildTupleFromCStrings() to create
108+
* the return tuple.
109+
*/
81110
AttInMetadata *attinmeta;
82111

83-
/* memory context used to initialize structure */
112+
/*
113+
* memory context used to initialize structure
114+
*
115+
* fmctx is set by SRF_FIRSTCALL_INIT() for you, and used by
116+
* SRF_RETURN_DONE() for cleanup. It is primarily for internal use
117+
* by the API.
118+
*/
84119
MemoryContext fmctx;
85120

86121
} FuncCallContext;
@@ -137,7 +172,7 @@ extern void get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem);
137172
* Datum result;
138173
* <user defined declarations>
139174
*
140-
* if(SRF_IS_FIRSTPASS())
175+
* if(SRF_IS_FIRSTCALL())
141176
* {
142177
* <user defined code>
143178
* funcctx = SRF_FIRSTCALL_INIT();
@@ -148,7 +183,7 @@ extern void get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem);
148183
* <user defined code>
149184
* }
150185
* <user defined code>
151-
* funcctx = SRF_PERCALL_SETUP(funcctx);
186+
* funcctx = SRF_PERCALL_SETUP();
152187
* <user defined code>
153188
*
154189
* if (funcctx->call_cntr < funcctx->max_calls)
@@ -167,14 +202,12 @@ extern void get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem);
167202

168203
/* from funcapi.c */
169204
extern FuncCallContext *init_MultiFuncCall(PG_FUNCTION_ARGS);
205+
extern FuncCallContext *per_MultiFuncCall(PG_FUNCTION_ARGS);
170206
extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx);
171207

172-
#define SRF_IS_FIRSTPASS() (fcinfo->flinfo->fn_extra == NULL)
208+
#define SRF_IS_FIRSTCALL() (fcinfo->flinfo->fn_extra == NULL)
173209
#define SRF_FIRSTCALL_INIT() init_MultiFuncCall(fcinfo)
174-
#define SRF_PERCALL_SETUP(_funcctx) \
175-
fcinfo->flinfo->fn_extra; \
176-
if(_funcctx->slot != NULL) \
177-
ExecClearTuple(_funcctx->slot)
210+
#define SRF_PERCALL_SETUP() per_MultiFuncCall(fcinfo)
178211
#define SRF_RETURN_NEXT(_funcctx, _result) \
179212
do { \
180213
ReturnSetInfo *rsi; \

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy